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($installer::globals::idttemplatepath . $installer::globals::separator . "Binary", $destinationdir . $installer::globals::separator . "Binary"); 798 799 if ((( $installer::globals::patch ) && ( $allvariables->{'WINDOWSPATCHBITMAPDIRECTORY'} )) || ( $allvariables->{'WINDOWSBITMAPDIRECTORY'} )) 800 { 801 my $bitmapdir = ""; 802 if ( $allvariables->{'WINDOWSPATCHBITMAPDIRECTORY'} ) { $bitmapdir = $allvariables->{'WINDOWSPATCHBITMAPDIRECTORY'}; } 803 if ( $allvariables->{'WINDOWSBITMAPDIRECTORY'} ) { $bitmapdir = $allvariables->{'WINDOWSBITMAPDIRECTORY'}; } 804 805 my $newsourcedir = $installer::globals::unpackpath . $installer::globals::separator . $bitmapdir; # path setting in list file dependent from unpackpath !? 806 $installer::logger::Lang->printf("\n"); 807 $installer::logger::Lang->printf( 808 "Overwriting files in directory \"%s%sBinary\" with files from directory \"%s\".\n", 809 $destinationdir, 810 $installer::globals::separator, 811 $newsourcedir); 812 if ( ! -d $newsourcedir ) 813 { 814 my $currentdir = cwd(); 815 installer::exiter::exit_program("ERROR: Directory $newsourcedir does not exist! Current directory is: $currentdir", "prepare_language_idt_directory"); 816 } 817 installer::systemactions::copy_directory($newsourcedir, $destinationdir . $installer::globals::separator . "Binary"); 818 } 819 } 820 821 installer::systemactions::create_directory($destinationdir . $installer::globals::separator . "Icon"); 822 823 if ( -d $installer::globals::idttemplatepath . $installer::globals::separator . "Icon") 824 { 825 installer::systemactions::copy_directory($installer::globals::idttemplatepath . $installer::globals::separator . "Icon", $destinationdir . $installer::globals::separator . "Icon"); 826 } 827 828 # Copying all files in $iconfilecollector, that describe icons of folderitems 829 830 for ( my $i = 0; $i <= $#{$iconfilecollector}; $i++ ) 831 { 832 my $iconfilename = ${$iconfilecollector}[$i]; 833 installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$iconfilename); 834 installer::systemactions::copy_one_file(${$iconfilecollector}[$i], $destinationdir . $installer::globals::separator . "Icon" . $installer::globals::separator . $iconfilename); 835 } 836 837 # Copying all files in $binarytablefiles in the binary directory 838 839 for ( my $i = 0; $i <= $#{$binarytablefiles}; $i++ ) 840 { 841 my $binaryfile = ${$binarytablefiles}[$i]; 842 my $binaryfilepath = $binaryfile->{'sourcepath'}; 843 my $binaryfilename = $binaryfilepath; 844 installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$binaryfilename); 845 installer::systemactions::copy_one_file($binaryfilepath, $destinationdir . $installer::globals::separator . "Binary" . $installer::globals::separator . $binaryfilename); 846 } 847 848 # Copying all new created and language independent idt-files to the destination $destinationdir. 849 # Example: "File.idt" 850 851 installer::systemactions::copy_directory_with_fileextension($newidtdir, $destinationdir, "idt"); 852 853 # Copying all new created and language dependent idt-files to the destination $destinationdir. 854 # Example: "Feature.idt.01" 855 856 installer::systemactions::copy_directory_with_fileextension($newidtdir, $destinationdir, $onelanguage); 857 installer::systemactions::rename_files_with_fileextension($destinationdir, $onelanguage); 858 859} 860 861############################################################## 862# Returning the source path of the rtf licensefile for 863# a specified language 864############################################################## 865 866sub get_rtflicensefilesource 867{ 868 my ($language, $includepatharrayref) = @_; 869 870 my $licensefilename = "license_" . $language . ".rtf"; 871 872 my $sourcefileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$licensefilename, $includepatharrayref, 1); 873 874 if ($$sourcefileref eq "") { installer::exiter::exit_program("ERROR: Could not find $licensefilename!", "get_rtflicensefilesource"); } 875 876 $installer::logger::Lang->printf("Using licensefile: %s\n", $$sourcefileref); 877 878 return $$sourcefileref; 879} 880 881############################################################## 882# Returning the source path of the licensefile for 883# a specified language 884############################################################## 885 886sub get_licensefilesource 887{ 888 my ($language, $filesref) = @_; 889 890 my $licensefilename = "license_" . $language . ".txt"; 891 my $sourcepath = ""; 892 my $foundlicensefile = 0; 893 894 for ( my $i = 0; $i <= $#{$filesref}; $i++ ) 895 { 896 my $onefile = ${$filesref}[$i]; 897 my $filename = $onefile->{'Name'}; 898 899 if ($filename eq $licensefilename) 900 { 901 $sourcepath = $onefile->{'sourcepath'}; 902 $foundlicensefile = 1; 903 last; 904 } 905 } 906 907 if ( ! $foundlicensefile ) { installer::exiter::exit_program("ERROR: Did not find file $licensefilename in file collector!", "get_licensefilesource"); } 908 909 return $sourcepath; 910} 911 912############################################################## 913# A simple converter to create the license text 914# in rtf format 915############################################################## 916 917sub get_rtf_licensetext 918{ 919 my ($licensefile) = @_; 920 921 # A very simple rtf converter 922 923 # The static header 924 925 my $rtf_licensetext = '{\rtf1\ansi\deff0'; 926 $rtf_licensetext = $rtf_licensetext . '{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}}'; 927 $rtf_licensetext = $rtf_licensetext . '{\colortbl\red0\green0\blue0;\red255\green255\blue255;\red128\green128\blue128;}'; 928 $rtf_licensetext = $rtf_licensetext . '{\stylesheet{\s1\snext1 Standard;}}'; 929 $rtf_licensetext = $rtf_licensetext . '{\info{\comment StarWriter}{\vern5690}}\deftab709'; 930 $rtf_licensetext = $rtf_licensetext . '{\*\pgdsctbl'; 931 $rtf_licensetext = $rtf_licensetext . '{\pgdsc0\pgdscuse195\pgwsxn11905\pghsxn16837\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\pgdscnxt0 Standard;}}'; 932 $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'; 933 $rtf_licensetext = $rtf_licensetext . '\pard\plain \s1'; 934 935 for ( my $i = 0; $i <= $#{$licensefile}; $i++ ) 936 { 937 my $oneline = ${$licensefile}[$i]; 938 # if ( $oneline =~ /^\s*$/ ) { $oneline = '\par'; } # empty lines 939 940 if ( $i == 0 ) { $oneline =~ s/^\W*//; } 941 942 $oneline =~ s/\t/ /g; # no tabs allowed, converting to four spaces 943 $oneline =~ s/\n$//g; # no newline at line end 944 945# $oneline =~ s/�/\\\'e4/g; # converting "�" 946# $oneline =~ s/�/\\\'f6/g; # converting "�" 947# $oneline =~ s/�/\\\'fc/g; # converting "�" 948# $oneline =~ s/�/\\\'df/g; # converting "�" 949 950 # german replacements 951 952 $oneline =~ s/\�\�/\\\'c4/g; # converting "�" 953 $oneline =~ s/\�\�/\\\'d6/g; # converting "�" 954 $oneline =~ s/\�\�/\\\'dc/g; # converting "�" 955 $oneline =~ s/\�\�/\\\'e4/g; # converting "�" 956 $oneline =~ s/\�\�/\\\'f6/g; # converting "�" 957 $oneline =~ s/\�\�/\\\'fc/g; # converting "�" 958 $oneline =~ s/\�\�/\\\'df/g; # converting "�" 959 960 # french replacements 961 962 $oneline =~ s/\�\�/\\\'c9/g; 963 $oneline =~ s/\�\�/\\\'c0/g; 964 $oneline =~ s/\�\�/\\\'ab/g; 965 $oneline =~ s/\�\�/\\\'bb/g; 966 $oneline =~ s/\�\�/\\\'e9/g; 967 $oneline =~ s/\�\�/\\\'e8/g; 968 $oneline =~ s/\�\�/\\\'e0/g; 969 $oneline =~ s/\�\�/\\\'f4/g; 970 $oneline =~ s/\�\�/\\\'e7/g; 971 $oneline =~ s/\�\�/\\\'ea/g; 972 $oneline =~ s/\�\�/\\\'ca/g; 973 $oneline =~ s/\�\�/\\\'fb/g; 974 $oneline =~ s/\�\�/\\\'f9/g; 975 $oneline =~ s/\�\�/\\\'ee/g; 976 977 # quotation marks 978 979 $oneline =~ s/\�\�\�/\\\'84/g; 980 $oneline =~ s/\�\�\�/\\ldblquote/g; 981 $oneline =~ s/\�\�\�/\\rquote/g; 982 983 984 $oneline =~ s/\�\�/\\\~/g; 985 986 $oneline = '\par ' . $oneline; 987 988 $rtf_licensetext = $rtf_licensetext . $oneline; 989 } 990 991 # and the end 992 993 $rtf_licensetext = $rtf_licensetext . '\par \par }'; 994 995 return $rtf_licensetext; 996} 997 998############################################################## 999# A simple converter to create a license txt string from 1000# the rtf format 1001############################################################## 1002 1003sub make_string_licensetext 1004{ 1005 my ($licensefile) = @_; 1006 1007 my $rtf_licensetext = ""; 1008 1009 for ( my $i = 0; $i <= $#{$licensefile}; $i++ ) 1010 { 1011 my $oneline = ${$licensefile}[$i]; 1012 $oneline =~ s/\s*$//g; # no whitespace at line end 1013 1014 $rtf_licensetext = $rtf_licensetext . $oneline . " "; 1015 } 1016 1017 return $rtf_licensetext; 1018} 1019 1020############################################################## 1021# Setting the path, where the soffice.exe is installed, into 1022# the CustomAction table 1023############################################################## 1024 1025sub add_officedir_to_database 1026{ 1027 my ($basedir, $allvariables) = @_; 1028 1029 my $customactionfilename = $basedir . $installer::globals::separator . "CustomAc.idt"; 1030 1031 my $customacfile = installer::files::read_file($customactionfilename); 1032 1033 my $found = 0; 1034 1035 # Updating the values 1036 1037 if ( $installer::globals::officeinstalldirectoryset ) 1038 { 1039 $found = 0; 1040 1041 for ( my $i = 0; $i <= $#{$customacfile}; $i++ ) 1042 { 1043 if ( ${$customacfile}[$i] =~ /\bOFFICEDIRECTORYGID\b/ ) 1044 { 1045 ${$customacfile}[$i] =~ s/\bOFFICEDIRECTORYGID\b/$installer::globals::officeinstalldirectory/; 1046 $found = 1; 1047 } 1048 } 1049 1050 if (( ! $found ) && ( ! $allvariables->{'IGNOREDIRECTORYLAYER'} )) 1051 { 1052 installer::exiter::exit_program("ERROR: \"OFFICEDIRECTORYGID\" not found in \"$customactionfilename\" !", "add_officedir_to_database"); 1053 } 1054 } 1055 1056 # Saving the file 1057 1058 installer::files::save_file($customactionfilename ,$customacfile); 1059 my $infoline = "Updated idt file: $customactionfilename\n"; 1060 $installer::logger::Lang->print($infoline); 1061 1062} 1063 1064############################################################## 1065# Including the license text into the table control.idt 1066############################################################## 1067 1068sub add_licensefile_to_database 1069{ 1070 my ($licensefile, $controltable) = @_; 1071 1072 # Nine tabs before the license text and two tabs after it 1073 # The license text has to be included into the dialog 1074 # LicenseAgreement into the control Memo. 1075 1076 my $foundlicenseline = 0; 1077 my ($number, $line); 1078 1079 for ( my $i = 0; $i <= $#{$controltable}; $i++ ) 1080 { 1081 $line = ${$controltable}[$i]; 1082 1083 if ( $line =~ /^\s*\bLicenseAgreement\b\t\bMemo\t/ ) 1084 { 1085 $foundlicenseline = 1; 1086 $number = $i; 1087 last; 1088 } 1089 } 1090 1091 if (!($foundlicenseline)) 1092 { 1093 installer::exiter::exit_program("ERROR: Line for license file in Control.idt not found!", "add_licensefile_to_database"); 1094 } 1095 else 1096 { 1097 my %control = (); 1098 1099 if ( $line =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 1100 { 1101 $control{'Dialog_'} = $1; 1102 $control{'Control'} = $2; 1103 $control{'Type'} = $3; 1104 $control{'X'} = $4; 1105 $control{'Y'} = $5; 1106 $control{'Width'} = $6; 1107 $control{'Height'} = $7; 1108 $control{'Attributes'} = $8; 1109 $control{'Property'} = $9; 1110 $control{'Text'} = $10; 1111 $control{'Control_Next'} = $11; 1112 $control{'Help'} = $12; 1113 } 1114 else 1115 { 1116 installer::exiter::exit_program("ERROR: Could not split line correctly!", "add_licensefile_to_database"); 1117 } 1118 1119 # my $licensetext = get_rtf_licensetext($licensefile); 1120 my $licensetext = make_string_licensetext($licensefile); 1121 1122 $control{'Text'} = $licensetext; 1123 1124 my $newline = $control{'Dialog_'} . "\t" . $control{'Control'} . "\t" . $control{'Type'} . "\t" . 1125 $control{'X'} . "\t" . $control{'Y'} . "\t" . $control{'Width'} . "\t" . 1126 $control{'Height'} . "\t" . $control{'Attributes'} . "\t" . $control{'Property'} . "\t" . 1127 $control{'Text'} . "\t" . $control{'Control_Next'} . "\t" . $control{'Help'} . "\n"; 1128 1129 ${$controltable}[$number] = $newline 1130 } 1131} 1132 1133################################################################################################ 1134# Including the checkboxes for the language selection dialog 1135# into the table control.idt . This is only relevant for 1136# multilingual installation sets. 1137# 1138# old: 1139# LanguageSelection CheckBox1 CheckBox 22 60 15 24 3 IS1033 CheckBox2 1140# LanguageSelection Text1 Text 40 60 70 15 65539 OOO_CONTROL_LANG_1033 1141# LanguageSelection CheckBox2 CheckBox 22 90 15 24 3 IS1031 Next 1142# LanguageSelection Text2 Text 40 90 70 15 65539 OOO_CONTROL_LANG_1031 1143# new: 1144# LanguageSelection CheckBox1 CheckBox 22 60 15 24 3 IS1033 Text CheckBox2 1145# LanguageSelection CheckBox2 CheckBox 22 90 15 24 3 IS1031 Text Next 1146################################################################################################ 1147 1148sub add_language_checkboxes_to_database 1149{ 1150 my ($controltable, $languagesarrayref) = @_; 1151 1152 # for each language, two lines have to be inserted 1153 1154 for ( my $i = 0; $i <= $#{$languagesarrayref}; $i++ ) 1155 { 1156 my $last = 0; 1157 if ( $i == $#{$languagesarrayref} ) { $last = 1; } # special handling for the last 1158 1159 my $onelanguage = ${$languagesarrayref}[$i]; 1160 my $windowslanguage = installer::windows::language::get_windows_language($onelanguage); 1161 1162 # my $is_english = 0; 1163 # if ( $windowslanguage eq "1033" ) { $is_english = 1; } 1164 1165 my $checkboxattribute = "3"; 1166 # if ( $is_english ) { $checkboxattribute = "1"; } # english is not deselectable 1167 1168 my $count = $i + 1; 1169 my $nextcount = $i + 2; 1170 my $checkboxcount = "CheckBox" . $count; 1171 1172 my $multiplier = 20; 1173 my $offset = 60; 1174 if ( $#{$languagesarrayref} > 7 ) 1175 { 1176 $multiplier = 15; # smaller differences for more than 7 languages 1177 $offset = 50; # smaller offset for more than 7 languages 1178 } 1179 1180 my $yvalue = $offset + $i * $multiplier; 1181 1182 my $property = "IS" . $windowslanguage; 1183 # 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"); } 1184 1185 my $controlnext = ""; 1186 if ( $last ) { $controlnext = "Next"; } 1187 else { $controlnext = "CheckBox" . $nextcount; } 1188 1189 my $stringname = "OOO_CONTROL_LANG_" . $windowslanguage; 1190 1191 my $line1 = "LanguageSelection" . "\t" . $checkboxcount . "\t" . "CheckBox" . "\t" . 1192 "22" . "\t" . $yvalue . "\t" . "200" . "\t" . "15" . "\t" . $checkboxattribute . "\t" . 1193 $property . "\t" . $stringname . "\t" . $controlnext . "\t" . "\n"; 1194 1195 push(@{$controltable}, $line1); 1196 1197 # my $textcount = "Text" . $count; 1198 # my $stringname = "OOO_CONTROL_LANG_" . $windowslanguage; 1199 # 1200 # $yvalue = $yvalue + 2; # text 2 pixel lower than checkbox 1201 # 1202 # my $line2 = "LanguageSelection" . "\t" . $textcount . "\t" . "Text" . "\t" . 1203 # "40" . "\t" . $yvalue . "\t" . "70" . "\t" . "15" . "\t" . "65539" . "\t" . 1204 # "\t" . $stringname . "\t" . "\t" . "\n"; 1205 # 1206 # push(@{$controltable}, $line2); 1207 } 1208} 1209 1210################################################################### 1211# Determining the last position in a sequencetable 1212# into the tables CustomAc.idt and InstallE.idt. 1213################################################################### 1214 1215sub get_last_position_in_sequencetable 1216{ 1217 my ($sequencetable) = @_; 1218 1219 my $position = 0; 1220 1221 for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) 1222 { 1223 my $line = ${$sequencetable}[$i]; 1224 1225 if ( $line =~ /^\s*\w+\t.*\t\s*(\d+)\s$/ ) 1226 { 1227 my $newposition = $1; 1228 if ( $newposition > $position ) { $position = $newposition; } 1229 } 1230 } 1231 1232 return $position; 1233} 1234 1235######################################################################### 1236# Determining the position of a specified Action in the sequencetable 1237######################################################################### 1238 1239sub get_position_in_sequencetable 1240{ 1241 my ($action, $sequencetable) = @_; 1242 1243 my $position = 0; 1244 1245 $action =~ s/^\s*behind_//; 1246 1247 for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) 1248 { 1249 my $line = ${$sequencetable}[$i]; 1250 1251 if ( $line =~ /^\s*(\w+)\t.*\t\s*(\d+)\s$/ ) 1252 { 1253 my $compareaction = $1; 1254 $position = $2; 1255 if ( $compareaction eq $action ) { last; } 1256 } 1257 } 1258 1259 return $position; 1260} 1261 1262################################################################################################ 1263# Including the CustomAction for the configuration 1264# into the tables CustomAc.idt and InstallE.idt. 1265# 1266# CustomAc.idt: ExecutePkgchk 82 pkgchk.exe -s 1267# InstallE.idt: ExecutePkgchk Not REMOVE="ALL" 3175 1268# 1269# CustomAc.idt: ExecuteQuickstart 82 install_quickstart.exe 1270# InstallE.idt: ExecuteQuickstart &gm_o_Quickstart=3 3200 1271# 1272# CustomAc.idt: ExecuteInstallRegsvrex 82 regsvrex.exe shlxthdl.dll 1273# InstallE.idt: ExecuteInstallRegsvrex Not REMOVE="ALL" 3225 1274# 1275# CustomAc.idt: ExecuteUninstallRegsvrex 82 regsvrex.exe /u shlxthdl.dll 1276# InstallE.idt: ExecuteUninstallRegsvrex REMOVE="ALL" 690 1277# 1278# CustomAc.idt: Regmsdocmsidll1 1 reg4msdocmsidll Reg4MsDocEntry 1279# InstallU.idt: Regmsdocmsidll1 Not REMOVE="ALL" 610 1280# 1281# CustomAc.idt: Regmsdocmsidll2 1 reg4msdocmsidll Reg4MsDocEntry 1282# InstallE.idt: Regmsdocmsidll2 Not REMOVE="ALL" 3160 1283################################################################################################ 1284 1285sub set_custom_action 1286{ 1287 my ($customactionidttable, $actionname, $actionflags, $exefilename, $actionparameter, $inbinarytable, $filesref, $customactionidttablename, $styles) = @_; 1288 1289 my $included_customaction = 0; 1290 my $infoline = ""; 1291 my $customaction_exefilename = $exefilename; 1292 my $uniquename = ""; 1293 1294 # when the style NO_FILE is set, no searching for the file is needed, no filtering is done, we can add that custom action 1295 if ( $styles =~ /\bNO_FILE\b/ ) 1296 { 1297 my $line = $actionname . "\t" . $actionflags . "\t" . $customaction_exefilename . "\t" . $actionparameter . "\n"; 1298 push(@{$customactionidttable}, $line); 1299 1300 $infoline = "Added $actionname CustomAction into table $customactionidttablename (NO_FILE has been set)\n"; 1301 $installer::logger::Lang->print($infoline); 1302 1303 $included_customaction = 1; 1304 return $included_customaction; 1305 } 1306 1307 # is the $exefilename a library that is included into the binary table 1308 1309 if ( $inbinarytable ) { $customaction_exefilename =~ s/\.//; } # this is the entry in the binary table ("abc.dll" -> "abcdll") 1310 1311 # is the $exefilename included into the product? 1312 1313 my $contains_file = 0; 1314 1315 # All files are located in $filesref and in @installer::globals::binarytableonlyfiles. 1316 # Both must be added together 1317 my $localfilesref = installer::converter::combine_arrays_from_references(\@installer::globals::binarytableonlyfiles, $filesref); 1318 1319 for ( my $i = 0; $i <= $#{$localfilesref}; $i++ ) 1320 { 1321 my $onefile = ${$localfilesref}[$i]; 1322 my $filename = ""; 1323 if ( exists($onefile->{'Name'}) ) 1324 { 1325 $filename = $onefile->{'Name'}; 1326 1327 if ( $filename eq $exefilename ) 1328 { 1329 $contains_file = 1; 1330 $uniquename = ${$localfilesref}[$i]->{'uniquename'}; 1331 last; 1332 } 1333 } 1334 else 1335 { 1336 installer::exiter::exit_program("ERROR: Did not find \"Name\" for file \"$onefile->{'uniquename'}\" ($onefile->{'gid'})!", "set_custom_action"); 1337 } 1338 } 1339 1340 if ( $contains_file ) 1341 { 1342 # Now the CustomAction can be included into the CustomAc.idt 1343 1344 if ( ! $inbinarytable ) { $customaction_exefilename = $uniquename; } # the unique file name has to be added to the custom action table 1345 1346 my $line = $actionname . "\t" . $actionflags . "\t" . $customaction_exefilename . "\t" . $actionparameter . "\n"; 1347 push(@{$customactionidttable}, $line); 1348 1349 $included_customaction = 1; 1350 } 1351 1352 if ( $included_customaction ) { $infoline = "Added $actionname CustomAction into table $customactionidttablename\n"; } 1353 else { $infoline = "Did not add $actionname CustomAction into table $customactionidttablename\n"; } 1354 $installer::logger::Lang->print($infoline); 1355 1356 return $included_customaction; 1357} 1358 1359#################################################################### 1360# Adding a Custom Action to InstallExecuteTable or InstallUITable 1361#################################################################### 1362 1363sub add_custom_action_to_install_table 1364{ 1365 my ($installtable, $exefilename, $actionname, $actioncondition, $position, $filesref, $installtablename, $styles) = @_; 1366 1367 my $included_customaction = 0; 1368 my $feature = ""; 1369 my $infoline = ""; 1370 1371 # when the style NO_FILE is set, no searching for the file is needed, no filtering is done, we can add that custom action 1372 if ( $styles =~ /\bNO_FILE\b/ ) 1373 { 1374 # then the InstallE.idt.idt or InstallU.idt.idt 1375 $actioncondition =~ s/FEATURETEMPLATE/$feature/g; # only execute Custom Action, if feature of the file is installed 1376 1377 my $actionposition = 0; 1378 1379 if ( $position eq "end" ) { $actionposition = get_last_position_in_sequencetable($installtable) + 25; } 1380 elsif ( $position =~ /^\s*behind_/ ) { $actionposition = get_position_in_sequencetable($position, $installtable) + 2; } 1381 else { $actionposition = get_position_in_sequencetable($position, $installtable) - 2; } 1382 1383 my $line = $actionname . "\t" . $actioncondition . "\t" . $actionposition . "\n"; 1384 push(@{$installtable}, $line); 1385 1386 $infoline = "Added $actionname CustomAction into table $installtablename (NO_FILE has been set)\n"; 1387 $installer::logger::Lang->print($infoline); 1388 return; 1389 } 1390 1391 my $contains_file = 0; 1392 1393 # All files are located in $filesref and in @installer::globals::binarytableonlyfiles. 1394 # Both must be added together 1395 my $localfilesref = installer::converter::combine_arrays_from_references(\@installer::globals::binarytableonlyfiles, $filesref); 1396 1397 for ( my $i = 0; $i <= $#{$localfilesref}; $i++ ) 1398 { 1399 my $filename = ${$localfilesref}[$i]->{'Name'}; 1400 1401 if ( $filename eq $exefilename ) 1402 { 1403 $contains_file = 1; 1404 1405 # Determining the feature of the file 1406 1407 if ( ${$localfilesref}[$i] ) { $feature = ${$localfilesref}[$i]->{'modules'}; } 1408 1409 # If modules contains a list of modules, only taking the first one. 1410 if ( $feature =~ /^\s*(.*?)\,/ ) { $feature = $1; } 1411 # Attention: Maximum feature length is 38! 1412 shorten_feature_gid(\$feature); 1413 1414 last; 1415 } 1416 } 1417 1418 if ( $contains_file ) 1419 { 1420 # then the InstallE.idt.idt or InstallU.idt.idt 1421 1422 $actioncondition =~ s/FEATURETEMPLATE/$feature/g; # only execute Custom Action, if feature of the file is installed 1423 1424# my $actionposition = 0; 1425# if ( $position eq "end" ) { $actionposition = get_last_position_in_sequencetable($installtable) + 25; } 1426# elsif ( $position =~ /^\s*behind_/ ) { $actionposition = get_position_in_sequencetable($position, $installtable) + 2; } 1427# else { $actionposition = get_position_in_sequencetable($position, $installtable) - 2; } 1428# my $line = $actionname . "\t" . $actioncondition . "\t" . $actionposition . "\n"; 1429 1430 my $positiontemplate = ""; 1431 if ( $position =~ /^\s*\d+\s*$/ ) { $positiontemplate = $position; } # setting the position directly, number defined in scp2 1432 else { $positiontemplate = "POSITIONTEMPLATE_" . $position; } 1433 1434 my $line = $actionname . "\t" . $actioncondition . "\t" . $positiontemplate . "\n"; 1435 push(@{$installtable}, $line); 1436 1437 $included_customaction = 1; 1438 } 1439 1440 if ( $included_customaction ) { $infoline = "Added $actionname CustomAction into table $installtablename\n"; } 1441 else { $infoline = "Did not add $actionname CustomAction into table $installtablename\n"; } 1442 $installer::logger::Lang->print($infoline); 1443 1444} 1445 1446################################################################## 1447# A line in the table ControlEvent connects a Control 1448# with a Custom Action 1449################################################################# 1450 1451sub connect_custom_action_to_control 1452{ 1453 my ( $table, $tablename, $dialog, $control, $event, $argument, $condition, $ordering) = @_; 1454 1455 my $line = $dialog . "\t" . $control. "\t" . $event. "\t" . $argument. "\t" . $condition. "\t" . $ordering . "\n"; 1456 1457 push(@{$table}, $line); 1458 1459 $line =~ s/\s*$//g; 1460 1461 $infoline = "Added line \"$line\" into table $tablename\n"; 1462 $installer::logger::Lang->print($infoline); 1463} 1464 1465################################################################## 1466# A line in the table ControlCondition connects a Control state 1467# with a condition 1468################################################################## 1469 1470sub connect_condition_to_control 1471{ 1472 my ( $table, $tablename, $dialog, $control, $event, $condition) = @_; 1473 1474 my $line = $dialog . "\t" . $control. "\t" . $event. "\t" . $condition. "\n"; 1475 1476 push(@{$table}, $line); 1477 1478 $line =~ s/\s*$//g; 1479 1480 $infoline = "Added line \"$line\" into table $tablename\n"; 1481 $installer::logger::Lang->print($infoline); 1482} 1483 1484################################################################## 1485# Searching for a sequencenumber in InstallUISequence table 1486# "ExecuteAction" must be the last action 1487################################################################## 1488 1489sub get_free_number_in_uisequence_table 1490{ 1491 my ( $installuitable ) = @_; 1492 1493 # determining the sequence of "ExecuteAction" 1494 1495 my $executeactionnumber = 0; 1496 1497 for ( my $i = 0; $i <= $#{$installuitable}; $i++ ) 1498 { 1499 if ( ${$installuitable}[$i] =~ /^\s*(\w+)\t\w*\t(\d+)\s*$/ ) 1500 { 1501 my $actionname = $1; 1502 my $actionnumber = $2; 1503 1504 if ( $actionname eq "ExecuteAction" ) 1505 { 1506 $executeactionnumber = $actionnumber; 1507 last; 1508 } 1509 } 1510 } 1511 1512 if ( $executeactionnumber == 0 ) { installer::exiter::exit_program("ERROR: Did not find \"ExecuteAction\" in InstallUISequence table!", "get_free_number_in_uisequence_table"); } 1513 1514 # determining the sequence of the action before "ExecuteAction" 1515 1516 my $lastactionnumber = 0; 1517 1518 for ( my $i = 0; $i <= $#{$installuitable}; $i++ ) 1519 { 1520 if ( ${$installuitable}[$i] =~ /^\s*\w+\t\w*\t(\d+)\s*$/ ) 1521 { 1522 my $actionnumber = $1; 1523 1524 if (( $actionnumber > $lastactionnumber ) && ( $actionnumber != $executeactionnumber )) 1525 { 1526 $lastactionnumber = $actionnumber; 1527 } 1528 } 1529 } 1530 1531 # the new number can now be calculated 1532 1533 my $newnumber = 0; 1534 1535 if ((( $lastactionnumber + $executeactionnumber ) % 2 ) == 0 ) { $newnumber = ( $lastactionnumber + $executeactionnumber ) / 2; } 1536 else { $newnumber = ( $lastactionnumber + $executeactionnumber -1 ) / 2; } 1537 1538 return $newnumber; 1539} 1540 1541################################################################## 1542# Searching for a specified string in the feature table 1543################################################################## 1544 1545sub get_feature_name 1546{ 1547 my ( $string, $featuretable ) = @_; 1548 1549 my $featurename = ""; 1550 1551 for ( my $i = 0; $i <= $#{$featuretable}; $i++ ) 1552 { 1553 if ( ${$featuretable}[$i] =~ /^\s*(\w+$string)\t/ ) 1554 { 1555 $featurename = $1; 1556 last; 1557 } 1558 } 1559 1560 return $featurename; 1561} 1562 1563###################################################################### 1564# Returning the toplevel directory name of one specific file 1565###################################################################### 1566 1567sub get_directory_name_from_file 1568{ 1569 my ($onefile) = @_; 1570 1571 my $destination = $onefile->{'destination'}; 1572 my $name = $onefile->{'Name'}; 1573 1574 $destination =~ s/\Q$name\E\s*$//; 1575 $destination =~ s/\Q$installer::globals::separator\E\s*$//; 1576 1577 my $path = ""; 1578 1579 if ( $destination =~ /\Q$installer::globals::separator\E/ ) 1580 { 1581 if ( $destination =~ /^\s*(\S.*\S\Q$installer::globals::separator\E)(\S.+\S?)/ ) 1582 { 1583 $path = $2; 1584 } 1585 } 1586 else 1587 { 1588 $path = $destination; 1589 } 1590 1591 return $path; 1592} 1593 1594############################################################# 1595# Including the new subdir into the directory table 1596############################################################# 1597 1598sub include_subdirname_into_directory_table 1599{ 1600 my ($dirname, $directorytable, $directorytablename, $onefile) = @_; 1601 1602 my $subdir = ""; 1603 if ( $onefile->{'Subdir'} ) { $subdir = $onefile->{'Subdir'}; } 1604 if ( $subdir eq "" ) { installer::exiter::exit_program("ERROR: No \"Subdir\" defined for $onefile->{'Name'}", "include_subdirname_into_directory_table"); } 1605 1606 # program INSTALLLOCATION program -> subjava INSTALLLOCATION program:java 1607 1608 my $uniquename = ""; 1609 my $parent = ""; 1610 my $name = ""; 1611 1612 my $includedline = 0; 1613 1614 my $newdir = ""; 1615 1616 for ( my $i = 0; $i <= $#{$directorytable}; $i++ ) 1617 { 1618 1619 if ( ${$directorytable}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\s*$/ ) 1620 { 1621 $uniquename = $1; 1622 $parent = $2; 1623 $name = $3; 1624 1625 if ( $dirname eq $name ) 1626 { 1627 my $newuniquename = "sub" . $subdir; 1628 $newdir = $newuniquename; 1629 # my $newparent = $parent; 1630 my $newparent = "INSTALLLOCATION"; 1631 my $newname = $name . "\:" . $subdir; 1632 my $newline = 1633 $line = "$newuniquename\t$newparent\t$newname\n"; 1634 push(@{$directorytable}, $line); 1635 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1636 $infoline = "Added $line into directory table $directorytablename\n"; 1637 $installer::logger::Lang->print($infoline); 1638 1639 $includedline = 1; 1640 last; 1641 } 1642 } 1643 } 1644 1645 if ( ! $includedline ) { installer::exiter::exit_program("ERROR: Could not include new subdirectory into directory table for file $onefile->{'Name'}!", "include_subdirname_into_directory_table"); } 1646 1647 return $newdir; 1648} 1649 1650################################################################## 1651# Including the new sub directory into the component table 1652################################################################## 1653 1654sub include_subdir_into_componenttable 1655{ 1656 my ($subdir, $onefile, $componenttable) = @_; 1657 1658 my $componentname = $onefile->{'componentname'}; 1659 1660 my $changeddirectory = 0; 1661 1662 for ( my $i = 0; $i <= $#{$componenttable}; $i++ ) 1663 { 1664 if ( ${$componenttable}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 1665 { 1666 my $localcomponentname = $1; 1667 my $directory = $3; 1668 1669 if ( $componentname eq $localcomponentname ) 1670 { 1671 my $oldvalue = ${$componenttable}[$i]; 1672 ${$componenttable}[$i] =~ s/\b\Q$directory\E\b/$subdir/; 1673 my $newvalue = ${$componenttable}[$i]; 1674 1675 installer::remover::remove_leading_and_ending_whitespaces(\$oldvalue); 1676 installer::remover::remove_leading_and_ending_whitespaces(\$newvalue); 1677 $infoline = "Change in Component table: From \"$oldvalue\" to \"$newvalue\"\n"; 1678 $installer::logger::Lang->print($infoline); 1679 1680 $changeddirectory = 1; 1681 last; 1682 } 1683 } 1684 } 1685 1686 if ( ! $changeddirectory ) { installer::exiter::exit_program("ERROR: Could not change directory for component: $onefile->{'Name'}!", "include_subdir_into_componenttable"); } 1687 1688} 1689 1690################################################################################################ 1691# Including the content for the child installations 1692# into the tables: 1693# CustomAc.idt, InstallU.idt, Feature.idt 1694################################################################################################ 1695 1696sub add_childprojects 1697{ 1698 my ($languageidtdir, $filesref, $allvariables) = @_; 1699 1700 my $customactiontablename = $languageidtdir . $installer::globals::separator . "CustomAc.idt"; 1701 my $customactiontable = installer::files::read_file($customactiontablename); 1702 my $installuitablename = $languageidtdir . $installer::globals::separator . "InstallU.idt"; 1703 my $installuitable = installer::files::read_file($installuitablename); 1704 my $featuretablename = $languageidtdir . $installer::globals::separator . "Feature.idt"; 1705 my $featuretable = installer::files::read_file($featuretablename); 1706 my $directorytablename = $languageidtdir . $installer::globals::separator . "Director.idt"; 1707 my $directorytable = installer::files::read_file($directorytablename); 1708 my $componenttablename = $languageidtdir . $installer::globals::separator . "Componen.idt"; 1709 my $componenttable = installer::files::read_file($componenttablename); 1710 1711 my $infoline = ""; 1712 my $line = ""; 1713 1714 $installer::globals::javafile = installer::worker::return_first_item_with_special_flag($filesref ,"JAVAFILE"); 1715 $installer::globals::urefile = installer::worker::return_first_item_with_special_flag($filesref ,"UREFILE"); 1716 1717 if (( $installer::globals::javafile eq "" ) && ( $allvariables->{'JAVAPRODUCT'} )) { installer::exiter::exit_program("ERROR: No JAVAFILE found in files collector!", "add_childprojects"); } 1718 if (( $installer::globals::urefile eq "" ) && ( $allvariables->{'UREPRODUCT'} )) { installer::exiter::exit_program("ERROR: No UREFILE found in files collector!", "add_childprojects"); } 1719 1720 # Content for Directory table 1721 # SystemFolder TARGETDIR . 1722 1723 my $contains_systemfolder = 0; 1724 1725 for ( my $i = 0; $i <= $#{$directorytable}; $i++ ) 1726 { 1727 if ( ${$directorytable}[$i] =~ /^\s*SystemFolder\t/ ) 1728 { 1729 $contains_systemfolder = 1; 1730 last; 1731 } 1732 } 1733 1734 if ( ! $contains_systemfolder ) 1735 { 1736 $line = "SystemFolder\tTARGETDIR\t\.\n"; 1737 push(@{$directorytable}, $line); 1738 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1739 $infoline = "Added $line into table $directorytablename\n"; 1740 } 1741 else 1742 { 1743 $infoline = "SystemFolder already exists in table $directorytablename\n"; 1744 } 1745 1746 $installer::logger::Lang->print($infoline); 1747 1748 # Additional content for the directory table 1749 # subjava INSTALLLOCATION program:java 1750 # subure INSTALLLOCATION program:ure 1751 1752 my $dirname = ""; 1753 my $subjavadir = ""; 1754 my $suburedir = ""; 1755 1756 if ( $allvariables->{'JAVAPRODUCT'} ) 1757 { 1758 $dirname = get_directory_name_from_file($installer::globals::javafile); 1759 $subjavadir = include_subdirname_into_directory_table($dirname, $directorytable, $directorytablename, $installer::globals::javafile); 1760 } 1761 1762 if ( $allvariables->{'UREPRODUCT'} ) 1763 { 1764 $dirname = get_directory_name_from_file($installer::globals::urefile); 1765 $suburedir = include_subdirname_into_directory_table($dirname, $directorytable, $directorytablename, $installer::globals::urefile); 1766 } 1767 1768 # Content for the Component table 1769 # The Java and Ada components have new directories 1770 1771 if ( $allvariables->{'JAVAPRODUCT'} ) { include_subdir_into_componenttable($subjavadir, $installer::globals::javafile, $componenttable); } 1772 if ( $allvariables->{'UREPRODUCT'} ) { include_subdir_into_componenttable($suburedir, $installer::globals::urefile, $componenttable); } 1773 1774 # Content for CustomAction table 1775 1776 if ( $allvariables->{'JAVAPRODUCT'} ) 1777 { 1778 $line = "InstallJava\t98\tSystemFolder\t[SourceDir]$installer::globals::javafile->{'Subdir'}\\$installer::globals::javafile->{'Name'} \/qb REBOOT=Suppress SPONSORS=0 DISABLEAD=1\n"; 1779 push(@{$customactiontable} ,$line); 1780 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1781 $infoline = "Added $line into table $customactiontablename\n"; 1782 $installer::logger::Lang->print($infoline); 1783 } 1784 1785 if ( $allvariables->{'UREPRODUCT'} ) 1786 { 1787 $line = "InstallUre\t98\tSystemFolder\t$installer::globals::urefile->{'Subdir'}\\$installer::globals::urefile->{'Name'} /S\n"; 1788 push(@{$customactiontable} ,$line); 1789 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1790 $infoline = "Added $line into table $customactiontablename\n"; 1791 $installer::logger::Lang->print($infoline); 1792 } 1793 1794 if ( $allvariables->{'JAVAPRODUCT'} ) 1795 { 1796 $line = "MaintenanceJava\t82\t$installer::globals::javafile->{'uniquename'}\t\/qb REBOOT=Suppress SPONSORS=0 DISABLEAD=1\n"; 1797 push(@{$customactiontable} ,$line); 1798 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1799 $infoline = "Added $line into table $customactiontablename\n"; 1800 $installer::logger::Lang->print($infoline); 1801 } 1802 1803 if ( $allvariables->{'UREPRODUCT'} ) 1804 { 1805 $line = "MaintenanceUre\t82\t$installer::globals::urefile->{'uniquename'}\t\/S\n"; 1806 push(@{$customactiontable} ,$line); 1807 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1808 $infoline = "Added $line into table $customactiontablename\n"; 1809 $installer::logger::Lang->print($infoline); 1810 } 1811 1812 # Content for InstallUISequence table 1813 # InstallAdabas &gm_o_Adabas=3 825 1814 # InstallJava &gm_o_Java=3 827 1815 1816 my $number = ""; 1817 my $featurename = ""; 1818 1819 if ( $allvariables->{'ADAPRODUCT'} ) 1820 { 1821 $number = get_free_number_in_uisequence_table($installuitable); 1822 $featurename = get_feature_name("_Adabas", $featuretable); 1823 $line = "InstallAdabas\t\&$featurename\=3 And Not Installed And Not PATCH\t$number\n"; 1824 push(@{$installuitable} ,$line); 1825 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1826 $infoline = "Added $line into table $installuitablename\n"; 1827 $installer::logger::Lang->print($infoline); 1828 } 1829 1830 if ( $allvariables->{'JAVAPRODUCT'} ) 1831 { 1832 $number = get_free_number_in_uisequence_table($installuitable) + 2; 1833 $featurename = get_feature_name("_Java", $featuretable); 1834 if ( $featurename ) { $line = "InstallJava\t\&$featurename\=3 And Not Installed And JAVAPATH\=\"\" And Not PATCH\t$number\n"; } 1835 else { $line = "InstallJava\tNot Installed And JAVAPATH\=\"\" And Not PATCH\t$number\n"; } # feature belongs to root 1836 push(@{$installuitable} ,$line); 1837 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1838 $infoline = "Added $line into table $installuitablename\n"; 1839 $installer::logger::Lang->print($infoline); 1840 } 1841 1842 if ( $allvariables->{'ADAPRODUCT'} ) 1843 { 1844 $number = get_free_number_in_uisequence_table($installuitable) + 4; 1845 $featurename = get_feature_name("_Adabas", $featuretable); 1846 $line = "MaintenanceAdabas\t\&$featurename\=3 And Installed And Not PATCH\t$number\n"; 1847 push(@{$installuitable} ,$line); 1848 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1849 $infoline = "Added $line into table $installuitablename\n"; 1850 $installer::logger::Lang->print($infoline); 1851 } 1852 1853 if ( $allvariables->{'JAVAPRODUCT'} ) 1854 { 1855 $number = get_free_number_in_uisequence_table($installuitable) + 6; 1856 $featurename = get_feature_name("_Java", $featuretable); 1857 if ( $featurename ) { $line = "MaintenanceJava\t\&$featurename\=3 And Installed And JAVAPATH\=\"\" And Not PATCH\t$number\n"; } 1858 else { $line = "MaintenanceJava\tInstalled And JAVAPATH\=\"\" And Not PATCH\t$number\n"; } # feature belongs to root 1859 push(@{$installuitable} ,$line); 1860 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1861 $infoline = "Added $line into table $installuitablename\n"; 1862 $installer::logger::Lang->print($infoline); 1863 } 1864 1865 if ( $allvariables->{'UREPRODUCT'} ) 1866 { 1867 $number = get_free_number_in_uisequence_table($installuitable) + 8; 1868 $featurename = get_feature_name("_Ure", $featuretable); 1869 if ( $featurename ) { $line = "InstallUre\t\&$featurename\=3 And Not Installed\t$number\n"; } 1870 else { $line = "InstallUre\tNot Installed\t$number\n"; } # feature belongs to root 1871 push(@{$installuitable} ,$line); 1872 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1873 $infoline = "Added $line into table $installuitablename\n"; 1874 $installer::logger::Lang->print($infoline); 1875 } 1876 1877 if ( $allvariables->{'UREPRODUCT'} ) 1878 { 1879 $number = get_free_number_in_uisequence_table($installuitable) + 10; 1880 $featurename = get_feature_name("_Ure", $featuretable); 1881 if ( $featurename ) { $line = "MaintenanceUre\t\&$featurename\=3 And Installed\t$number\n"; } 1882 else { $line = "MaintenanceUre\tInstalled\t$number\n"; } # feature belongs to root 1883 push(@{$installuitable} ,$line); 1884 installer::remover::remove_leading_and_ending_whitespaces(\$line); 1885 $infoline = "Added $line into table $installuitablename\n"; 1886 $installer::logger::Lang->print($infoline); 1887 } 1888 1889 # Content for Feature table, better from scp (translation) 1890 # gm_o_java gm_optional Java 1.4.2 Description 2 200 1891 1892 installer::files::save_file($customactiontablename, $customactiontable); 1893 installer::files::save_file($installuitablename, $installuitable); 1894 installer::files::save_file($featuretablename, $featuretable); 1895 installer::files::save_file($directorytablename, $directorytable); 1896 installer::files::save_file($componenttablename, $componenttable); 1897} 1898 1899################################################################## 1900# Setting the encoding in all idt files. Replacing the 1901# variable WINDOWSENCODINGTEMPLATE 1902################################################################## 1903 1904sub setencoding 1905{ 1906 my ( $languageidtdir, $onelanguage ) = @_; 1907 1908 my $encoding = installer::windows::language::get_windows_encoding($onelanguage); 1909 1910 # collecting all idt files in the directory $languageidtdir and substituting the string 1911 1912 my $idtfiles = installer::systemactions::find_file_with_file_extension("idt", $languageidtdir); 1913 1914 for ( my $i = 0; $i <= $#{$idtfiles}; $i++ ) 1915 { 1916 my $onefilename = $languageidtdir . $installer::globals::separator . ${$idtfiles}[$i]; 1917 my $onefile = installer::files::read_file($onefilename); 1918 1919 for ( my $j = 0; $j <= $#{$onefile}; $j++ ) 1920 { 1921 ${$onefile}[$j] =~ s/WINDOWSENCODINGTEMPLATE/$encoding/g; 1922 } 1923 1924 installer::files::save_file($onefilename, $onefile); 1925 } 1926} 1927 1928################################################################## 1929# Setting the condition, that at least one module is selected. 1930# All modules with flag SHOW_MULTILINGUAL_ONLY were already 1931# collected. In table ControlE.idt, the string 1932# LANGUAGECONDITIONINSTALL needs to be replaced. 1933# Also for APPLICATIONCONDITIONINSTALL for the applications 1934# with flag APPLICATIONMODULE. 1935################################################################## 1936 1937sub set_multilanguageonly_condition 1938{ 1939 my ( $languageidtdir ) = @_; 1940 1941 my $onefilename = $languageidtdir . $installer::globals::separator . "ControlE.idt"; 1942 my $onefile = installer::files::read_file($onefilename); 1943 1944 # Language modules 1945 1946 my $condition = ""; 1947 1948 foreach my $module ( sort keys %installer::globals::multilingual_only_modules ) 1949 { 1950 $condition = $condition . " &$module=3 Or"; 1951 } 1952 1953 $condition =~ s/^\s*//; 1954 $condition =~ s/\s*Or\s*$//; # removing the ending "Or" 1955 1956 if ( $condition eq "" ) { $condition = "1"; } 1957 1958 for ( my $j = 0; $j <= $#{$onefile}; $j++ ) 1959 { 1960 ${$onefile}[$j] =~ s/LANGUAGECONDITIONINSTALL/$condition/; 1961 } 1962 1963 # Application modules 1964 1965 $condition = ""; 1966 1967 foreach my $module ( sort keys %installer::globals::application_modules ) 1968 { 1969 $condition = $condition . " &$module=3 Or"; 1970 } 1971 1972 $condition =~ s/^\s*//; 1973 $condition =~ s/\s*Or\s*$//; # removing the ending "Or" 1974 1975 if ( $condition eq "" ) { $condition = "1"; } 1976 1977 for ( my $j = 0; $j <= $#{$onefile}; $j++ ) 1978 { 1979 ${$onefile}[$j] =~ s/APPLICATIONCONDITIONINSTALL/$condition/; 1980 } 1981 1982 installer::files::save_file($onefilename, $onefile); 1983} 1984 1985############################################# 1986# Putting array values into hash 1987############################################# 1988 1989sub fill_assignment_hash 1990{ 1991 my ($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray) = @_; 1992 1993 my $max = $parameter - 1; 1994 1995 if ( $max != $#{$assignmentarray} ) 1996 { 1997 my $definedparameter = $#{$assignmentarray} + 1; 1998 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"); 1999 } 2000 2001 for ( my $i = 0; $i <= $#{$assignmentarray}; $i++ ) 2002 { 2003 my $counter = $i + 1; 2004 my $key = "parameter". $counter; 2005 2006 my $localvalue = ${$assignmentarray}[$i]; 2007 installer::remover::remove_leading_and_ending_quotationmarks(\$localvalue); 2008 $localvalue =~ s/\\\"/\"/g; 2009 $localvalue =~ s/\\\!/\!/g; 2010 $localvalue =~ s/\\\&/\&/g; 2011 $localvalue =~ s/\\\</\</g; 2012 $localvalue =~ s/\\\>/\>/g; 2013 $assignmenthashref->{$key} = $localvalue; 2014 } 2015} 2016 2017########################################################################## 2018# Checking the assignment of a Windows CustomAction and putting it 2019# into a hash 2020########################################################################## 2021 2022sub create_customaction_assignment_hash 2023{ 2024 my ($gid, $name, $key, $assignmentarray) = @_; 2025 2026 my %assignment = (); 2027 my $assignmenthashref = \%assignment; 2028 2029 my $tablename = ${$assignmentarray}[0]; 2030 installer::remover::remove_leading_and_ending_quotationmarks(\$tablename); 2031 2032 my $tablename_defined = 0; 2033 my $parameter = 0; 2034 2035 if ( $tablename eq "InstallUISequence" ) 2036 { 2037 $tablename_defined = 1; 2038 $parameter = 3; 2039 fill_assignment_hash($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray); 2040 } 2041 2042 if ( $tablename eq "InstallExecuteSequence" ) 2043 { 2044 $tablename_defined = 1; 2045 $parameter = 3; 2046 fill_assignment_hash($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray); 2047 } 2048 2049 if ( $tablename eq "AdminExecuteSequence" ) 2050 { 2051 $tablename_defined = 1; 2052 $parameter = 3; 2053 fill_assignment_hash($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray); 2054 } 2055 2056 if ( $tablename eq "ControlEvent" ) 2057 { 2058 $tablename_defined = 1; 2059 $parameter = 7; 2060 fill_assignment_hash($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray); 2061 } 2062 2063 if ( $tablename eq "ControlCondition" ) 2064 { 2065 $tablename_defined = 1; 2066 $parameter = 5; 2067 fill_assignment_hash($gid, $name, $key, $assignmenthashref, $parameter, $tablename, $assignmentarray); 2068 } 2069 2070 if ( ! $tablename_defined ) 2071 { 2072 installer::exiter::exit_program("ERROR: gid: $gid, key: $key ! Unknown Windows CustomAction table: $tablename ! Currently supported: InstallUISequence, InstallExecuteSequence, ControlEvent, ControlCondition", "create_customaction_assignment_hash"); 2073 } 2074 2075 return $assignmenthashref; 2076} 2077 2078########################################################################## 2079# Finding the position of a specified CustomAction. 2080# If the CustomAction is not found, the return value is "-1". 2081# If the CustomAction position is not defined yet, 2082# the return value is also "-1". 2083########################################################################## 2084 2085sub get_customaction_position 2086{ 2087 my ($action, $sequencetable) = @_; 2088 2089 my $position = -1; 2090 2091 for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) 2092 { 2093 my $line = ${$sequencetable}[$i]; 2094 2095 if ( $line =~ /^\s*([\w\.]+)\t.*\t\s*(\d+)\s$/ ) # matching only, if position is a number! 2096 { 2097 my $compareaction = $1; 2098 my $localposition = $2; 2099 2100 if ( $compareaction eq $action ) 2101 { 2102 $position = $localposition; 2103 last; 2104 } 2105 } 2106 } 2107 2108 return $position; 2109} 2110 2111########################################################################## 2112# Setting the position of CustomActions in sequence tables. 2113# Replacing all occurences of "POSITIONTEMPLATE_" 2114########################################################################## 2115 2116sub set_positions_in_table 2117{ 2118 my ( $sequencetable, $tablename ) = @_; 2119 2120 $installer::logger::Lang->print("\n"); 2121 $installer::logger::Lang->printf("Setting positions in table \"%s\".\n", $tablename); 2122 2123 # Step 1: Resolving all occurences of "POSITIONTEMPLATE_end" 2124 2125 my $lastposition = get_last_position_in_sequencetable($sequencetable); 2126 2127 for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) 2128 { 2129 if ( ${$sequencetable}[$i] =~ /^\s*([\w\.]+)\t.*\t\s*POSITIONTEMPLATE_end\s*$/ ) 2130 { 2131 my $customaction = $1; 2132 $lastposition = $lastposition + 25; 2133 ${$sequencetable}[$i] =~ s/POSITIONTEMPLATE_end/$lastposition/; 2134 $infoline = "Setting position \"$lastposition\" for custom action \"$customaction\".\n"; 2135 $installer::logger::Lang->print($infoline); 2136 } 2137 } 2138 2139 # Step 2: Resolving all occurences of "POSITIONTEMPLATE_abc" or "POSITIONTEMPLATE_behind_abc" 2140 # where abc is the name of the reference Custom Action. 2141 # This has to be done, until there is no more occurence of POSITIONTEMPLATE (success) 2142 # or there is no replacement in one circle (failure). 2143 2144 my $template_exists = 0; 2145 my $template_replaced = 0; 2146 my $counter = 0; 2147 2148 do 2149 { 2150 $template_exists = 0; 2151 $template_replaced = 0; 2152 $counter++; 2153 2154 for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) 2155 { 2156 if ( ${$sequencetable}[$i] =~ /^\s*([\w\.]+)\t.*\t\s*(POSITIONTEMPLATE_.*?)\s*$/ ) 2157 { 2158 my $onename = $1; 2159 my $templatename = $2; 2160 my $positionname = $templatename; 2161 my $customaction = $templatename; 2162 $customaction =~ s/POSITIONTEMPLATE_//; 2163 $template_exists = 1; 2164 2165 # Trying to find the correct number. 2166 # This can fail, if the custom action has no number 2167 2168 my $setbehind = 0; 2169 if ( $customaction =~ /^\s*behind_(.*?)\s*$/ ) 2170 { 2171 $customaction = $1; 2172 $setbehind = 1; 2173 } 2174 2175 my $position = get_customaction_position($customaction, $sequencetable); 2176 2177 if ( $position >= 0 ) # Found CustomAction and is has a position. Otherwise return value is "-1". 2178 { 2179 my $newposition = 0; 2180 if ( $setbehind ) { $newposition = $position + 2; } 2181 else { $newposition = $position - 2; } 2182 ${$sequencetable}[$i] =~ s/$templatename/$newposition/; 2183 $template_replaced = 1; 2184 $infoline = "Setting position \"$newposition\" for custom action \"$onename\" (scp: \"$positionname\" at position $position).\n"; 2185 $installer::logger::Lang->print($infoline); 2186 } 2187 else 2188 { 2189 $infoline = "Could not assign position for custom action \"$onename\" yet (scp: \"$positionname\").\n"; 2190 $installer::logger::Lang->print($infoline); 2191 } 2192 } 2193 } 2194 } while (( $template_exists ) && ( $template_replaced )); 2195 2196 # An error occured, because templates still exist, but could not be replaced. 2197 # Reason: 2198 # 1. Wrong name of CustomAction in scp2 (typo?) 2199 # 2. Circular dependencies of CustomActions (A after B and B after A) 2200 2201 # Problem: It is allowed, that a CustomAction is defined in scp2 in a library that is 2202 # part of product ABC, but this CustomAction is not used in this product 2203 # and the reference CustomAction is not part of this product. 2204 # Therefore this cannot be an error, but only produce a warning. The assigned number 2205 # must be the last sequence number. 2206 2207 if (( $template_exists ) && ( ! $template_replaced )) 2208 { 2209 # Giving a precise error message, collecting all unresolved templates 2210 # my $templatestring = ""; 2211 2212 for ( my $i = 0; $i <= $#{$sequencetable}; $i++ ) 2213 { 2214 if ( ${$sequencetable}[$i] =~ /^\s*([\w\.]+)\t.*\t\s*(POSITIONTEMPLATE_.*?)\s*$/ ) 2215 { 2216 my $customactionname = $1; 2217 my $fulltemplate = $2; 2218 my $template = $fulltemplate; 2219 $template =~ s/POSITIONTEMPLATE_//; 2220 # my $newstring = $customactionname . " (" . $template . ")"; 2221 # $templatestring = $templatestring . $newstring . ", "; 2222 # Setting at the end! 2223 $lastposition = $lastposition + 25; 2224 ${$sequencetable}[$i] =~ s/$fulltemplate/$lastposition/; 2225 $infoline = "WARNING: Setting position \"$lastposition\" for custom action \"$customactionname\". Could not find CustomAction \"$template\".\n"; 2226 $installer::logger::Lang->print($infoline); 2227 } 2228 } 2229 # $templatestring =~ s/,\s*$//; 2230 2231 # $infoline = "Error: Saving table \"$tablename\"\n"; 2232 # $installer::logger::Lang->print($infoline); 2233 # print $infoline; 2234 # installer::files::save_file($tablename, $sequencetable); 2235 # installer::exiter::exit_program("ERROR: Unresolved positions in CustomActions in scp2: $templatestring", "set_positions_in_table"); 2236 } 2237} 2238 2239########################################################################## 2240# Setting the Windows custom actions into different tables 2241# CustomAc.idt, InstallE.idt, InstallU.idt, ControlE.idt, ControlC.idt 2242########################################################################## 2243 2244sub addcustomactions 2245{ 2246 my ($languageidtdir, $customactions, $filesarray) = @_; 2247 2248 $installer::logger::Lang->print("\n"); 2249 $installer::logger::Lang->add_timestamp("Performance Info: addcustomactions start\n"); 2250 2251 my $customactionidttablename = $languageidtdir . $installer::globals::separator . "CustomAc.idt"; 2252 my $customactionidttable = installer::files::read_file($customactionidttablename); 2253 my $installexecutetablename = $languageidtdir . $installer::globals::separator . "InstallE.idt"; 2254 my $installexecutetable = installer::files::read_file($installexecutetablename); 2255 my $adminexecutetablename = $languageidtdir . $installer::globals::separator . "AdminExe.idt"; 2256 my $adminexecutetable = installer::files::read_file($adminexecutetablename); 2257 my $installuitablename = $languageidtdir . $installer::globals::separator . "InstallU.idt"; 2258 my $installuitable = installer::files::read_file($installuitablename); 2259 my $controleventtablename = $languageidtdir . $installer::globals::separator . "ControlE.idt"; 2260 my $controleventtable = installer::files::read_file($controleventtablename); 2261 my $controlconditiontablename = $languageidtdir . $installer::globals::separator . "ControlC.idt"; 2262 my $controlconditiontable = installer::files::read_file($controlconditiontablename); 2263 2264 # Iterating over all Windows custom actions 2265 2266 for ( my $i = 0; $i <= $#{$customactions}; $i++ ) 2267 { 2268 my $customaction = ${$customactions}[$i]; 2269 my $name = $customaction->{'Name'}; 2270 my $typ = $customaction->{'Typ'}; 2271 my $source = $customaction->{'Source'}; 2272 my $target = $customaction->{'Target'}; 2273 my $inbinarytable = $customaction->{'Inbinarytable'}; 2274 my $gid = $customaction->{'gid'}; 2275 2276 my $styles = ""; 2277 if ( $customaction->{'Styles'} ) { $styles = $customaction->{'Styles'}; } 2278 2279 my $added_customaction = set_custom_action($customactionidttable, $name, $typ, $source, $target, $inbinarytable, $filesarray, $customactionidttablename, $styles); 2280 2281 if ( $added_customaction ) 2282 { 2283 # If the CustomAction was added into the CustomAc.idt, it can be connected to the installation. 2284 # There are currently two different ways for doing this: 2285 # 1. Using "add_custom_action_to_install_table", which adds the CustomAction to the install sequences, 2286 # which are saved in InstallE.idt and InstallU.idt 2287 # 2. Using "connect_custom_action_to_control" and "connect_custom_action_to_control". The first method 2288 # connects a CustomAction to a control in ControlE.idt. The second method sets a condition for a control, 2289 # which might be influenced by the CustomAction. This happens in ControlC.idt. 2290 2291 # Any Windows CustomAction can have a lot of different assignments. 2292 2293 for ( my $j = 1; $j <= 50; $j++ ) 2294 { 2295 my $key = "Assignment" . $j; 2296 my $value = ""; 2297 if ( $customaction->{$key} ) 2298 { 2299 $value = $customaction->{$key}; 2300 2301 # in a patch the Assignment can be overwritten by a PatchAssignment 2302 if ( $installer::globals::patch ) 2303 { 2304 $patchkey = "PatchAssignment" . $j; 2305 if ( $customaction->{$patchkey} ) 2306 { 2307 $value = $customaction->{$patchkey}; 2308 $key = $patchkey; 2309 } 2310 } 2311 2312 } 2313 else { last; } 2314 2315 # $value is now a comma separated list 2316 if ( $value =~ /^\s*\(\s*(.*)\s*\);?\s*$/ ) { $value = $1; } 2317 my $assignmentarray = installer::converter::convert_stringlist_into_array(\$value, ","); 2318 my $assignment = create_customaction_assignment_hash($gid, $name, $key, $assignmentarray); 2319 2320 if ( $assignment->{'parameter1'} eq "InstallExecuteSequence" ) 2321 { 2322 add_custom_action_to_install_table($installexecutetable, $source, $name, $assignment->{'parameter2'}, $assignment->{'parameter3'}, $filesarray, $installexecutetablename, $styles); 2323 } 2324 elsif ( $assignment->{'parameter1'} eq "AdminExecuteSequence" ) 2325 { 2326 add_custom_action_to_install_table($adminexecutetable, $source, $name, $assignment->{'parameter2'}, $assignment->{'parameter3'}, $filesarray, $adminexecutetablename, $styles); 2327 } 2328 elsif ( $assignment->{'parameter1'} eq "InstallUISequence" ) 2329 { 2330 add_custom_action_to_install_table($installuitable, $source, $name, $assignment->{'parameter2'}, $assignment->{'parameter3'}, $filesarray, $installuitablename, $styles); 2331 } 2332 elsif ( $assignment->{'parameter1'} eq "ControlEvent" ) 2333 { 2334 connect_custom_action_to_control($controleventtable, $controleventtablename, $assignment->{'parameter2'}, $assignment->{'parameter3'}, $assignment->{'parameter4'}, $assignment->{'parameter5'}, $assignment->{'parameter6'}, $assignment->{'parameter7'}); 2335 } 2336 elsif ( $assignment->{'parameter1'} eq "ControlCondition" ) 2337 { 2338 connect_condition_to_control($controlconditiontable, $controlconditiontablename, $assignment->{'parameter2'}, $assignment->{'parameter3'}, $assignment->{'parameter4'}, $assignment->{'parameter5'}); 2339 } 2340 else 2341 { 2342 installer::exiter::exit_program("ERROR: gid: $gid, key: $key ! Unknown Windows CustomAction table: $assignmenthashref->{'parameter1'} ! Currently supported: InstallUISequence, InstallESequence, ControlEvent, ControlCondition", "addcustomactions"); 2343 } 2344 } 2345 } 2346 } 2347 2348 # Setting the positions in the tables 2349 2350 set_positions_in_table($installexecutetable, $installexecutetablename); 2351 set_positions_in_table($installuitable, $installuitablename); 2352 set_positions_in_table($adminexecutetable, $adminexecutetablename); 2353 2354 # Saving the files 2355 2356 installer::files::save_file($customactionidttablename, $customactionidttable); 2357 installer::files::save_file($installexecutetablename, $installexecutetable); 2358 installer::files::save_file($adminexecutetablename, $adminexecutetable); 2359 installer::files::save_file($installuitablename, $installuitable); 2360 installer::files::save_file($controleventtablename, $controleventtable); 2361 installer::files::save_file($controlconditiontablename, $controlconditiontable); 2362 2363 my $infoline = "Updated idt file: $customactionidttablename\n"; 2364 $installer::logger::Lang->print($infoline); 2365 $infoline = "Updated idt file: $installexecutetablename\n"; 2366 $installer::logger::Lang->print($infoline); 2367 $infoline = "Updated idt file: $adminexecutetablename\n"; 2368 $installer::logger::Lang->print($infoline); 2369 $infoline = "Updated idt file: $installuitablename\n"; 2370 $installer::logger::Lang->print($infoline); 2371 $infoline = "Updated idt file: $controleventtablename\n"; 2372 $installer::logger::Lang->print($infoline); 2373 $infoline = "Updated idt file: $controlconditiontablename\n"; 2374 $installer::logger::Lang->print($infoline); 2375 2376 $installer::logger::Lang->print("\n"); 2377 $installer::logger::Lang->add_timestamp("Performance Info: addcustomactions end\n"); 2378} 2379 2380########################################################################## 2381# Setting bidi attributes in idt tables 2382########################################################################## 2383 2384sub setbidiattributes 2385{ 2386 my ($languageidtdir, $onelanguage) = @_; 2387 2388 # Editing the files Dialog.idt and Control.idt 2389 2390 my $dialogfilename = $languageidtdir . $installer::globals::separator . "Dialog.idt"; 2391 my $controlfilename = $languageidtdir . $installer::globals::separator . "Control.idt"; 2392 2393 my $dialogfile = installer::files::read_file($dialogfilename); 2394 my $controlfile = installer::files::read_file($controlfilename); 2395 2396 # Searching attributes in Dialog.idt and adding "896". 2397 # Attributes are in column 6 (from 10). 2398 2399 my $bidiattribute = 896; 2400 for ( my $i = 0; $i <= $#{$dialogfile}; $i++ ) 2401 { 2402 if ( $i < 3 ) { next; } 2403 if ( ${$dialogfile}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 2404 { 2405 my $one = $1; 2406 my $two = $2; 2407 my $three = $3; 2408 my $four = $4; 2409 my $five = $5; 2410 my $attribute = $6; 2411 my $seven = $7; 2412 my $eight = $8; 2413 $attribute = $attribute + $bidiattribute; 2414 ${$dialogfile}[$i] = "$one\t$two\t$three\t$four\t$five\t$attribute\t$seven\t$eight\n"; 2415 } 2416 } 2417 2418 # Searching attributes in Control.idt and adding "224". 2419 # Attributes are in column 8 (from 12). 2420 2421 $bidiattribute = 224; 2422 for ( my $i = 0; $i <= $#{$controlfile}; $i++ ) 2423 { 2424 if ( $i < 3 ) { next; } 2425 if ( ${$controlfile}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 2426 { 2427 my $one = $1; 2428 my $two = $2; 2429 my $three = $3; 2430 my $four = $4; 2431 my $five = $5; 2432 my $six = $6; 2433 my $seven = $7; 2434 my $attribute = $8; 2435 my $nine = $9; 2436 my $ten = $10; 2437 my $eleven = $11; 2438 my $twelve = $12; 2439 $attribute = $attribute + $bidiattribute; 2440 ${$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"; 2441 } 2442 } 2443 2444 # Saving the file 2445 2446 installer::files::save_file($dialogfilename, $dialogfile); 2447 $infoline = "Set bidi support in idt file \"$dialogfilename\" for language $onelanguage\n"; 2448 $installer::logger::Lang->print($infoline); 2449 2450 installer::files::save_file($controlfilename, $controlfile); 2451 $infoline = "Set bidi support in idt file \"$controlfilename\" for language $onelanguage\n"; 2452 $installer::logger::Lang->print($infoline); 2453} 2454 24551; 2456