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