1#************************************************************** 2# 3# Licensed to the Apache Software Foundation (ASF) under one 4# or more contributor license agreements. See the NOTICE file 5# distributed with this work for additional information 6# regarding copyright ownership. The ASF licenses this file 7# to you under the Apache License, Version 2.0 (the 8# "License"); you may not use this file except in compliance 9# with the License. You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, 14# software distributed under the License is distributed on an 15# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16# KIND, either express or implied. See the License for the 17# specific language governing permissions and limitations 18# under the License. 19# 20#************************************************************** 21 22 23 24package installer::windows::idtglobal; 25 26use Cwd; 27use installer::converter; 28use installer::existence; 29use installer::exiter; 30use installer::files; 31use installer::globals; 32use installer::pathanalyzer; 33use installer::remover; 34use installer::scriptitems; 35use installer::systemactions; 36use installer::windows::language; 37 38############################################################## 39# Shorten the gid for a feature. 40# Attention: Maximum length is 38 41############################################################## 42 43sub shorten_feature_gid 44{ 45 my ($stringref) = @_; 46 47 $$stringref =~ s/gid_Module_/gm_/; 48 $$stringref =~ s/_Extension_/_ex_/; 49 $$stringref =~ s/_Root_/_r_/; 50 $$stringref =~ s/_Prg_/_p_/; 51 $$stringref =~ s/_Optional_/_o_/; 52 $$stringref =~ s/_Tools_/_tl_/; 53 $$stringref =~ s/_Wrt_Flt_/_w_f_/; 54 $$stringref =~ s/_Javafilter_/_jf_/; 55 $$stringref =~ s/_Productivity_/_pr_/; 56 $$stringref =~ s/_Replacement_/_rpl_/; 57} 58 59=head2 create_shortend_feature_gid ($feature_name) 60 61 This is a side effect free version of shorten_feature_gid. 62 The shortened feature name is returned instead of overwriting the given name. 63 64=cut 65sub create_shortend_feature_gid ($) 66{ 67 my ($feature_name) = @_; 68 shorten_feature_gid(\$feature_name); 69 return $feature_name; 70} 71 72############################################ 73# Getting the next free number, that 74# can be added. 75# Sample: 01-44-~1.DAT, 01-44-~2.DAT, ... 76############################################ 77 78sub get_next_free_number 79{ 80 my ($name, $shortnamesref) = @_; 81 82 my $counter = 0; 83 my $dontsave = 0; 84 my $alreadyexists; 85 my ($newname, $shortname); 86 87 do 88 { 89 $alreadyexists = 0; 90 $counter++; 91 $newname = $name . $counter; 92 93 for ( my $i = 0; $i <= $#{$shortnamesref}; $i++ ) 94 { 95 $shortname = ${$shortnamesref}[$i]; 96 97 if ( uc($shortname) eq uc($newname) ) # case insensitive 98 { 99 $alreadyexists = 1; 100 last; 101 } 102 } 103 } 104 until (!($alreadyexists)); 105 106 if (( $counter > 9 ) && ( length($name) > 6 )) { $dontsave = 1; } 107 if (( $counter > 99 ) && ( length($name) > 5 )) { $dontsave = 1; } 108 109 if (!($dontsave)) 110 { 111 push(@{$shortnamesref}, $newname); # adding the new shortname to the array of shortnames 112 } 113 114 return $counter 115} 116 117############################################ 118# Getting the next free number, that 119# can be added. 120# Sample: 01-44-~1.DAT, 01-44-~2.DAT, ... 121############################################ 122 123sub get_next_free_number_with_hash 124{ 125 my ($name, $shortnamesref, $ext) = @_; 126 127 my $counter = 0; 128 my $dontsave = 0; 129 my $saved = 0; 130 my $alreadyexists; 131 my ($newname, $shortname); 132 133 do 134 { 135 $alreadyexists = 0; 136 $counter++; 137 $newname = $name . $counter; 138 $newname = uc($newname); # case insensitive, always upper case 139 if ( exists($shortnamesref->{$newname}) || 140 exists($installer::globals::savedrev83mapping{$newname.$ext}) ) 141 { 142 $alreadyexists = 1; 143 } 144 } 145 until (!($alreadyexists)); 146 147 if (( $counter > 9 ) && ( length($name) > 6 )) { $dontsave = 1; } 148 if (( $counter > 99 ) && ( length($name) > 5 )) { $dontsave = 1; } 149 150 if (!($dontsave)) 151 { 152 # push(@{$shortnamesref}, $newname); # adding the new shortname to the array of shortnames 153 $shortnamesref->{$newname} = 1; # adding the new shortname to the array of shortnames, always uppercase 154 $saved = 1; 155 } 156 157 return ( $counter, $saved ) 158} 159 160######################################### 161# 8.3 for filenames and directories 162######################################### 163 164sub make_eight_three_conform 165{ 166 my ($inputstring, $pattern, $shortnamesref) = @_; 167 168 # all shortnames are collected in $shortnamesref, because of uniqueness 169 170 my ($name, $namelength, $number); 171 my $conformstring = ""; 172 my $changed = 0; 173 174 if (( $inputstring =~ /^\s*(.*?)\.(.*?)\s*$/ ) && ( $pattern eq "file" )) # files with a dot 175 { 176 $name = $1; 177 my $extension = $2; 178 179 $namelength = length($name); 180 my $extensionlength = length($extension); 181 182 if ( $extensionlength > 3 ) 183 { 184 # simply taking the first three letters 185 $extension = substr($extension, 0, 3); # name, offset, length 186 } 187 188 # Attention: readme.html -> README~1.HTM 189 190 if (( $namelength > 8 ) || ( $extensionlength > 3 )) 191 { 192 # taking the first six letters 193 $name = substr($name, 0, 6); # name, offset, length 194 $name =~ s/\s*$//; # removing ending whitespaces 195 $name = $name . "\~"; 196 $number = get_next_free_number($name, $shortnamesref); 197 198 # if $number>9 the new name would be "abcdef~10.xyz", which is 9+3, and therefore not allowed 199 200 if ( $number > 9 ) 201 { 202 $name = substr($name, 0, 5); # name, offset, length 203 $name =~ s/\s*$//; # removing ending whitespaces 204 $name = $name . "\~"; 205 $number = get_next_free_number($name, $shortnamesref); 206 207 if ( $number > 99 ) 208 { 209 $name = substr($name, 0, 4); # name, offset, length 210 $name =~ s/\s*$//; # removing ending whitespaces 211 $name = $name . "\~"; 212 $number = get_next_free_number($name, $shortnamesref); 213 } 214 } 215 216 $name = $name . "$number"; 217 218 $changed = 1; 219 } 220 221 $conformstring = $name . "\." . $extension; 222 223 if ( $changed ) { $conformstring= uc($conformstring); } 224 } 225 else # no dot in filename or directory (also used for shortcuts) 226 { 227 $name = $inputstring; 228 $namelength = length($name); 229 230 if ( $namelength > 8 ) 231 { 232 # taking the first six letters 233 $name = substr($name, 0, 6); # name, offset, length 234 $name =~ s/\s*$//; # removing ending whitespaces 235 $name = $name . "\~"; 236 $number = get_next_free_number($name, $shortnamesref); 237 238 # if $number>9 the new name would be "abcdef~10.xyz", which is 9+3, and therefore not allowed 239 240 if ( $number > 9 ) 241 { 242 $name = substr($name, 0, 5); # name, offset, length 243 $name =~ s/\s*$//; # removing ending whitespaces 244 $name = $name . "\~"; 245 $number = get_next_free_number($name, $shortnamesref); 246 247 if ( $number > 99 ) 248 { 249 $name = substr($name, 0, 4); # name, offset, length 250 $name =~ s/\s*$//; # removing ending whitespaces 251 $name = $name . "\~"; 252 $number = get_next_free_number($name, $shortnamesref); 253 } 254 } 255 256 $name = $name . "$number"; 257 $changed = 1; 258 if ( $pattern eq "dir" ) { $name =~ s/\./\_/g; } # in directories replacing "." with "_" 259 } 260 261 $conformstring = $name; 262 263 if ( $changed ) { $conformstring = uc($name); } 264 } 265 266 return $conformstring; 267} 268 269######################################### 270# 8.3 for filenames and directories 271# $shortnamesref is a hash in this case 272# -> performance reasons 273######################################### 274 275sub make_eight_three_conform_with_hash 276{ 277 my ($inputstring, $pattern, $shortnamesref) = @_; 278 279 # all shortnames are collected in $shortnamesref, because of uniqueness (a hash!) 280 281 my ($name, $namelength, $number); 282 my $conformstring = ""; 283 my $changed = 0; 284 my $saved; 285 286 # if (( $inputstring =~ /^\s*(.*?)\.(.*?)\s*$/ ) && ( $pattern eq "file" )) # files with a dot 287 if (( $inputstring =~ /^\s*(.*)\.(.*?)\s*$/ ) && ( $pattern eq "file" )) # files with a dot 288 { 289 # extension has to be non-greedy, but name is. This is important to find the last dot in the filename 290 $name = $1; 291 my $extension = $2; 292 293 if ( $name =~ /^\s*(.*?)\s*$/ ) { $name = $1; } # now the name is also non-greedy 294 $name =~ s/\.//g; # no dots in 8+3 conform filename 295 296 $namelength = length($name); 297 my $extensionlength = length($extension); 298 299 if ( $extensionlength > 3 ) 300 { 301 # simply taking the first three letters 302 $extension = substr($extension, 0, 3); # name, offset, length 303 $changed = 1; 304 } 305 306 # Attention: readme.html -> README~1.HTM 307 308 if (( $namelength > 8 ) || ( $extensionlength > 3 )) 309 { 310 # taking the first six letters, if filename is longer than 6 characters 311 if ( $namelength > 6 ) 312 { 313 $name = substr($name, 0, 6); # name, offset, length 314 $name =~ s/\s*$//; # removing ending whitespaces 315 $name = $name . "\~"; 316 ($number, $saved) = get_next_free_number_with_hash($name, $shortnamesref, '.'.uc($extension)); 317 318 # if $number>9 the new name would be "abcdef~10.xyz", which is 9+3, and therefore not allowed 319 320 if ( ! $saved ) 321 { 322 $name = substr($name, 0, 5); # name, offset, length 323 $name =~ s/\s*$//; # removing ending whitespaces 324 $name = $name . "\~"; 325 ($number, $saved) = get_next_free_number_with_hash($name, $shortnamesref, '.'.uc($extension)); 326 327 # if $number>99 the new name would be "abcde~100.xyz", which is 9+3, and therefore not allowed 328 329 if ( ! $saved ) 330 { 331 $name = substr($name, 0, 4); # name, offset, length 332 $name =~ s/\s*$//; # removing ending whitespaces 333 $name = $name . "\~"; 334 ($number, $saved) = get_next_free_number_with_hash($name, $shortnamesref, '.'.uc($extension)); 335 336 if ( ! $saved ) 337 { 338 installer::exiter::exit_program("ERROR: Could not set 8+3 conform name for $inputstring !", "make_eight_three_conform_with_hash"); 339 } 340 } 341 } 342 343 $name = $name . "$number"; 344 $changed = 1; 345 } 346 } 347 348 $conformstring = $name . "\." . $extension; 349 350 if ( $changed ) { $conformstring= uc($conformstring); } 351 } 352 else # no dot in filename or directory (also used for shortcuts) 353 { 354 $name = $inputstring; 355 $namelength = length($name); 356 357 if ( $namelength > 8 ) 358 { 359 # taking the first six letters 360 $name = substr($name, 0, 6); # name, offset, length 361 $name =~ s/\s*$//; # removing ending whitespaces 362 $name = $name . "\~"; 363 ( $number, $saved ) = get_next_free_number_with_hash($name, $shortnamesref, ''); 364 365 # if $number>9 the new name would be "abcdef~10", which is 9+0, and therefore not allowed 366 367 if ( ! $saved ) 368 { 369 $name = substr($name, 0, 5); # name, offset, length 370 $name =~ s/\s*$//; # removing ending whitespaces 371 $name = $name . "\~"; 372 ( $number, $saved ) = get_next_free_number_with_hash($name, $shortnamesref, ''); 373 374 # if $number>99 the new name would be "abcde~100", which is 9+0, and therefore not allowed 375 376 if ( ! $saved ) 377 { 378 $name = substr($name, 0, 4); # name, offset, length 379 $name =~ s/\s*$//; # removing ending whitespaces 380 $name = $name . "\~"; 381 ( $number, $saved ) = get_next_free_number_with_hash($name, $shortnamesref, ''); 382 383 if ( ! $saved ) { installer::exiter::exit_program("ERROR: Could not set 8+3 conform name for $inputstring !", "make_eight_three_conform_with_hash"); } 384 } 385 } 386 387 $name = $name . "$number"; 388 $changed = 1; 389 if ( $pattern eq "dir" ) { $name =~ s/\./\_/g; } # in directories replacing "." with "_" 390 } 391 392 $conformstring = $name; 393 394 if ( $changed ) { $conformstring = uc($name); } 395 } 396 397 return $conformstring; 398} 399 400######################################### 401# Writing the header for idt files 402######################################### 403 404sub write_idt_header 405{ 406 my ($idtref, $definestring) = @_; 407 408 my $oneline; 409 410 if ( $definestring eq "file" ) 411 { 412 $oneline = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"; 413 push(@{$idtref}, $oneline); 414 $oneline = "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"; 415 push(@{$idtref}, $oneline); 416 $oneline = "File\tFile\n"; 417 push(@{$idtref}, $oneline); 418 } 419 420 if ( $definestring eq "filehash" ) 421 { 422 $oneline = "File_\tOptions\tHashPart1\tHashPart2\tHashPart3\tHashPart4\n"; 423 push(@{$idtref}, $oneline); 424 $oneline = "s72\ti2\ti4\ti4\ti4\ti4\n"; 425 push(@{$idtref}, $oneline); 426 $oneline = "MsiFileHash\tFile_\n"; 427 push(@{$idtref}, $oneline); 428 } 429 430 if ( $definestring eq "directory" ) 431 { 432 $oneline = "Directory\tDirectory_Parent\tDefaultDir\n"; 433 push(@{$idtref}, $oneline); 434 $oneline = "s72\tS72\tl255\n"; 435 push(@{$idtref}, $oneline); 436 $oneline = "Directory\tDirectory\n"; 437 push(@{$idtref}, $oneline); 438 } 439 440 if ( $definestring eq "component" ) 441 { 442 $oneline = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"; 443 push(@{$idtref}, $oneline); 444 $oneline = "s72\tS38\ts72\ti2\tS255\tS72\n"; 445 push(@{$idtref}, $oneline); 446 $oneline = "Component\tComponent\n"; 447 push(@{$idtref}, $oneline); 448 } 449 450 if ( $definestring eq "feature" ) 451 { 452 $oneline = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"; 453 push(@{$idtref}, $oneline); 454 $oneline = "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"; 455 push(@{$idtref}, $oneline); 456 $oneline = "WINDOWSENCODINGTEMPLATE\tFeature\tFeature\n"; 457 push(@{$idtref}, $oneline); 458 } 459 460 if ( $definestring eq "featurecomponent" ) 461 { 462 $oneline = "Feature_\tComponent_\n"; 463 push(@{$idtref}, $oneline); 464 $oneline = "s38\ts72\n"; 465 push(@{$idtref}, $oneline); 466 $oneline = "FeatureComponents\tFeature_\tComponent_\n"; 467 push(@{$idtref}, $oneline); 468 } 469 470 if ( $definestring eq "media" ) 471 { 472 $oneline = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"; 473 push(@{$idtref}, $oneline); 474 $oneline = "i2\ti2\tL64\tS255\tS32\tS72\n"; 475 push(@{$idtref}, $oneline); 476 $oneline = "Media\tDiskId\n"; 477 push(@{$idtref}, $oneline); 478 } 479 480 if ( $definestring eq "font" ) 481 { 482 $oneline = "File_\tFontTitle\n"; 483 push(@{$idtref}, $oneline); 484 $oneline = "s72\tS128\n"; 485 push(@{$idtref}, $oneline); 486 $oneline = "Font\tFile_\n"; 487 push(@{$idtref}, $oneline); 488 } 489 490 if ( $definestring eq "shortcut" ) 491 { 492 $oneline = "Shortcut\tDirectory_\tName\tComponent_\tTarget\tArguments\tDescription\tHotkey\tIcon_\tIconIndex\tShowCmd\tWkDir\n"; 493 push(@{$idtref}, $oneline); 494 $oneline = "s72\ts72\tl128\ts72\ts72\tS255\tL255\tI2\tS72\tI2\tI2\tS72\n"; 495 push(@{$idtref}, $oneline); 496 $oneline = "WINDOWSENCODINGTEMPLATE\tShortcut\tShortcut\n"; 497 push(@{$idtref}, $oneline); 498 } 499 500 if ( $definestring eq "registry" ) 501 { 502 $oneline = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"; 503 push(@{$idtref}, $oneline); 504 $oneline = "s72\ti2\tl255\tL255\tL0\ts72\n"; 505 push(@{$idtref}, $oneline); 506 $oneline = "Registry\tRegistry\n"; 507 push(@{$idtref}, $oneline); 508 } 509 510 if ( $definestring eq "reg64" ) 511 { 512 $oneline = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"; 513 push(@{$idtref}, $oneline); 514 $oneline = "s72\ti2\tl255\tL255\tL0\ts72\n"; 515 push(@{$idtref}, $oneline); 516 $oneline = "Reg64\tRegistry\n"; 517 push(@{$idtref}, $oneline); 518 } 519 520 if ( $definestring eq "createfolder" ) 521 { 522 $oneline = "Directory_\tComponent_\n"; 523 push(@{$idtref}, $oneline); 524 $oneline = "s72\ts72\n"; 525 push(@{$idtref}, $oneline); 526 $oneline = "CreateFolder\tDirectory_\tComponent_\n"; 527 push(@{$idtref}, $oneline); 528 } 529 530 if ( $definestring eq "removefile" ) 531 { 532 $oneline = "FileKey\tComponent_\tFileName\tDirProperty\tInstallMode\n"; 533 push(@{$idtref}, $oneline); 534 $oneline = "s72\ts72\tL255\ts72\ti2\n"; 535 push(@{$idtref}, $oneline); 536 $oneline = "RemoveFile\tFileKey\n"; 537 push(@{$idtref}, $oneline); 538 } 539 540 if ( $definestring eq "upgrade" ) 541 { 542 $oneline = "UpgradeCode\tVersionMin\tVersionMax\tLanguage\tAttributes\tRemove\tActionProperty\n"; 543 push(@{$idtref}, $oneline); 544 $oneline = "s38\tS20\tS20\tS255\ti4\tS255\ts72\n"; 545 push(@{$idtref}, $oneline); 546 $oneline = "Upgrade\tUpgradeCode\tVersionMin\tVersionMax\tLanguage\tAttributes\n"; 547 push(@{$idtref}, $oneline); 548 } 549 550 if ( $definestring eq "icon" ) 551 { 552 $oneline = "Name\tData\n"; 553 push(@{$idtref}, $oneline); 554 $oneline = "s72\tv0\n"; 555 push(@{$idtref}, $oneline); 556 $oneline = "Icon\tName\n"; 557 push(@{$idtref}, $oneline); 558 } 559 560 if ( $definestring eq "inifile" ) 561 { 562 $oneline = "IniFile\tFileName\tDirProperty\tSection\tKey\tValue\tAction\tComponent_\n"; 563 push(@{$idtref}, $oneline); 564 $oneline = "s72\tl255\tS72\tl96\tl128\tl255\ti2\ts72\n"; 565 push(@{$idtref}, $oneline); 566 $oneline = "IniFile\tIniFile\n"; 567 push(@{$idtref}, $oneline); 568 } 569 570 if ( $definestring eq "selfreg" ) 571 { 572 $oneline = "File_\tCost\n"; 573 push(@{$idtref}, $oneline); 574 $oneline = "s72\tI2\n"; 575 push(@{$idtref}, $oneline); 576 $oneline = "SelfReg\tFile_\n"; 577 push(@{$idtref}, $oneline); 578 } 579 580 if ( $definestring eq "msiassembly" ) 581 { 582 $oneline = "Component_\tFeature_\tFile_Manifest\tFile_Application\tAttributes\n"; 583 push(@{$idtref}, $oneline); 584 $oneline = "s72\ts38\tS72\tS72\tI2\n"; 585 push(@{$idtref}, $oneline); 586 $oneline = "MsiAssembly\tComponent_\n"; 587 push(@{$idtref}, $oneline); 588 } 589 590 if ( $definestring eq "msiassemblyname" ) 591 { 592 $oneline = "Component_\tName\tValue\n"; 593 push(@{$idtref}, $oneline); 594 $oneline = "s72\ts255\ts255\n"; 595 push(@{$idtref}, $oneline); 596 $oneline = "MsiAssemblyName\tComponent_\tName\n"; 597 push(@{$idtref}, $oneline); 598 } 599 600 if ( $definestring eq "appsearch" ) 601 { 602 $oneline = "Property\tSignature_\n"; 603 push(@{$idtref}, $oneline); 604 $oneline = "s72\ts72\n"; 605 push(@{$idtref}, $oneline); 606 $oneline = "AppSearch\tProperty\tSignature_\n"; 607 push(@{$idtref}, $oneline); 608 } 609 610 if ( $definestring eq "reglocat" ) 611 { 612 $oneline = "Signature_\tRoot\tKey\tName\tType\n"; 613 push(@{$idtref}, $oneline); 614 $oneline = "s72\ti2\ts255\tS255\tI2\n"; 615 push(@{$idtref}, $oneline); 616 $oneline = "RegLocator\tSignature_\n"; 617 push(@{$idtref}, $oneline); 618 } 619 620 if ( $definestring eq "signatur" ) 621 { 622 $oneline = "Signature\tFileName\tMinVersion\tMaxVersion\tMinSize\tMaxSize\tMinDate\tMaxDate\tLanguages\n"; 623 push(@{$idtref}, $oneline); 624 $oneline = "s72\ts255\tS20\tS20\tI4\tI4\tI4\tI4\tS255\n"; 625 push(@{$idtref}, $oneline); 626 $oneline = "Signature\tSignature\n"; 627 push(@{$idtref}, $oneline); 628 } 629 630} 631 632############################################################## 633# Returning the name of the rranslation file for a 634# given language. 635# Sample: "01" oder "en-US" -> "1033.txt" 636############################################################## 637 638sub get_languagefilename 639{ 640 my ($idtfilename, $basedir) = @_; 641 642 # $idtfilename =~ s/\.idt/\.ulf/; 643 $idtfilename =~ s/\.idt/\.mlf/; 644 645 my $languagefilename = $basedir . $installer::globals::separator . $idtfilename; 646 647 return $languagefilename; 648} 649 650############################################################## 651# Returning the complete block in all languages 652# for a specified string 653############################################################## 654 655sub get_language_block_from_language_file 656{ 657 my ($searchstring, $languagefile) = @_; 658 659 my @language_block = (); 660 661 for ( my $i = 0; $i <= $#{$languagefile}; $i++ ) 662 { 663 if ( ${$languagefile}[$i] =~ /^\s*\[\s*$searchstring\s*\]\s*$/ ) 664 { 665 my $counter = $i; 666 667 push(@language_block, ${$languagefile}[$counter]); 668 $counter++; 669 670 while (( $counter <= $#{$languagefile} ) && (!( ${$languagefile}[$counter] =~ /^\s*\[/ ))) 671 { 672 push(@language_block, ${$languagefile}[$counter]); 673 $counter++; 674 } 675 676 last; 677 } 678 } 679 680 return \@language_block; 681} 682 683############################################################## 684# Returning a specific language string from the block 685# of all translations 686############################################################## 687 688sub get_language_string_from_language_block 689{ 690 my ($language_block, $language, $oldstring) = @_; 691 692 my $newstring = ""; 693 694 for ( my $i = 0; $i <= $#{$language_block}; $i++ ) 695 { 696 if ( ${$language_block}[$i] =~ /^\s*$language\s*\=\s*\"(.*)\"\s*$/ ) 697 { 698 $newstring = $1; 699 last; 700 } 701 } 702 703 if ( $newstring eq "" ) 704 { 705 $language = "en-US"; # defaulting to english 706 707 for ( my $i = 0; $i <= $#{$language_block}; $i++ ) 708 { 709 if ( ${$language_block}[$i] =~ /^\s*$language\s*\=\s*\"(.*)\"\s*$/ ) 710 { 711 $newstring = $1; 712 last; 713 } 714 } 715 } 716 717 return $newstring; 718} 719 720############################################################## 721# Returning a specific code from the block 722# of all codes. No defaulting to english! 723############################################################## 724 725sub get_code_from_code_block 726{ 727 my ($codeblock, $language) = @_; 728 729 my $newstring = ""; 730 731 for ( my $i = 0; $i <= $#{$codeblock}; $i++ ) 732 { 733 if ( ${$codeblock}[$i] =~ /^\s*$language\s*\=\s*\"(.*)\"\s*$/ ) 734 { 735 $newstring = $1; 736 last; 737 } 738 } 739 740 return $newstring; 741} 742 743############################################################## 744# Translating an idt file 745############################################################## 746 747sub translate_idtfile 748{ 749 my ($idtfile, $languagefile, $onelanguage) = @_; 750 751 for ( my $i = 0; $i <= $#{$idtfile}; $i++ ) 752 { 753 my @allstrings = (); 754 755 my $oneline = ${$idtfile}[$i]; 756 757 while ( $oneline =~ /\b(OOO_\w+)\b/ ) 758 { 759 my $replacestring = $1; 760 push(@allstrings, $replacestring); 761 $oneline =~ s/$replacestring//; 762 } 763 764 my $oldstring; 765 766 foreach $oldstring (@allstrings) 767 { 768 my $language_block = get_language_block_from_language_file($oldstring, $languagefile); 769 my $newstring = get_language_string_from_language_block($language_block, $onelanguage, $oldstring); 770 771 # if (!( $newstring eq "" )) { ${$idtfile}[$i] =~ s/$oldstring/$newstring/; } 772 ${$idtfile}[$i] =~ s/$oldstring/$newstring/; # always substitute, even if $newstring eq "" (there are empty strings for control.idt) 773 } 774 } 775} 776 777############################################################## 778# Copying all needed files to create a msi database 779# into one language specific directory 780############################################################## 781 782sub prepare_language_idt_directory ($$$$$$$) 783{ 784 my ($destinationdir, $newidtdir, $onelanguage, $filesref, $iconfilecollector, $binarytablefiles, $allvariables) = @_; 785 786 # Copying all idt-files from the source $installer::globals::idttemplatepath to the destination $destinationdir 787 # Copying all files in the subdirectory "Binary" 788 # Copying all files in the subdirectory "Icon" 789 790 my $infoline = ""; 791 792 installer::systemactions::copy_directory($installer::globals::idttemplatepath, $destinationdir); 793 794 if ( -d $installer::globals::idttemplatepath . $installer::globals::separator . "Binary") 795 { 796 installer::systemactions::create_directory($destinationdir . $installer::globals::separator . "Binary"); 797 installer::systemactions::copy_directory( 798 $installer::globals::idttemplatepath . $installer::globals::separator . "Binary", 799 $destinationdir . $installer::globals::separator . "Binary"); 800 801 if ((( $installer::globals::patch ) && ( $allvariables->{'WINDOWSPATCHBITMAPDIRECTORY'} )) || ( $allvariables->{'WINDOWSBITMAPDIRECTORY'} )) 802 { 803 my $bitmapdir = ""; 804 if ( $allvariables->{'WINDOWSPATCHBITMAPDIRECTORY'} ) 805 { 806 $bitmapdir = $allvariables->{'WINDOWSPATCHBITMAPDIRECTORY'}; 807 } 808 if ( $allvariables->{'WINDOWSBITMAPDIRECTORY'} ) 809 { 810 $bitmapdir = $allvariables->{'WINDOWSBITMAPDIRECTORY'}; 811 } 812 813 my $newsourcedir = $installer::globals::unpackpath . $installer::globals::separator . $bitmapdir; # path setting in list file dependent from unpackpath !? 814 $installer::logger::Lang->printf("\n"); 815 $installer::logger::Lang->printf( 816 "Overwriting files in directory \"%s%sBinary\" with files from directory \"%s\".\n", 817 $destinationdir, 818 $installer::globals::separator, 819 $newsourcedir); 820 if ( ! -d $newsourcedir ) 821 { 822 my $currentdir = cwd(); 823 installer::exiter::exit_program( 824 "ERROR: Directory $newsourcedir does not exist! Current directory is: $currentdir", 825 "prepare_language_idt_directory"); 826 } 827 installer::systemactions::copy_directory( 828 $newsourcedir, 829 $destinationdir . $installer::globals::separator . "Binary"); 830 } 831 } 832 833 installer::systemactions::create_directory($destinationdir . $installer::globals::separator . "Icon"); 834 835 if ( -d $installer::globals::idttemplatepath . $installer::globals::separator . "Icon") 836 { 837 installer::systemactions::copy_directory( 838 $installer::globals::idttemplatepath . $installer::globals::separator . "Icon", 839 $destinationdir . $installer::globals::separator . "Icon"); 840 } 841 842 # Copying all files in $iconfilecollector, that describe icons of folderitems 843 844 for ( my $i = 0; $i <= $#{$iconfilecollector}; $i++ ) 845 { 846 my $iconfilename = ${$iconfilecollector}[$i]; 847 installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$iconfilename); 848 installer::systemactions::copy_one_file( 849 ${$iconfilecollector}[$i], 850 $destinationdir . $installer::globals::separator . "Icon" . $installer::globals::separator . $iconfilename); 851 } 852 853 # Copying all files in $binarytablefiles in the binary directory 854 855 foreach my $binaryfile (@$binarytablefiles) 856 { 857 my $binaryfilepath = $binaryfile->{'sourcepath'}; 858 my $binaryfilename = $binaryfilepath; 859 $installer::logger::Lang->printf("copying binary file %s to %s\n", 860 $binaryfilepath, 861 $binaryfilename); 862 installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$binaryfilename); 863 installer::systemactions::copy_one_file( 864 $binaryfilepath, 865 $destinationdir . $installer::globals::separator . "Binary" . $installer::globals::separator . $binaryfilename); 866 } 867 868 # Copying all new created and language independent idt-files to the destination $destinationdir. 869 # Example: "File.idt" 870 871 installer::systemactions::copy_directory_with_fileextension($newidtdir, $destinationdir, "idt"); 872 873 # Copying all new created and language dependent idt-files to the destination $destinationdir. 874 # Example: "Feature.idt.01" 875 876 installer::systemactions::copy_directory_with_fileextension($newidtdir, $destinationdir, $onelanguage); 877 installer::systemactions::rename_files_with_fileextension($destinationdir, $onelanguage); 878 879} 880 881############################################################## 882# Returning the source path of the rtf licensefile for 883# a specified language 884############################################################## 885 886sub get_rtflicensefilesource 887{ 888 my ($language, $includepatharrayref) = @_; 889 890 my $licensefilename = "license_" . $language . ".rtf"; 891 892 my $sourcefileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$licensefilename, $includepatharrayref, 1); 893 894 if ($$sourcefileref eq "") { installer::exiter::exit_program("ERROR: Could not find $licensefilename!", "get_rtflicensefilesource"); } 895 896 $installer::logger::Lang->printf("Using licensefile: %s\n", $$sourcefileref); 897 898 return $$sourcefileref; 899} 900 901############################################################## 902# Returning the source path of the licensefile for 903# a specified language 904############################################################## 905 906sub get_licensefilesource 907{ 908 my ($language, $filesref) = @_; 909 910 my $licensefilename = "license_" . $language . ".txt"; 911 my $sourcepath = ""; 912 my $foundlicensefile = 0; 913 914 for ( my $i = 0; $i <= $#{$filesref}; $i++ ) 915 { 916 my $onefile = ${$filesref}[$i]; 917 my $filename = $onefile->{'Name'}; 918 919 if ($filename eq $licensefilename) 920 { 921 $sourcepath = $onefile->{'sourcepath'}; 922 $foundlicensefile = 1; 923 last; 924 } 925 } 926 927 if ( ! $foundlicensefile ) { installer::exiter::exit_program("ERROR: Did not find file $licensefilename in file collector!", "get_licensefilesource"); } 928 929 return $sourcepath; 930} 931 932############################################################## 933# A simple converter to create the license text 934# in rtf format 935############################################################## 936 937sub get_rtf_licensetext 938{ 939 my ($licensefile) = @_; 940 941 # A very simple rtf converter 942 943 # The static header 944 945 my $rtf_licensetext = '{\rtf1\ansi\deff0'; 946 $rtf_licensetext = $rtf_licensetext . '{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}}'; 947 $rtf_licensetext = $rtf_licensetext . '{\colortbl\red0\green0\blue0;\red255\green255\blue255;\red128\green128\blue128;}'; 948 $rtf_licensetext = $rtf_licensetext . '{\stylesheet{\s1\snext1 Standard;}}'; 949 $rtf_licensetext = $rtf_licensetext . '{\info{\comment StarWriter}{\vern5690}}\deftab709'; 950 $rtf_licensetext = $rtf_licensetext . '{\*\pgdsctbl'; 951 $rtf_licensetext = $rtf_licensetext . '{\pgdsc0\pgdscuse195\pgwsxn11905\pghsxn16837\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\pgdscnxt0 Standard;}}'; 952 $rtf_licensetext = $rtf_licensetext . '\paperh16837\paperw11905\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\pgwsxn11905\pghsxn16837\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc'; 953 $rtf_licensetext = $rtf_licensetext . '\pard\plain \s1'; 954 955 for ( my $i = 0; $i <= $#{$licensefile}; $i++ ) 956 { 957 my $oneline = ${$licensefile}[$i]; 958 # if ( $oneline =~ /^\s*$/ ) { $oneline = '\par'; } # empty lines 959 960 if ( $i == 0 ) { $oneline =~ s/^\W*//; } 961 962 $oneline =~ s/\t/ /g; # no tabs allowed, converting to four spaces 963 $oneline =~ s/\n$//g; # no newline at line end 964 965# $oneline =~ s/�/\\\'e4/g; # converting "�" 966# $oneline =~ s/�/\\\'f6/g; # converting "�" 967# $oneline =~ s/�/\\\'fc/g; # converting "�" 968# $oneline =~ s/�/\\\'df/g; # converting "�" 969 970 # german replacements 971 972 $oneline =~ s/\�\�/\\\'c4/g; # converting "�" 973 $oneline =~ s/\�\�/\\\'d6/g; # converting "�" 974 $oneline =~ s/\�\�/\\\'dc/g; # converting "�" 975 $oneline =~ s/\�\�/\\\'e4/g; # converting "�" 976 $oneline =~ s/\�\�/\\\'f6/g; # converting "�" 977 $oneline =~ s/\�\�/\\\'fc/g; # converting "�" 978 $oneline =~ s/\�\�/\\\'df/g; # converting "�" 979 980 # french replacements 981 982 $oneline =~ s/\�\�/\\\'c9/g; 983 $oneline =~ s/\�\�/\\\'c0/g; 984 $oneline =~ s/\�\�/\\\'ab/g; 985 $oneline =~ s/\�\�/\\\'bb/g; 986 $oneline =~ s/\�\�/\\\'e9/g; 987 $oneline =~ s/\�\�/\\\'e8/g; 988 $oneline =~ s/\�\�/\\\'e0/g; 989 $oneline =~ s/\�\�/\\\'f4/g; 990 $oneline =~ s/\�\�/\\\'e7/g; 991 $oneline =~ s/\�\�/\\\'ea/g; 992 $oneline =~ s/\�\�/\\\'ca/g; 993 $oneline =~ s/\�\�/\\\'fb/g; 994 $oneline =~ s/\�\�/\\\'f9/g; 995 $oneline =~ s/\�\�/\\\'ee/g; 996 997 # quotation marks 998 999 $oneline =~ s/\�\�\�/\\\'84/g; 1000 $oneline =~ s/\�\�\�/\\ldblquote/g; 1001 $oneline =~ s/\�\�\�/\\rquote/g; 1002 1003 1004 $oneline =~ s/\�\�/\\\~/g; 1005 1006 $oneline = '\par ' . $oneline; 1007 1008 $rtf_licensetext = $rtf_licensetext . $oneline; 1009 } 1010 1011 # and the end 1012 1013 $rtf_licensetext = $rtf_licensetext . '\par \par }'; 1014 1015 return $rtf_licensetext; 1016} 1017 1018############################################################## 1019# A simple converter to create a license txt string from 1020# the rtf format 1021############################################################## 1022 1023sub make_string_licensetext 1024{ 1025 my ($licensefile) = @_; 1026 1027 my $rtf_licensetext = ""; 1028 1029 for ( my $i = 0; $i <= $#{$licensefile}; $i++ ) 1030 { 1031 my $oneline = ${$licensefile}[$i]; 1032 $oneline =~ s/\s*$//g; # no whitespace at line end 1033 1034 $rtf_licensetext = $rtf_licensetext . $oneline . " "; 1035 } 1036 1037 return $rtf_licensetext; 1038} 1039 1040############################################################## 1041# Setting the path, where the soffice.exe is installed, into 1042# the CustomAction table 1043############################################################## 1044 1045sub add_officedir_to_database 1046{ 1047 my ($basedir, $allvariables) = @_; 1048 1049 my $customactionfilename = $basedir . $installer::globals::separator . "CustomAc.idt"; 1050 1051 my $customacfile = installer::files::read_file($customactionfilename); 1052 1053 my $found = 0; 1054 1055 # Updating the values 1056 1057 if ( $installer::globals::officeinstalldirectoryset ) 1058 { 1059 $found = 0; 1060 1061 for ( my $i = 0; $i <= $#{$customacfile}; $i++ ) 1062 { 1063 if ( ${$customacfile}[$i] =~ /\bOFFICEDIRECTORYGID\b/ ) 1064 { 1065 ${$customacfile}[$i] =~ s/\bOFFICEDIRECTORYGID\b/$installer::globals::officeinstalldirectory/; 1066 $found = 1; 1067 } 1068 } 1069 1070 if (( ! $found ) && ( ! $allvariables->{'IGNOREDIRECTORYLAYER'} )) 1071 { 1072 installer::exiter::exit_program("ERROR: \"OFFICEDIRECTORYGID\" not found in \"$customactionfilename\" !", "add_officedir_to_database"); 1073 } 1074 } 1075 1076 # Saving the file 1077 1078 installer::files::save_file($customactionfilename ,$customacfile); 1079 my $infoline = "Updated idt file: $customactionfilename\n"; 1080 $installer::logger::Lang->print($infoline); 1081 1082} 1083 1084############################################################## 1085# Including the license text into the table control.idt 1086############################################################## 1087 1088sub add_licensefile_to_database 1089{ 1090 my ($licensefile, $controltable) = @_; 1091 1092 # Nine tabs before the license text and two tabs after it 1093 # The license text has to be included into the dialog 1094 # LicenseAgreement into the control Memo. 1095 1096 my $foundlicenseline = 0; 1097 my ($number, $line); 1098 1099 for ( my $i = 0; $i <= $#{$controltable}; $i++ ) 1100 { 1101 $line = ${$controltable}[$i]; 1102 1103 if ( $line =~ /^\s*\bLicenseAgreement\b\t\bMemo\t/ ) 1104 { 1105 $foundlicenseline = 1; 1106 $number = $i; 1107 last; 1108 } 1109 } 1110 1111 if (!($foundlicenseline)) 1112 { 1113 installer::exiter::exit_program("ERROR: Line for license file in Control.idt not found!", "add_licensefile_to_database"); 1114 } 1115 else 1116 { 1117 my %control = (); 1118 1119 if ( $line =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 1120 { 1121 $control{'Dialog_'} = $1; 1122 $control{'Control'} = $2; 1123 $control{'Type'} = $3; 1124 $control{'X'} = $4; 1125 $control{'Y'} = $5; 1126 $control{'Width'} = $6; 1127 $control{'Height'} = $7; 1128 $control{'Attributes'} = $8; 1129 $control{'Property'} = $9; 1130 $control{'Text'} = $10; 1131 $control{'Control_Next'} = $11; 1132 $control{'Help'} = $12; 1133 } 1134 else 1135 { 1136 installer::exiter::exit_program("ERROR: Could not split line correctly!", "add_licensefile_to_database"); 1137 } 1138 1139 # my $licensetext = get_rtf_licensetext($licensefile); 1140 my $licensetext = make_string_licensetext($licensefile); 1141 1142 $control{'Text'} = $licensetext; 1143 1144 my $newline = $control{'Dialog_'} . "\t" . $control{'Control'} . "\t" . $control{'Type'} . "\t" . 1145 $control{'X'} . "\t" . $control{'Y'} . "\t" . $control{'Width'} . "\t" . 1146 $control{'Height'} . "\t" . $control{'Attributes'} . "\t" . $control{'Property'} . "\t" . 1147 $control{'Text'} . "\t" . $control{'Control_Next'} . "\t" . $control{'Help'} . "\n"; 1148 1149 ${$controltable}[$number] = $newline 1150 } 1151} 1152 1153################################################################################################ 1154# Including the checkboxes for the language selection dialog 1155# into the table control.idt . This is only relevant for 1156# multilingual installation sets. 1157# 1158# old: 1159# LanguageSelection CheckBox1 CheckBox 22 60 15 24 3 IS1033 CheckBox2 1160# LanguageSelection Text1 Text 40 60 70 15 65539 OOO_CONTROL_LANG_1033 1161# LanguageSelection CheckBox2 CheckBox 22 90 15 24 3 IS1031 Next 1162# LanguageSelection Text2 Text 40 90 70 15 65539 OOO_CONTROL_LANG_1031 1163# new: 1164# LanguageSelection CheckBox1 CheckBox 22 60 15 24 3 IS1033 Text CheckBox2 1165# LanguageSelection CheckBox2 CheckBox 22 90 15 24 3 IS1031 Text Next 1166################################################################################################ 1167 1168sub add_language_checkboxes_to_database 1169{ 1170 my ($controltable, $languagesarrayref) = @_; 1171 1172 # for each language, two lines have to be inserted 1173 1174 for ( my $i = 0; $i <= $#{$languagesarrayref}; $i++ ) 1175 { 1176 my $last = 0; 1177 if ( $i == $#{$languagesarrayref} ) { $last = 1; } # special handling for the last 1178 1179 my $onelanguage = ${$languagesarrayref}[$i]; 1180 my $windowslanguage = installer::windows::language::get_windows_language($onelanguage); 1181 1182 # my $is_english = 0; 1183 # if ( $windowslanguage eq "1033" ) { $is_english = 1; } 1184 1185 my $checkboxattribute = "3"; 1186 # if ( $is_english ) { $checkboxattribute = "1"; } # english is not deselectable 1187 1188 my $count = $i + 1; 1189 my $nextcount = $i + 2; 1190 my $checkboxcount = "CheckBox" . $count; 1191 1192 my $multiplier = 20; 1193 my $offset = 60; 1194 if ( $#{$languagesarrayref} > 7 ) 1195 { 1196 $multiplier = 15; # smaller differences for more than 7 languages 1197 $offset = 50; # smaller offset for more than 7 languages 1198 } 1199 1200 my $yvalue = $offset + $i * $multiplier; 1201 1202 my $property = "IS" . $windowslanguage; 1203 # if ( ! exists($installer::globals::languageproperties{$property}) ) { installer::exiter::exit_program("ERROR: Could not find property \"$property\" in the list of language properties!", "add_language_checkboxes_to_database"); } 1204 1205 my $controlnext = ""; 1206 if ( $last ) { $controlnext = "Next"; } 1207 else { $controlnext = "CheckBox" . $nextcount; } 1208 1209 my $stringname = "OOO_CONTROL_LANG_" . $windowslanguage; 1210 1211 my $line1 = "LanguageSelection" . "\t" . $checkboxcount . "\t" . "CheckBox" . "\t" . 1212 "22" . "\t" . $yvalue . "\t" . "200" . "\t" . "15" . "\t" . $checkboxattribute . "\t" . 1213 $property . "\t" . $stringname . "\t" . $controlnext . "\t" . "\n"; 1214 1215 push(@{$controltable}, $line1); 1216 1217 # my $textcount = "Text" . $count; 1218 # my $stringname = "OOO_CONTROL_LANG_" . $windowslanguage; 1219 # 1220 # $yvalue = $yvalue + 2; # text 2 pixel lower than checkbox 1221 # 1222 # my $line2 = "LanguageSelection" . "\t" . $textcount . "\t" . "Text" . "\t" . 1223 # "40" . "\t" . $yvalue . "\t" . "70" . "\t" . "15" . "\t" . "65539" . "\t" . 1224 # "\t" . $stringname . "\t" . "\t" . "\n"; 1225 # 1226 # push(@{$controltable}, $line2); 1227 } 1228} 1229 1230################################################################### 1231# Determining the last position in a sequencetable 1232# into the tables CustomAc.idt and InstallE.idt. 1233################################################################### 1234 1235sub get_last_position_in_sequencetable 1236{ 1237 my ($sequencetable) = @_; 1238 1239 my $position = 0; 1240 1241 for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) 1242 { 1243 my $line = ${$sequencetable}[$i]; 1244 1245 if ( $line =~ /^\s*\w+\t.*\t\s*(\d+)\s$/ ) 1246 { 1247 my $newposition = $1; 1248 if ( $newposition > $position ) { $position = $newposition; } 1249 } 1250 } 1251 1252 return $position; 1253} 1254 1255######################################################################### 1256# Determining the position of a specified Action in the sequencetable 1257######################################################################### 1258 1259sub get_position_in_sequencetable 1260{ 1261 my ($action, $sequencetable) = @_; 1262 1263 my $position = 0; 1264 1265 $action =~ s/^\s*behind_//; 1266 1267 for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) 1268 { 1269 my $line = ${$sequencetable}[$i]; 1270 1271 if ( $line =~ /^\s*(\w+)\t.*\t\s*(\d+)\s$/ ) 1272 { 1273 my $compareaction = $1; 1274 $position = $2; 1275 if ( $compareaction eq $action ) { last; } 1276 } 1277 } 1278 1279 return $position; 1280} 1281 1282################################################################################################ 1283# Including the CustomAction for the configuration 1284# into the tables CustomAc.idt and InstallE.idt. 1285# 1286# CustomAc.idt: ExecutePkgchk 82 pkgchk.exe -s 1287# InstallE.idt: ExecutePkgchk Not REMOVE="ALL" 3175 1288# 1289# CustomAc.idt: ExecuteQuickstart 82 install_quickstart.exe 1290# InstallE.idt: ExecuteQuickstart &gm_o_Quickstart=3 3200 1291# 1292# CustomAc.idt: ExecuteInstallRegsvrex 82 regsvrex.exe shlxthdl.dll 1293# InstallE.idt: ExecuteInstallRegsvrex Not REMOVE="ALL" 3225 1294# 1295# CustomAc.idt: ExecuteUninstallRegsvrex 82 regsvrex.exe /u shlxthdl.dll 1296# InstallE.idt: ExecuteUninstallRegsvrex REMOVE="ALL" 690 1297# 1298# CustomAc.idt: Regmsdocmsidll1 1 reg4msdocmsidll Reg4MsDocEntry 1299# InstallU.idt: Regmsdocmsidll1 Not REMOVE="ALL" 610 1300# 1301# CustomAc.idt: Regmsdocmsidll2 1 reg4msdocmsidll Reg4MsDocEntry 1302# InstallE.idt: Regmsdocmsidll2 Not REMOVE="ALL" 3160 1303################################################################################################ 1304 1305sub set_custom_action 1306{ 1307 my ($customactionidttable, $actionname, $actionflags, $exefilename, $actionparameter, $inbinarytable, $filesref, $customactionidttablename, $styles) = @_; 1308 1309 my $included_customaction = 0; 1310 my $infoline = ""; 1311 my $customaction_exefilename = $exefilename; 1312 my $uniquename = ""; 1313 1314 # when the style NO_FILE is set, no searching for the file is needed, no filtering is done, we can add that custom action 1315 if ( $styles =~ /\bNO_FILE\b/ ) 1316 { 1317 my $line = $actionname . "\t" . $actionflags . "\t" . $customaction_exefilename . "\t" . $actionparameter . "\n"; 1318 push(@{$customactionidttable}, $line); 1319 1320 $infoline = "Added $actionname CustomAction into table $customactionidttablename (NO_FILE has been set)\n"; 1321 $installer::logger::Lang->print($infoline); 1322 1323 $included_customaction = 1; 1324 return $included_customaction; 1325 } 1326 1327 # is the $exefilename a library that is included into the binary table 1328 1329 if ( $inbinarytable ) { $customaction_exefilename =~ s/\.//; } # this is the entry in the binary table ("abc.dll" -> "abcdll") 1330 1331 # is the $exefilename included into the product? 1332 1333 my $contains_file = 0; 1334 1335 # All files are located in $filesref and in @installer::globals::binarytableonlyfiles. 1336 # Both must be added together 1337 my $localfilesref = installer::converter::combine_arrays_from_references(\@installer::globals::binarytableonlyfiles, $filesref); 1338 1339 for ( my $i = 0; $i <= $#{$localfilesref}; $i++ ) 1340 { 1341 my $onefile = ${$localfilesref}[$i]; 1342 my $filename = ""; 1343 if ( exists($onefile->{'Name'}) ) 1344 { 1345 $filename = $onefile->{'Name'}; 1346 1347 if ( $filename eq $exefilename ) 1348 { 1349 $contains_file = 1; 1350 $uniquename = ${$localfilesref}[$i]->{'uniquename'}; 1351 last; 1352 } 1353 } 1354 else 1355 { 1356 installer::exiter::exit_program("ERROR: Did not find \"Name\" for file \"$onefile->{'uniquename'}\" ($onefile->{'gid'})!", "set_custom_action"); 1357 } 1358 } 1359 1360 if ( $contains_file ) 1361 { 1362 # Now the CustomAction can be included into the CustomAc.idt 1363 1364 if ( ! $inbinarytable ) { $customaction_exefilename = $uniquename; } # the unique file name has to be added to the custom action table 1365 1366 my $line = $actionname . "\t" . $actionflags . "\t" . $customaction_exefilename . "\t" . $actionparameter . "\n"; 1367 push(@{$customactionidttable}, $line); 1368 1369 $included_customaction = 1; 1370 } 1371 1372 if ( $included_customaction ) { $infoline = "Added $actionname CustomAction into table $customactionidttablename\n"; } 1373 else { $infoline = "Did not add $actionname CustomAction into table $customactionidttablename\n"; } 1374 $installer::logger::Lang->print($infoline); 1375 1376 return $included_customaction; 1377} 1378 1379#################################################################### 1380# Adding a Custom Action to InstallExecuteTable or InstallUITable 1381#################################################################### 1382 1383sub add_custom_action_to_install_table 1384{ 1385 my ($installtable, $exefilename, $actionname, $actioncondition, $position, $filesref, $installtablename, $styles) = @_; 1386 1387 my $included_customaction = 0; 1388 my $feature = ""; 1389 my $infoline = ""; 1390 1391 # when the style NO_FILE is set, no searching for the file is needed, no filtering is done, we can add that custom action 1392 if ( $styles =~ /\bNO_FILE\b/ ) 1393 { 1394 # then the InstallE.idt.idt or InstallU.idt.idt 1395 $actioncondition =~ s/FEATURETEMPLATE/$feature/g; # only execute Custom Action, if feature of the file is installed 1396 1397 my $actionposition = 0; 1398 1399 if ( $position eq "end" ) { $actionposition = get_last_position_in_sequencetable($installtable) + 25; } 1400 elsif ( $position =~ /^\s*behind_/ ) { $actionposition = get_position_in_sequencetable($position, $installtable) + 2; } 1401 else { $actionposition = get_position_in_sequencetable($position, $installtable) - 2; } 1402 1403 my $line = $actionname . "\t" . $actioncondition . "\t" . $actionposition . "\n"; 1404 push(@{$installtable}, $line); 1405 1406 $infoline = "Added $actionname CustomAction into table $installtablename (NO_FILE has been set)\n"; 1407 $installer::logger::Lang->print($infoline); 1408 return; 1409 } 1410 1411 my $contains_file = 0; 1412 1413 # All files are located in $filesref and in @installer::globals::binarytableonlyfiles. 1414 # Both must be added together 1415 my $localfilesref = installer::converter::combine_arrays_from_references(\@installer::globals::binarytableonlyfiles, $filesref); 1416 1417 for ( my $i = 0; $i <= $#{$localfilesref}; $i++ ) 1418 { 1419 my $filename = ${$localfilesref}[$i]->{'Name'}; 1420 1421 if ( $filename eq $exefilename ) 1422 { 1423 $contains_file = 1; 1424 1425 # Determining the feature of the file 1426 1427 if ( ${$localfilesref}[$i] ) { $feature = ${$localfilesref}[$i]->{'modules'}; } 1428 1429 # If modules contains a list of modules, only taking the first one. 1430 if ( $feature =~ /^\s*(.*?)\,/ ) { $feature = $1; } 1431 # Attention: Maximum feature length is 38! 1432 shorten_feature_gid(\$feature); 1433 1434 last; 1435 } 1436 } 1437 1438 if ( $contains_file ) 1439 { 1440 # then the InstallE.idt.idt or InstallU.idt.idt 1441 1442 $actioncondition =~ s/FEATURETEMPLATE/$feature/g; # only execute Custom Action, if feature of the file is installed 1443 1444# my $actionposition = 0; 1445# if ( $position eq "end" ) { $actionposition = get_last_position_in_sequencetable($installtable) + 25; } 1446# elsif ( $position =~ /^\s*behind_/ ) { $actionposition = get_position_in_sequencetable($position, $installtable) + 2; } 1447# else { $actionposition = get_position_in_sequencetable($position, $installtable) - 2; } 1448# my $line = $actionname . "\t" . $actioncondition . "\t" . $actionposition . "\n"; 1449 1450 my $positiontemplate = ""; 1451 if ( $position =~ /^\s*\d+\s*$/ ) { $positiontemplate = $position; } # setting the position directly, number defined in scp2 1452 else { $positiontemplate = "POSITIONTEMPLATE_" . $position; } 1453 1454 my $line = $actionname . "\t" . $actioncondition . "\t" . $positiontemplate . "\n"; 1455 push(@{$installtable}, $line); 1456 1457 $included_customaction = 1; 1458 } 1459 1460 if ( $included_customaction ) { $infoline = "Added $actionname CustomAction into table $installtablename\n"; } 1461 else { $infoline = "Did not add $actionname CustomAction into table $installtablename\n"; } 1462 $installer::logger::Lang->print($infoline); 1463 1464} 1465 1466################################################################## 1467# A line in the table ControlEvent connects a Control 1468# with a Custom Action 1469################################################################# 1470 1471sub connect_custom_action_to_control 1472{ 1473 my ( $table, $tablename, $dialog, $control, $event, $argument, $condition, $ordering) = @_; 1474 1475 my $line = $dialog . "\t" . $control. "\t" . $event. "\t" . $argument. "\t" . $condition. "\t" . $ordering . "\n"; 1476 1477 push(@{$table}, $line); 1478 1479 $line =~ s/\s*$//g; 1480 1481 $infoline = "Added line \"$line\" into table $tablename\n"; 1482 $installer::logger::Lang->print($infoline); 1483} 1484 1485################################################################## 1486# A line in the table ControlCondition connects a Control state 1487# with a condition 1488################################################################## 1489 1490sub connect_condition_to_control 1491{ 1492 my ( $table, $tablename, $dialog, $control, $event, $condition) = @_; 1493 1494 my $line = $dialog . "\t" . $control. "\t" . $event. "\t" . $condition. "\n"; 1495 1496 push(@{$table}, $line); 1497 1498 $line =~ s/\s*$//g; 1499 1500 $infoline = "Added line \"$line\" into table $tablename\n"; 1501 $installer::logger::Lang->print($infoline); 1502} 1503 1504################################################################## 1505# Searching for a sequencenumber in InstallUISequence table 1506# "ExecuteAction" must be the last action 1507################################################################## 1508 1509sub get_free_number_in_uisequence_table 1510{ 1511 my ( $installuitable ) = @_; 1512 1513 # determining the sequence of "ExecuteAction" 1514 1515 my $executeactionnumber = 0; 1516 1517 for ( my $i = 0; $i <= $#{$installuitable}; $i++ ) 1518 { 1519 if ( ${$installuitable}[$i] =~ /^\s*(\w+)\t\w*\t(\d+)\s*$/ ) 1520 { 1521 my $actionname = $1; 1522 my $actionnumber = $2; 1523 1524 if ( $actionname eq "ExecuteAction" ) 1525 { 1526 $executeactionnumber = $actionnumber; 1527 last; 1528 } 1529 } 1530 } 1531 1532 if ( $executeactionnumber == 0 ) { installer::exiter::exit_program("ERROR: Did not find \"ExecuteAction\" in InstallUISequence table!", "get_free_number_in_uisequence_table"); } 1533 1534 # determining the sequence of the action before "ExecuteAction" 1535 1536 my $lastactionnumber = 0; 1537 1538 for ( my $i = 0; $i <= $#{$installuitable}; $i++ ) 1539 { 1540 if ( ${$installuitable}[$i] =~ /^\s*\w+\t\w*\t(\d+)\s*$/ ) 1541 { 1542 my $actionnumber = $1; 1543 1544 if (( $actionnumber > $lastactionnumber ) && ( $actionnumber != $executeactionnumber )) 1545 { 1546 $lastactionnumber = $actionnumber; 1547 } 1548 } 1549 } 1550 1551 # the new number can now be calculated 1552 1553 my $newnumber = 0; 1554 1555 if ((( $lastactionnumber + $executeactionnumber ) % 2 ) == 0 ) { $newnumber = ( $lastactionnumber + $executeactionnumber ) / 2; } 1556 else { $newnumber = ( $lastactionnumber + $executeactionnumber -1 ) / 2; } 1557 1558 return $newnumber; 1559} 1560 1561################################################################## 1562# Searching for a specified string in the feature table 1563################################################################## 1564 1565sub get_feature_name 1566{ 1567 my ( $string, $featuretable ) = @_; 1568 1569 my $featurename = ""; 1570 1571 for ( my $i = 0; $i <= $#{$featuretable}; $i++ ) 1572 { 1573 if ( ${$featuretable}[$i] =~ /^\s*(\w+$string)\t/ ) 1574 { 1575 $featurename = $1; 1576 last; 1577 } 1578 } 1579 1580 return $featurename; 1581} 1582 1583###################################################################### 1584# Returning the toplevel directory name of one specific file 1585###################################################################### 1586 1587sub get_directory_name_from_file 1588{ 1589 my ($onefile) = @_; 1590 1591 my $destination = $onefile->{'destination'}; 1592 my $name = $onefile->{'Name'}; 1593 1594 $destination =~ s/\Q$name\E\s*$//; 1595 $destination =~ s/\Q$installer::globals::separator\E\s*$//; 1596 1597 my $path = ""; 1598 1599 if ( $destination =~ /\Q$installer::globals::separator\E/ ) 1600 { 1601 if ( $destination =~ /^\s*(\S.*\S\Q$installer::globals::separator\E)(\S.+\S?)/ ) 1602 { 1603 $path = $2; 1604 } 1605 } 1606 else 1607 { 1608 $path = $destination; 1609 } 1610 1611 return $path; 1612} 1613 1614############################################################# 1615# Including the new subdir into the directory table 1616############################################################# 1617 1618sub include_subdirname_into_directory_table 1619{ 1620 my ($dirname, $directorytable, $directorytablename, $onefile) = @_; 1621 1622 my $subdir = ""; 1623 if ( $onefile->{'Subdir'} ) { $subdir = $onefile->{'Subdir'}; } 1624 if ( $subdir eq "" ) { installer::exiter::exit_program("ERROR: No \"Subdir\" defined for $onefile->{'Name'}", "include_subdirname_into_directory_table"); } 1625 1626 # program INSTALLLOCATION program -> subjava INSTALLLOCATION program:java 1627 1628 my $uniquename = ""; 1629 my $parent = ""; 1630 my $name = ""; 1631 1632 my $includedline = 0; 1633 1634 my $newdir = ""; 1635 1636 for ( my $i = 0; $i <= $#{$directorytable}; $i++ ) 1637 { 1638 1639 if ( ${$directorytable}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\s*$/ ) 1640 { 1641 $uniquename = $1; 1642 $parent = $2; 1643 $name = $3; 1644 1645 if ( $dirname eq $name ) 1646 { 1647 my $newuniquename = "sub" . $subdir; 1648 $newdir = $newuniquename; 1649 # my $newparent = $parent; 1650 my $newparent = "INSTALLLOCATION"; 1651 my $newname = $name . "\:" . $subdir; 1652 my $newline = 1653 $line = "$newuniquename\t$newparent\t$newname\n"; 1654 push(@{$directorytable}, $line); 1655 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1656 $infoline = "Added $line into directory table $directorytablename\n"; 1657 $installer::logger::Lang->print($infoline); 1658 1659 $includedline = 1; 1660 last; 1661 } 1662 } 1663 } 1664 1665 if ( ! $includedline ) { installer::exiter::exit_program("ERROR: Could not include new subdirectory into directory table for file $onefile->{'Name'}!", "include_subdirname_into_directory_table"); } 1666 1667 return $newdir; 1668} 1669 1670################################################################## 1671# Including the new sub directory into the component table 1672################################################################## 1673 1674sub include_subdir_into_componenttable 1675{ 1676 my ($subdir, $onefile, $componenttable) = @_; 1677 1678 my $componentname = $onefile->{'componentname'}; 1679 1680 my $changeddirectory = 0; 1681 1682 for ( my $i = 0; $i <= $#{$componenttable}; $i++ ) 1683 { 1684 if ( ${$componenttable}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 1685 { 1686 my $localcomponentname = $1; 1687 my $directory = $3; 1688 1689 if ( $componentname eq $localcomponentname ) 1690 { 1691 my $oldvalue = ${$componenttable}[$i]; 1692 ${$componenttable}[$i] =~ s/\b\Q$directory\E\b/$subdir/; 1693 my $newvalue = ${$componenttable}[$i]; 1694 1695 installer::remover::remove_leading_and_ending_whitespaces(\$oldvalue); 1696 installer::remover::remove_leading_and_ending_whitespaces(\$newvalue); 1697 $infoline = "Change in Component table: From \"$oldvalue\" to \"$newvalue\"\n"; 1698 $installer::logger::Lang->print($infoline); 1699 1700 $changeddirectory = 1; 1701 last; 1702 } 1703 } 1704 } 1705 1706 if ( ! $changeddirectory ) { installer::exiter::exit_program("ERROR: Could not change directory for component: $onefile->{'Name'}!", "include_subdir_into_componenttable"); } 1707 1708} 1709 1710################################################################################################ 1711# Including the content for the child installations 1712# into the tables: 1713# CustomAc.idt, InstallU.idt, Feature.idt 1714################################################################################################ 1715 1716sub add_childprojects 1717{ 1718 my ($languageidtdir, $filesref, $allvariables) = @_; 1719 1720 my $customactiontablename = $languageidtdir . $installer::globals::separator . "CustomAc.idt"; 1721 my $customactiontable = installer::files::read_file($customactiontablename); 1722 my $installuitablename = $languageidtdir . $installer::globals::separator . "InstallU.idt"; 1723 my $installuitable = installer::files::read_file($installuitablename); 1724 my $featuretablename = $languageidtdir . $installer::globals::separator . "Feature.idt"; 1725 my $featuretable = installer::files::read_file($featuretablename); 1726 my $directorytablename = $languageidtdir . $installer::globals::separator . "Director.idt"; 1727 my $directorytable = installer::files::read_file($directorytablename); 1728 my $componenttablename = $languageidtdir . $installer::globals::separator . "Componen.idt"; 1729 my $componenttable = installer::files::read_file($componenttablename); 1730 1731 my $infoline = ""; 1732 my $line = ""; 1733 1734 $installer::globals::javafile = installer::worker::return_first_item_with_special_flag($filesref ,"JAVAFILE"); 1735 $installer::globals::urefile = installer::worker::return_first_item_with_special_flag($filesref ,"UREFILE"); 1736 1737 if (( $installer::globals::javafile eq "" ) && ( $allvariables->{'JAVAPRODUCT'} )) { installer::exiter::exit_program("ERROR: No JAVAFILE found in files collector!", "add_childprojects"); } 1738 if (( $installer::globals::urefile eq "" ) && ( $allvariables->{'UREPRODUCT'} )) { installer::exiter::exit_program("ERROR: No UREFILE found in files collector!", "add_childprojects"); } 1739 1740 # Content for Directory table 1741 # SystemFolder TARGETDIR . 1742 1743 my $contains_systemfolder = 0; 1744 1745 for ( my $i = 0; $i <= $#{$directorytable}; $i++ ) 1746 { 1747 if ( ${$directorytable}[$i] =~ /^\s*SystemFolder\t/ ) 1748 { 1749 $contains_systemfolder = 1; 1750 last; 1751 } 1752 } 1753 1754 if ( ! $contains_systemfolder ) 1755 { 1756 $line = "SystemFolder\tTARGETDIR\t\.\n"; 1757 push(@{$directorytable}, $line); 1758 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1759 $infoline = "Added $line into table $directorytablename\n"; 1760 } 1761 else 1762 { 1763 $infoline = "SystemFolder already exists in table $directorytablename\n"; 1764 } 1765 1766 $installer::logger::Lang->print($infoline); 1767 1768 # Additional content for the directory table 1769 # subjava INSTALLLOCATION program:java 1770 # subure INSTALLLOCATION program:ure 1771 1772 my $dirname = ""; 1773 my $subjavadir = ""; 1774 my $suburedir = ""; 1775 1776 if ( $allvariables->{'JAVAPRODUCT'} ) 1777 { 1778 $dirname = get_directory_name_from_file($installer::globals::javafile); 1779 $subjavadir = include_subdirname_into_directory_table($dirname, $directorytable, $directorytablename, $installer::globals::javafile); 1780 } 1781 1782 if ( $allvariables->{'UREPRODUCT'} ) 1783 { 1784 $dirname = get_directory_name_from_file($installer::globals::urefile); 1785 $suburedir = include_subdirname_into_directory_table($dirname, $directorytable, $directorytablename, $installer::globals::urefile); 1786 } 1787 1788 # Content for the Component table 1789 # The Java and Ada components have new directories 1790 1791 if ( $allvariables->{'JAVAPRODUCT'} ) { include_subdir_into_componenttable($subjavadir, $installer::globals::javafile, $componenttable); } 1792 if ( $allvariables->{'UREPRODUCT'} ) { include_subdir_into_componenttable($suburedir, $installer::globals::urefile, $componenttable); } 1793 1794 # Content for CustomAction table 1795 1796 if ( $allvariables->{'JAVAPRODUCT'} ) 1797 { 1798 $line = "InstallJava\t98\tSystemFolder\t[SourceDir]$installer::globals::javafile->{'Subdir'}\\$installer::globals::javafile->{'Name'} \/qb REBOOT=Suppress SPONSORS=0 DISABLEAD=1\n"; 1799 push(@{$customactiontable} ,$line); 1800 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1801 $infoline = "Added $line into table $customactiontablename\n"; 1802 $installer::logger::Lang->print($infoline); 1803 } 1804 1805 if ( $allvariables->{'UREPRODUCT'} ) 1806 { 1807 $line = "InstallUre\t98\tSystemFolder\t$installer::globals::urefile->{'Subdir'}\\$installer::globals::urefile->{'Name'} /S\n"; 1808 push(@{$customactiontable} ,$line); 1809 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1810 $infoline = "Added $line into table $customactiontablename\n"; 1811 $installer::logger::Lang->print($infoline); 1812 } 1813 1814 if ( $allvariables->{'JAVAPRODUCT'} ) 1815 { 1816 $line = "MaintenanceJava\t82\t$installer::globals::javafile->{'uniquename'}\t\/qb REBOOT=Suppress SPONSORS=0 DISABLEAD=1\n"; 1817 push(@{$customactiontable} ,$line); 1818 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1819 $infoline = "Added $line into table $customactiontablename\n"; 1820 $installer::logger::Lang->print($infoline); 1821 } 1822 1823 if ( $allvariables->{'UREPRODUCT'} ) 1824 { 1825 $line = "MaintenanceUre\t82\t$installer::globals::urefile->{'uniquename'}\t\/S\n"; 1826 push(@{$customactiontable} ,$line); 1827 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1828 $infoline = "Added $line into table $customactiontablename\n"; 1829 $installer::logger::Lang->print($infoline); 1830 } 1831 1832 # Content for InstallUISequence table 1833 # InstallAdabas &gm_o_Adabas=3 825 1834 # InstallJava &gm_o_Java=3 827 1835 1836 my $number = ""; 1837 my $featurename = ""; 1838 1839 if ( $allvariables->{'ADAPRODUCT'} ) 1840 { 1841 $number = get_free_number_in_uisequence_table($installuitable); 1842 $featurename = get_feature_name("_Adabas", $featuretable); 1843 $line = "InstallAdabas\t\&$featurename\=3 And Not Installed And Not PATCH\t$number\n"; 1844 push(@{$installuitable} ,$line); 1845 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1846 $infoline = "Added $line into table $installuitablename\n"; 1847 $installer::logger::Lang->print($infoline); 1848 } 1849 1850 if ( $allvariables->{'JAVAPRODUCT'} ) 1851 { 1852 $number = get_free_number_in_uisequence_table($installuitable) + 2; 1853 $featurename = get_feature_name("_Java", $featuretable); 1854 if ( $featurename ) { $line = "InstallJava\t\&$featurename\=3 And Not Installed And JAVAPATH\=\"\" And Not PATCH\t$number\n"; } 1855 else { $line = "InstallJava\tNot Installed And JAVAPATH\=\"\" And Not PATCH\t$number\n"; } # feature belongs to root 1856 push(@{$installuitable} ,$line); 1857 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1858 $infoline = "Added $line into table $installuitablename\n"; 1859 $installer::logger::Lang->print($infoline); 1860 } 1861 1862 if ( $allvariables->{'ADAPRODUCT'} ) 1863 { 1864 $number = get_free_number_in_uisequence_table($installuitable) + 4; 1865 $featurename = get_feature_name("_Adabas", $featuretable); 1866 $line = "MaintenanceAdabas\t\&$featurename\=3 And Installed And Not PATCH\t$number\n"; 1867 push(@{$installuitable} ,$line); 1868 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1869 $infoline = "Added $line into table $installuitablename\n"; 1870 $installer::logger::Lang->print($infoline); 1871 } 1872 1873 if ( $allvariables->{'JAVAPRODUCT'} ) 1874 { 1875 $number = get_free_number_in_uisequence_table($installuitable) + 6; 1876 $featurename = get_feature_name("_Java", $featuretable); 1877 if ( $featurename ) { $line = "MaintenanceJava\t\&$featurename\=3 And Installed And JAVAPATH\=\"\" And Not PATCH\t$number\n"; } 1878 else { $line = "MaintenanceJava\tInstalled And JAVAPATH\=\"\" And Not PATCH\t$number\n"; } # feature belongs to root 1879 push(@{$installuitable} ,$line); 1880 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1881 $infoline = "Added $line into table $installuitablename\n"; 1882 $installer::logger::Lang->print($infoline); 1883 } 1884 1885 if ( $allvariables->{'UREPRODUCT'} ) 1886 { 1887 $number = get_free_number_in_uisequence_table($installuitable) + 8; 1888 $featurename = get_feature_name("_Ure", $featuretable); 1889 if ( $featurename ) { $line = "InstallUre\t\&$featurename\=3 And Not Installed\t$number\n"; } 1890 else { $line = "InstallUre\tNot Installed\t$number\n"; } # feature belongs to root 1891 push(@{$installuitable} ,$line); 1892 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1893 $infoline = "Added $line into table $installuitablename\n"; 1894 $installer::logger::Lang->print($infoline); 1895 } 1896 1897 if ( $allvariables->{'UREPRODUCT'} ) 1898 { 1899 $number = get_free_number_in_uisequence_table($installuitable) + 10; 1900 $featurename = get_feature_name("_Ure", $featuretable); 1901 if ( $featurename ) { $line = "MaintenanceUre\t\&$featurename\=3 And Installed\t$number\n"; } 1902 else { $line = "MaintenanceUre\tInstalled\t$number\n"; } # feature belongs to root 1903 push(@{$installuitable} ,$line); 1904 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1905 $infoline = "Added $line into table $installuitablename\n"; 1906 $installer::logger::Lang->print($infoline); 1907 } 1908 1909 # Content for Feature table, better from scp (translation) 1910 # gm_o_java gm_optional Java 1.4.2 Description 2 200 1911 1912 installer::files::save_file($customactiontablename, $customactiontable); 1913 installer::files::save_file($installuitablename, $installuitable); 1914 installer::files::save_file($featuretablename, $featuretable); 1915 installer::files::save_file($directorytablename, $directorytable); 1916 installer::files::save_file($componenttablename, $componenttable); 1917} 1918 1919################################################################## 1920# Setting the encoding in all idt files. Replacing the 1921# variable WINDOWSENCODINGTEMPLATE 1922################################################################## 1923 1924sub setencoding 1925{ 1926 my ( $languageidtdir, $onelanguage ) = @_; 1927 1928 my $encoding = installer::windows::language::get_windows_encoding($onelanguage); 1929 1930 # collecting all idt files in the directory $languageidtdir and substituting the string 1931 1932 my $idtfiles = installer::systemactions::find_file_with_file_extension("idt", $languageidtdir); 1933 1934 for ( my $i = 0; $i <= $#{$idtfiles}; $i++ ) 1935 { 1936 my $onefilename = $languageidtdir . $installer::globals::separator . ${$idtfiles}[$i]; 1937 my $onefile = installer::files::read_file($onefilename); 1938 1939 for ( my $j = 0; $j <= $#{$onefile}; $j++ ) 1940 { 1941 ${$onefile}[$j] =~ s/WINDOWSENCODINGTEMPLATE/$encoding/g; 1942 } 1943 1944 installer::files::save_file($onefilename, $onefile); 1945 } 1946} 1947 1948################################################################## 1949# Setting the condition, that at least one module is selected. 1950# All modules with flag SHOW_MULTILINGUAL_ONLY were already 1951# collected. In table ControlE.idt, the string 1952# LANGUAGECONDITIONINSTALL needs to be replaced. 1953# Also for APPLICATIONCONDITIONINSTALL for the applications 1954# with flag APPLICATIONMODULE. 1955################################################################## 1956 1957sub set_multilanguageonly_condition 1958{ 1959 my ( $languageidtdir ) = @_; 1960 1961 my $onefilename = $languageidtdir . $installer::globals::separator . "ControlE.idt"; 1962 my $onefile = installer::files::read_file($onefilename); 1963 1964 # Language modules 1965 1966 my $condition = ""; 1967 1968 foreach my $module ( sort keys %installer::globals::multilingual_only_modules ) 1969 { 1970 $condition = $condition . " &$module=3 Or"; 1971 } 1972 1973 $condition =~ s/^\s*//; 1974 $condition =~ s/\s*Or\s*$//; # removing the ending "Or" 1975 1976 if ( $condition eq "" ) { $condition = "1"; } 1977 1978 for ( my $j = 0; $j <= $#{$onefile}; $j++ ) 1979 { 1980 ${$onefile}[$j] =~ s/LANGUAGECONDITIONINSTALL/$condition/; 1981 } 1982 1983 # Application modules 1984 1985 $condition = ""; 1986 1987 foreach my $module ( sort keys %installer::globals::application_modules ) 1988 { 1989 $condition = $condition . " &$module=3 Or"; 1990 } 1991 1992 $condition =~ s/^\s*//; 1993 $condition =~ s/\s*Or\s*$//; # removing the ending "Or" 1994 1995 if ( $condition eq "" ) { $condition = "1"; } 1996 1997 for ( my $j = 0; $j <= $#{$onefile}; $j++ ) 1998 { 1999 ${$onefile}[$j] =~ s/APPLICATIONCONDITIONINSTALL/$condition/; 2000 } 2001 2002 installer::files::save_file($onefilename, $onefile); 2003} 2004 2005############################################# 2006# Putting array values into hash 2007############################################# 2008 2009sub fill_assignment_hash 2010{ 2011 my ($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray) = @_; 2012 2013 my $max = $parameter - 1; 2014 2015 if ( $max != $#{$assignmentarray} ) 2016 { 2017 my $definedparameter = $#{$assignmentarray} + 1; 2018 installer::exiter::exit_program("ERROR: gid: $gid, key: $key ! Wrong parameter in scp. For table $tablename $parameter parameter are required ! You defined: $definedparameter", "fill_assignment_hash"); 2019 } 2020 2021 for ( my $i = 0; $i <= $#{$assignmentarray}; $i++ ) 2022 { 2023 my $counter = $i + 1; 2024 my $key = "parameter". $counter; 2025 2026 my $localvalue = ${$assignmentarray}[$i]; 2027 installer::remover::remove_leading_and_ending_quotationmarks(\$localvalue); 2028 $localvalue =~ s/\\\"/\"/g; 2029 $localvalue =~ s/\\\!/\!/g; 2030 $localvalue =~ s/\\\&/\&/g; 2031 $localvalue =~ s/\\\</\</g; 2032 $localvalue =~ s/\\\>/\>/g; 2033 $assignmenthashref->{$key} = $localvalue; 2034 } 2035} 2036 2037########################################################################## 2038# Checking the assignment of a Windows CustomAction and putting it 2039# into a hash 2040########################################################################## 2041 2042sub create_customaction_assignment_hash 2043{ 2044 my ($gid, $name, $key, $assignmentarray) = @_; 2045 2046 my %assignment = (); 2047 my $assignmenthashref = \%assignment; 2048 2049 my $tablename = ${$assignmentarray}[0]; 2050 installer::remover::remove_leading_and_ending_quotationmarks(\$tablename); 2051 2052 my $tablename_defined = 0; 2053 my $parameter = 0; 2054 2055 if ( $tablename eq "InstallUISequence" ) 2056 { 2057 $tablename_defined = 1; 2058 $parameter = 3; 2059 fill_assignment_hash($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray); 2060 } 2061 2062 if ( $tablename eq "InstallExecuteSequence" ) 2063 { 2064 $tablename_defined = 1; 2065 $parameter = 3; 2066 fill_assignment_hash($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray); 2067 } 2068 2069 if ( $tablename eq "AdminExecuteSequence" ) 2070 { 2071 $tablename_defined = 1; 2072 $parameter = 3; 2073 fill_assignment_hash($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray); 2074 } 2075 2076 if ( $tablename eq "ControlEvent" ) 2077 { 2078 $tablename_defined = 1; 2079 $parameter = 7; 2080 fill_assignment_hash($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray); 2081 } 2082 2083 if ( $tablename eq "ControlCondition" ) 2084 { 2085 $tablename_defined = 1; 2086 $parameter = 5; 2087 fill_assignment_hash($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray); 2088 } 2089 2090 if ( ! $tablename_defined ) 2091 { 2092 installer::exiter::exit_program("ERROR: gid: $gid, key: $key ! Unknown Windows CustomAction table: $tablename ! Currently supported: InstallUISequence, InstallExecuteSequence, ControlEvent, ControlCondition", "create_customaction_assignment_hash"); 2093 } 2094 2095 return $assignmenthashref; 2096} 2097 2098########################################################################## 2099# Finding the position of a specified CustomAction. 2100# If the CustomAction is not found, the return value is "-1". 2101# If the CustomAction position is not defined yet, 2102# the return value is also "-1". 2103########################################################################## 2104 2105sub get_customaction_position 2106{ 2107 my ($action, $sequencetable) = @_; 2108 2109 my $position = -1; 2110 2111 for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) 2112 { 2113 my $line = ${$sequencetable}[$i]; 2114 2115 if ( $line =~ /^\s*([\w\.]+)\t.*\t\s*(\d+)\s$/ ) # matching only, if position is a number! 2116 { 2117 my $compareaction = $1; 2118 my $localposition = $2; 2119 2120 if ( $compareaction eq $action ) 2121 { 2122 $position = $localposition; 2123 last; 2124 } 2125 } 2126 } 2127 2128 return $position; 2129} 2130 2131########################################################################## 2132# Setting the position of CustomActions in sequence tables. 2133# Replacing all occurences of "POSITIONTEMPLATE_" 2134########################################################################## 2135 2136sub set_positions_in_table 2137{ 2138 my ( $sequencetable, $tablename ) = @_; 2139 2140 $installer::logger::Lang->print("\n"); 2141 $installer::logger::Lang->printf("Setting positions in table \"%s\".\n", $tablename); 2142 2143 # Step 1: Resolving all occurences of "POSITIONTEMPLATE_end" 2144 2145 my $lastposition = get_last_position_in_sequencetable($sequencetable); 2146 2147 for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) 2148 { 2149 if ( ${$sequencetable}[$i] =~ /^\s*([\w\.]+)\t.*\t\s*POSITIONTEMPLATE_end\s*$/ ) 2150 { 2151 my $customaction = $1; 2152 $lastposition = $lastposition + 25; 2153 ${$sequencetable}[$i] =~ s/POSITIONTEMPLATE_end/$lastposition/; 2154 $infoline = "Setting position \"$lastposition\" for custom action \"$customaction\".\n"; 2155 $installer::logger::Lang->print($infoline); 2156 } 2157 } 2158 2159 # Step 2: Resolving all occurences of "POSITIONTEMPLATE_abc" or "POSITIONTEMPLATE_behind_abc" 2160 # where abc is the name of the reference Custom Action. 2161 # This has to be done, until there is no more occurence of POSITIONTEMPLATE (success) 2162 # or there is no replacement in one circle (failure). 2163 2164 my $template_exists = 0; 2165 my $template_replaced = 0; 2166 my $counter = 0; 2167 2168 do 2169 { 2170 $template_exists = 0; 2171 $template_replaced = 0; 2172 $counter++; 2173 2174 for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) 2175 { 2176 if ( ${$sequencetable}[$i] =~ /^\s*([\w\.]+)\t.*\t\s*(POSITIONTEMPLATE_.*?)\s*$/ ) 2177 { 2178 my $onename = $1; 2179 my $templatename = $2; 2180 my $positionname = $templatename; 2181 my $customaction = $templatename; 2182 $customaction =~ s/POSITIONTEMPLATE_//; 2183 $template_exists = 1; 2184 2185 # Trying to find the correct number. 2186 # This can fail, if the custom action has no number 2187 2188 my $setbehind = 0; 2189 if ( $customaction =~ /^\s*behind_(.*?)\s*$/ ) 2190 { 2191 $customaction = $1; 2192 $setbehind = 1; 2193 } 2194 2195 my $position = get_customaction_position($customaction, $sequencetable); 2196 2197 if ( $position >= 0 ) # Found CustomAction and is has a position. Otherwise return value is "-1". 2198 { 2199 my $newposition = 0; 2200 if ( $setbehind ) { $newposition = $position + 2; } 2201 else { $newposition = $position - 2; } 2202 ${$sequencetable}[$i] =~ s/$templatename/$newposition/; 2203 $template_replaced = 1; 2204 $infoline = "Setting position \"$newposition\" for custom action \"$onename\" (scp: \"$positionname\" at position $position).\n"; 2205 $installer::logger::Lang->print($infoline); 2206 } 2207 else 2208 { 2209 $infoline = "Could not assign position for custom action \"$onename\" yet (scp: \"$positionname\").\n"; 2210 $installer::logger::Lang->print($infoline); 2211 } 2212 } 2213 } 2214 } while (( $template_exists ) && ( $template_replaced )); 2215 2216 # An error occured, because templates still exist, but could not be replaced. 2217 # Reason: 2218 # 1. Wrong name of CustomAction in scp2 (typo?) 2219 # 2. Circular dependencies of CustomActions (A after B and B after A) 2220 2221 # Problem: It is allowed, that a CustomAction is defined in scp2 in a library that is 2222 # part of product ABC, but this CustomAction is not used in this product 2223 # and the reference CustomAction is not part of this product. 2224 # Therefore this cannot be an error, but only produce a warning. The assigned number 2225 # must be the last sequence number. 2226 2227 if (( $template_exists ) && ( ! $template_replaced )) 2228 { 2229 # Giving a precise error message, collecting all unresolved templates 2230 # my $templatestring = ""; 2231 2232 for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) 2233 { 2234 if ( ${$sequencetable}[$i] =~ /^\s*([\w\.]+)\t.*\t\s*(POSITIONTEMPLATE_.*?)\s*$/ ) 2235 { 2236 my $customactionname = $1; 2237 my $fulltemplate = $2; 2238 my $template = $fulltemplate; 2239 $template =~ s/POSITIONTEMPLATE_//; 2240 # my $newstring = $customactionname . " (" . $template . ")"; 2241 # $templatestring = $templatestring . $newstring . ", "; 2242 # Setting at the end! 2243 $lastposition = $lastposition + 25; 2244 ${$sequencetable}[$i] =~ s/$fulltemplate/$lastposition/; 2245 $infoline = "WARNING: Setting position \"$lastposition\" for custom action \"$customactionname\". Could not find CustomAction \"$template\".\n"; 2246 $installer::logger::Lang->print($infoline); 2247 } 2248 } 2249 # $templatestring =~ s/,\s*$//; 2250 2251 # $infoline = "Error: Saving table \"$tablename\"\n"; 2252 # $installer::logger::Lang->print($infoline); 2253 # print $infoline; 2254 # installer::files::save_file($tablename, $sequencetable); 2255 # installer::exiter::exit_program("ERROR: Unresolved positions in CustomActions in scp2: $templatestring", "set_positions_in_table"); 2256 } 2257} 2258 2259########################################################################## 2260# Setting the Windows custom actions into different tables 2261# CustomAc.idt, InstallE.idt, InstallU.idt, ControlE.idt, ControlC.idt 2262########################################################################## 2263 2264sub addcustomactions 2265{ 2266 my ($languageidtdir, $customactions, $filesarray) = @_; 2267 2268 $installer::logger::Lang->print("\n"); 2269 $installer::logger::Lang->add_timestamp("Performance Info: addcustomactions start\n"); 2270 2271 my $customactionidttablename = $languageidtdir . $installer::globals::separator . "CustomAc.idt"; 2272 my $customactionidttable = installer::files::read_file($customactionidttablename); 2273 my $installexecutetablename = $languageidtdir . $installer::globals::separator . "InstallE.idt"; 2274 my $installexecutetable = installer::files::read_file($installexecutetablename); 2275 my $adminexecutetablename = $languageidtdir . $installer::globals::separator . "AdminExe.idt"; 2276 my $adminexecutetable = installer::files::read_file($adminexecutetablename); 2277 my $installuitablename = $languageidtdir . $installer::globals::separator . "InstallU.idt"; 2278 my $installuitable = installer::files::read_file($installuitablename); 2279 my $controleventtablename = $languageidtdir . $installer::globals::separator . "ControlE.idt"; 2280 my $controleventtable = installer::files::read_file($controleventtablename); 2281 my $controlconditiontablename = $languageidtdir . $installer::globals::separator . "ControlC.idt"; 2282 my $controlconditiontable = installer::files::read_file($controlconditiontablename); 2283 2284 # Iterating over all Windows custom actions 2285 2286 for ( my $i = 0; $i <= $#{$customactions}; $i++ ) 2287 { 2288 my $customaction = ${$customactions}[$i]; 2289 my $name = $customaction->{'Name'}; 2290 my $typ = $customaction->{'Typ'}; 2291 my $source = $customaction->{'Source'}; 2292 my $target = $customaction->{'Target'}; 2293 my $inbinarytable = $customaction->{'Inbinarytable'}; 2294 my $gid = $customaction->{'gid'}; 2295 2296 my $styles = ""; 2297 if ( $customaction->{'Styles'} ) { $styles = $customaction->{'Styles'}; } 2298 2299 my $added_customaction = set_custom_action($customactionidttable, $name, $typ, $source, $target, $inbinarytable, $filesarray, $customactionidttablename, $styles); 2300 2301 if ( $added_customaction ) 2302 { 2303 # If the CustomAction was added into the CustomAc.idt, it can be connected to the installation. 2304 # There are currently two different ways for doing this: 2305 # 1. Using "add_custom_action_to_install_table", which adds the CustomAction to the install sequences, 2306 # which are saved in InstallE.idt and InstallU.idt 2307 # 2. Using "connect_custom_action_to_control" and "connect_custom_action_to_control". The first method 2308 # connects a CustomAction to a control in ControlE.idt. The second method sets a condition for a control, 2309 # which might be influenced by the CustomAction. This happens in ControlC.idt. 2310 2311 # Any Windows CustomAction can have a lot of different assignments. 2312 2313 for ( my $j = 1; $j <= 50; $j++ ) 2314 { 2315 my $key = "Assignment" . $j; 2316 my $value = ""; 2317 if ( $customaction->{$key} ) 2318 { 2319 $value = $customaction->{$key}; 2320 2321 # in a patch the Assignment can be overwritten by a PatchAssignment 2322 if ( $installer::globals::patch ) 2323 { 2324 $patchkey = "PatchAssignment" . $j; 2325 if ( $customaction->{$patchkey} ) 2326 { 2327 $value = $customaction->{$patchkey}; 2328 $key = $patchkey; 2329 } 2330 } 2331 2332 } 2333 else { last; } 2334 2335 # $value is now a comma separated list 2336 if ( $value =~ /^\s*\(\s*(.*)\s*\);?\s*$/ ) { $value = $1; } 2337 my $assignmentarray = installer::converter::convert_stringlist_into_array(\$value, ","); 2338 my $assignment = create_customaction_assignment_hash($gid, $name, $key, $assignmentarray); 2339 2340 if ( $assignment->{'parameter1'} eq "InstallExecuteSequence" ) 2341 { 2342 add_custom_action_to_install_table($installexecutetable, $source, $name, $assignment->{'parameter2'}, $assignment->{'parameter3'}, $filesarray, $installexecutetablename, $styles); 2343 } 2344 elsif ( $assignment->{'parameter1'} eq "AdminExecuteSequence" ) 2345 { 2346 add_custom_action_to_install_table($adminexecutetable, $source, $name, $assignment->{'parameter2'}, $assignment->{'parameter3'}, $filesarray, $adminexecutetablename, $styles); 2347 } 2348 elsif ( $assignment->{'parameter1'} eq "InstallUISequence" ) 2349 { 2350 add_custom_action_to_install_table($installuitable, $source, $name, $assignment->{'parameter2'}, $assignment->{'parameter3'}, $filesarray, $installuitablename, $styles); 2351 } 2352 elsif ( $assignment->{'parameter1'} eq "ControlEvent" ) 2353 { 2354 connect_custom_action_to_control($controleventtable, $controleventtablename, $assignment->{'parameter2'}, $assignment->{'parameter3'}, $assignment->{'parameter4'}, $assignment->{'parameter5'}, $assignment->{'parameter6'}, $assignment->{'parameter7'}); 2355 } 2356 elsif ( $assignment->{'parameter1'} eq "ControlCondition" ) 2357 { 2358 connect_condition_to_control($controlconditiontable, $controlconditiontablename, $assignment->{'parameter2'}, $assignment->{'parameter3'}, $assignment->{'parameter4'}, $assignment->{'parameter5'}); 2359 } 2360 else 2361 { 2362 installer::exiter::exit_program("ERROR: gid: $gid, key: $key ! Unknown Windows CustomAction table: $assignmenthashref->{'parameter1'} ! Currently supported: InstallUISequence, InstallESequence, ControlEvent, ControlCondition", "addcustomactions"); 2363 } 2364 } 2365 } 2366 } 2367 2368 # Setting the positions in the tables 2369 2370 set_positions_in_table($installexecutetable, $installexecutetablename); 2371 set_positions_in_table($installuitable, $installuitablename); 2372 set_positions_in_table($adminexecutetable, $adminexecutetablename); 2373 2374 # Saving the files 2375 2376 installer::files::save_file($customactionidttablename, $customactionidttable); 2377 installer::files::save_file($installexecutetablename, $installexecutetable); 2378 installer::files::save_file($adminexecutetablename, $adminexecutetable); 2379 installer::files::save_file($installuitablename, $installuitable); 2380 installer::files::save_file($controleventtablename, $controleventtable); 2381 installer::files::save_file($controlconditiontablename, $controlconditiontable); 2382 2383 my $infoline = "Updated idt file: $customactionidttablename\n"; 2384 $installer::logger::Lang->print($infoline); 2385 $infoline = "Updated idt file: $installexecutetablename\n"; 2386 $installer::logger::Lang->print($infoline); 2387 $infoline = "Updated idt file: $adminexecutetablename\n"; 2388 $installer::logger::Lang->print($infoline); 2389 $infoline = "Updated idt file: $installuitablename\n"; 2390 $installer::logger::Lang->print($infoline); 2391 $infoline = "Updated idt file: $controleventtablename\n"; 2392 $installer::logger::Lang->print($infoline); 2393 $infoline = "Updated idt file: $controlconditiontablename\n"; 2394 $installer::logger::Lang->print($infoline); 2395 2396 $installer::logger::Lang->print("\n"); 2397 $installer::logger::Lang->add_timestamp("Performance Info: addcustomactions end\n"); 2398} 2399 2400########################################################################## 2401# Setting bidi attributes in idt tables 2402########################################################################## 2403 2404sub setbidiattributes 2405{ 2406 my ($languageidtdir, $onelanguage) = @_; 2407 2408 # Editing the files Dialog.idt and Control.idt 2409 2410 my $dialogfilename = $languageidtdir . $installer::globals::separator . "Dialog.idt"; 2411 my $controlfilename = $languageidtdir . $installer::globals::separator . "Control.idt"; 2412 2413 my $dialogfile = installer::files::read_file($dialogfilename); 2414 my $controlfile = installer::files::read_file($controlfilename); 2415 2416 # Searching attributes in Dialog.idt and adding "896". 2417 # Attributes are in column 6 (from 10). 2418 2419 my $bidiattribute = 896; 2420 for ( my $i = 0; $i <= $#{$dialogfile}; $i++ ) 2421 { 2422 if ( $i < 3 ) { next; } 2423 if ( ${$dialogfile}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 2424 { 2425 my $one = $1; 2426 my $two = $2; 2427 my $three = $3; 2428 my $four = $4; 2429 my $five = $5; 2430 my $attribute = $6; 2431 my $seven = $7; 2432 my $eight = $8; 2433 $attribute = $attribute + $bidiattribute; 2434 ${$dialogfile}[$i] = "$one\t$two\t$three\t$four\t$five\t$attribute\t$seven\t$eight\n"; 2435 } 2436 } 2437 2438 # Searching attributes in Control.idt and adding "224". 2439 # Attributes are in column 8 (from 12). 2440 2441 $bidiattribute = 224; 2442 for ( my $i = 0; $i <= $#{$controlfile}; $i++ ) 2443 { 2444 if ( $i < 3 ) { next; } 2445 if ( ${$controlfile}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 2446 { 2447 my $one = $1; 2448 my $two = $2; 2449 my $three = $3; 2450 my $four = $4; 2451 my $five = $5; 2452 my $six = $6; 2453 my $seven = $7; 2454 my $attribute = $8; 2455 my $nine = $9; 2456 my $ten = $10; 2457 my $eleven = $11; 2458 my $twelve = $12; 2459 $attribute = $attribute + $bidiattribute; 2460 ${$controlfile}[$i] = "$one\t$two\t$three\t$four\t$five\t$six\t$seven\t$attribute\t$nine\t$ten\t$eleven\t$twelve\n"; 2461 } 2462 } 2463 2464 # Saving the file 2465 2466 installer::files::save_file($dialogfilename, $dialogfile); 2467 $infoline = "Set bidi support in idt file \"$dialogfilename\" for language $onelanguage\n"; 2468 $installer::logger::Lang->print($infoline); 2469 2470 installer::files::save_file($controlfilename, $controlfile); 2471 $infoline = "Set bidi support in idt file \"$controlfilename\" for language $onelanguage\n"; 2472 $installer::logger::Lang->print($infoline); 2473} 2474 24751; 2476