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 22package installer::windows::directory; 23 24use installer::exiter; 25use installer::files; 26use installer::globals; 27use installer::pathanalyzer; 28use installer::windows::idtglobal; 29use installer::windows::msiglobal; 30use installer::scriptitems; 31 32use strict; 33 34############################################################## 35# Collecting all directory trees in global hash 36############################################################## 37 38sub collectdirectorytrees 39{ 40 my ( $directoryref ) = @_; 41 42 for ( my $i = 0; $i <= $#{$directoryref}; $i++ ) 43 { 44 my $onedir = ${$directoryref}[$i]; 45 my $styles = ""; 46 if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; } 47 48 if ( $styles ne "" ) 49 { 50 foreach my $treestyle ( keys %installer::globals::treestyles ) 51 { 52 if ( $styles =~ /\b$treestyle\b/ ) 53 { 54 my $hostname = $onedir->{'HostName'}; 55 # -> hostname is the key, the style the value! 56 $installer::globals::hostnametreestyles{$hostname} = $treestyle; 57 } 58 } 59 } 60 } 61} 62 63############################################################## 64# Overwriting global programfilesfolder, if required 65############################################################## 66 67sub overwrite_programfilesfolder 68{ 69 my ( $allvariables ) = @_; 70 71 if ( $allvariables->{'PROGRAMFILESFOLDERNAME'} ) 72 { 73 $installer::globals::programfilesfolder = $allvariables->{'PROGRAMFILESFOLDERNAME'}; 74 } 75} 76 77=head2 make_short_dir_version($longstring) 78 79 Transform the given string into one that is at most 70 characters long. 80 That is done in two steps: 81 - Cut all parts separated by '_' or '-' down to a length of 5. 82 - Cut down the result to a length of 60 and fill it up to length 70 83 with the MD5 checksum. 84 85 This transform always returns the same result for the same string. 86 There is no counter and reference to a global set of names to make the string unique. 87 88=cut 89sub make_short_dir_version ($) 90{ 91 my ($longstring) = @_; 92 93 my $shortstring = ""; 94 my $cutlength = 60; 95 my $length = 5; # So the directory can still be recognized 96 my $longstring_save = $longstring; 97 98 # Splitting the string at each "underline" and allowing only $length characters per directory name. 99 # Checking also uniqueness and length. 100 101 my @outer_parts = split(/_/, $longstring); 102 foreach my $onestring (@outer_parts) 103 { 104 my $partstring = ""; 105 106 if ( $onestring =~ /\-/ ) 107 { 108 my @inner_parts = split(/-/, $onestring); 109 @inner_parts = map {substr($_,0,$length)} @inner_parts; 110 $partstring = join("-", @inner_parts); 111 $partstring =~ s/^\s*\-//; 112 } 113 else 114 { 115 $partstring = substr($onestring, 0, $length); 116 } 117 118 $shortstring .= "_" . $partstring; 119 } 120 121 $shortstring =~ s/^\s*\_//; 122 123 # Setting unique ID to each directory 124 # No counter allowed, process must be absolute reproducible due to patch creation process. 125 126 my $subid = installer::windows::msiglobal::calculate_id($longstring_save, 9); # taking only the first 9 digits 127 $shortstring = substr($shortstring, 0, $cutlength) . "_" . $subid; 128 129 return $shortstring; 130} 131 132=head2 get_unique_name ($hostname, $unique_map, $shortdirhash, $shortdirhashreverse) 133 134 Return a long and a short unique name for the given $hostname. 135 Despite the function name and unlike the generation of unique 136 names for files, the returned names are not really unique. Quite 137 the opposite. The returned names are guaranteed to return the 138 same result for the same input. 139 140 The returned short name has at most length 70. 141 142=cut 143sub get_unique_name ($$) 144{ 145 my ($hostname, $hostnamehash) = @_; 146 147 # Make sure that we where not called for this hostname before. Otherwise the other test would be triggered. 148 if (defined $hostnamehash->{$hostname}) 149 { 150 installer::exiter::exit_program( 151 "ERROR: get_unique_name was already called for hostname ".$hostname, 152 "get_unique_name"); 153 } 154 $hostnamehash->{$hostname} = 1; 155 156 my $uniquename = $hostname; 157 158 $uniquename =~ s/^\s*//g; # removing beginning white spaces 159 $uniquename =~ s/\s*$//g; # removing ending white spaces 160 $uniquename =~ s/\s//g; # removing white spaces 161 $uniquename =~ s/\_//g; # removing existing underlines 162 $uniquename =~ s/\.//g; # removing dots in directoryname 163 $uniquename =~ s/OpenOffice/OO/g; 164 165 $uniquename =~ s/\Q$installer::globals::separator\E/\_/g; # replacing slash and backslash with underline 166 167 $uniquename =~ s/_registry/_rgy/g; 168 $uniquename =~ s/_registration/_rgn/g; 169 $uniquename =~ s/_extension/_ext/g; 170 $uniquename =~ s/_frame/_frm/g; 171 $uniquename =~ s/_table/_tbl/g; 172 $uniquename =~ s/_chart/_crt/g; 173 174 my $short_uniquename = make_short_dir_version($uniquename); 175 176 return ($uniquename, $short_uniquename); 177} 178 179=head2 check_unique_directorynames($directories) 180 181 The one really important check is made in get_unique_name(). It 182 checks that get_unique_name() is not called twice for the same 183 directory host name. The tests in this function contain the 184 legacy tests that basically only check if there where a collision 185 of the partial MD5 sum that is used to make the short unique names 186 unique. 187 188 The maps $unique_map, $shortdirhash, $shortdirhashreverse are used 189 only to check that _different_ input names are mapped to different 190 results. They are not used to influence the result. That assumes 191 that this function is called only once for every directory 192 hostname. 193=cut 194sub check_unique_directorynames ($) 195{ 196 my ($directories) = @_; 197 198 my %completedirhashstep1 = (); 199 my %shortdirhash = (); 200 my %shortdirhashreverse = (); 201 202 # Check unique name of directories. 203 foreach my $directory (@$directories) 204 { 205 my ($long_uniquename, $short_uniquename) = ($directory->{'long_uniquename'}, $directory->{'uniquename'}); 206 207 # The names after this small changes must still be unique! 208 if (exists($completedirhashstep1{$long_uniquename})) 209 { 210 installer::exiter::exit_program( 211 sprintf("ERROR: Unallowed modification of directory name, not unique (step 1): \"%s\".", 212 $short_uniquename), 213 "check_unique_directorynames"); 214 } 215 $completedirhashstep1{$long_uniquename} = 1; 216 217 # Checking if the same directory already exists, but has another short version. 218 if (exists($shortdirhash{$long_uniquename}) 219 && ( $shortdirhash{$long_uniquename} ne $short_uniquename )) 220 { 221 installer::exiter::exit_program( 222 sprintf( 223 "ERROR: Unallowed modification of directory name, not unique (step 2A): \"%s\".", 224 $short_uniquename), 225 "check_unique_directorynames"); 226 } 227 $shortdirhash{$long_uniquename} = $short_uniquename; 228 229 # Also checking vice versa 230 # Checking if the same short directory already exists, but has another long version. 231 if (exists($shortdirhashreverse{$short_uniquename}) 232 && ( $shortdirhashreverse{$short_uniquename} ne $long_uniquename )) 233 { 234 installer::exiter::exit_program( 235 sprintf( 236 "ERROR: Unallowed modification of directory name, not unique (step 2B): \"%s\".", 237 $short_uniquename), 238 "check_unique_directorynames"); 239 } 240 $shortdirhashreverse{$short_uniquename} = $long_uniquename; 241 } 242 243 # Check unique name of parents 244 foreach my $directory (@$directories) 245 { 246 my ($long_uniquename, $short_uniquename) 247 = ($directory->{'long_uniqueparentname'}, $directory->{'uniqueparentname'}); 248 249 # Again checking if the same directory already exists, but has another short version. 250 if (exists($shortdirhash{$long_uniquename}) 251 && ( $shortdirhash{$long_uniquename} ne $short_uniquename )) 252 { 253 installer::exiter::exit_program( 254 sprintf( 255 "ERROR: Unallowed modification of directory name, not unique (step 3A): \"%s\".", 256 $short_uniquename), 257 "check_unique_directorynames"); 258 } 259 $shortdirhash{$long_uniquename} = $short_uniquename; 260 261 # Also checking vice versa 262 # Checking if the same short directory already exists, but has another long version. 263 if (exists($shortdirhashreverse{$short_uniquename}) 264 && ( $shortdirhashreverse{$short_uniquename} ne $long_uniquename )) 265 { 266 installer::exiter::exit_program( 267 sprintf( 268 "ERROR: Unallowed modification of directory name, not unique (step 3B): \"%s\".", 269 $short_uniquename), 270 "check_unique_directorynames"); 271 } 272 $shortdirhashreverse{$short_uniquename} = $long_uniquename; 273 } 274} 275 276sub get_unique_parent_name ($$) 277{ 278 my ($uniqueparentname, $styles) = @_; 279 280 my $keepparent = 1; 281 282 if ( $uniqueparentname =~ /^\s*(.*)\_(.*?)\s*$/ ) # the underline is now the separator 283 { 284 $uniqueparentname = $1; 285 $keepparent = 0; 286 } 287 else 288 { 289 $uniqueparentname = $installer::globals::programfilesfolder; 290 $keepparent = 1; 291 } 292 293 if ( $styles =~ /\bPROGRAMFILESFOLDER\b/ ) 294 { 295 $uniqueparentname = $installer::globals::programfilesfolder; 296 $keepparent = 1; 297 } 298 if ( $styles =~ /\bCOMMONFILESFOLDER\b/ ) 299 { 300 $uniqueparentname = $installer::globals::commonfilesfolder; 301 $keepparent = 1; 302 } 303 if ( $styles =~ /\bCOMMONAPPDATAFOLDER\b/ ) 304 { 305 $uniqueparentname = $installer::globals::commonappdatafolder; 306 $keepparent = 1; 307 } 308 if ( $styles =~ /\bLOCALAPPDATAFOLDER\b/ ) 309 { 310 $uniqueparentname = $installer::globals::localappdatafolder; 311 $keepparent = 1; 312 } 313 314 if ( $styles =~ /\bSHAREPOINTPATH\b/ ) 315 { 316 $uniqueparentname = "SHAREPOINTPATH"; 317 $installer::globals::usesharepointpath = 1; 318 $keepparent = 1; 319 } 320 321 # also setting short directory name for the parent 322 323 my $originaluniqueparentname = $uniqueparentname; 324 325 if ( ! $keepparent ) 326 { 327 $uniqueparentname = make_short_dir_version($uniqueparentname); 328 } 329 330 return ($originaluniqueparentname, $uniqueparentname); 331} 332 333############################################################## 334# Adding unique directory names to the directory collection 335############################################################## 336 337sub create_unique_directorynames ($) 338{ 339 my ($directories) = @_; 340 341 $installer::globals::officeinstalldirectoryset = 0; 342 343 my %hostnamehash = (); 344 my $infoline = ""; 345 my $errorcount = 0; 346 347 foreach my $directory (@$directories) 348 { 349 next if defined $directory->{'uniquename'}; 350 351 my $styles = $directory->{'Styles'}; 352 $styles = "" unless defined $styles; 353 354 my ($originaluniquename, $uniquename) = get_unique_name( 355 $directory->{'HostName'}, 356 \%hostnamehash); 357 358 my ($originaluniqueparentname, $uniqueparentname) = get_unique_parent_name( 359 $originaluniquename, 360 $styles); 361 362 # Hyphen not allowed in database 363 $uniquename =~ s/\-/\_/g; # making "-" to "_" 364 $uniqueparentname =~ s/\-/\_/g; # making "-" to "_" 365 366 # And finally setting the values for the directories 367 $directory->{'uniquename'} = $uniquename; 368 $directory->{'uniqueparentname'} = $uniqueparentname; 369 $directory->{'long_uniquename'} = $originaluniquename; 370 $directory->{'long_uniqueparentname'} = $originaluniqueparentname; 371 } 372 373 # Find the installation directory. 374 foreach my $directory (@$directories) 375 { 376 next unless defined $directory->{'Styles'}; 377 378 # setting the installlocation directory 379 next unless $directory->{'Styles'} =~ /\bISINSTALLLOCATION\b/; 380 381 if ( $installer::globals::installlocationdirectoryset ) 382 { 383 installer::exiter::exit_program( 384 sprintf( 385 "ERROR: Directory with flag ISINSTALLLOCATION alread set: \"%s\".", 386 $installer::globals::installlocationdirectory), 387 "create_unique_directorynames"); 388 } 389 390 $installer::globals::installlocationdirectory = $directory->{'uniquename'}; 391 $installer::globals::installlocationdirectoryset = 1; 392 } 393} 394 395##################################################### 396# Adding ":." to selected default directory names 397##################################################### 398 399sub update_defaultdir ($$) 400{ 401 my ( $onedir, $allvariableshashref ) = @_; 402 403 if ($installer::globals::addchildprojects 404 || $installer::globals::patch 405 || $installer::globals::languagepack 406 || $allvariableshashref->{'CHANGETARGETDIR'}) 407 { 408 my $sourcediraddon = "\:\."; 409 return $onedir->{'defaultdir'} . $sourcediraddon; 410 } 411 else 412 { 413 return $onedir->{'defaultdir'}; 414 } 415} 416 417##################################################### 418# The directory with the style ISINSTALLLOCATION 419# will be replaced by INSTALLLOCATION 420##################################################### 421 422sub set_installlocation_directory 423{ 424 my ( $directoryref, $allvariableshashref ) = @_; 425 426 if ( ! $installer::globals::installlocationdirectoryset ) 427 { 428 installer::exiter::exit_program( 429 "ERROR: Directory with flag ISINSTALLLOCATION not set!", 430 "set_installlocation_directory"); 431 } 432 433 for ( my $i = 0; $i <= $#{$directoryref}; $i++ ) 434 { 435 my $onedir = ${$directoryref}[$i]; 436 437 if ( $onedir->{'uniquename'} eq $installer::globals::installlocationdirectory ) 438 { 439 $onedir->{'uniquename'} = "INSTALLLOCATION"; 440 $onedir->{'defaultdir'} = update_defaultdir($onedir, $allvariableshashref); 441 } 442 443 if ( $onedir->{'uniquename'} eq $installer::globals::vendordirectory ) 444 { 445 $onedir->{'defaultdir'} = update_defaultdir($onedir, $allvariableshashref); 446 } 447 448 if ( $onedir->{'uniqueparentname'} eq $installer::globals::installlocationdirectory ) 449 { 450 $onedir->{'uniqueparentname'} = "INSTALLLOCATION"; 451 } 452 } 453} 454 455##################################################### 456# Getting the name of the top level directory. This 457# can have only one letter 458##################################################### 459 460sub get_last_directory_name 461{ 462 my ($completepathref) = @_; 463 464 if ( $$completepathref =~ /^.*[\/\\](.+?)\s*$/ ) 465 { 466 $$completepathref = $1; 467 } 468} 469 470sub setup_global_font_directory_name ($) 471{ 472 my ($directories) = @_; 473 474 foreach my $directory (@$directories) 475 { 476 next unless defined $directory->{'Dir'}; 477 next unless defined $directory->{'defaultdir'}; 478 479 next if $directory->{'Dir'} ne "PREDEFINED_OSSYSTEMFONTDIR"; 480 next if $directory->{'defaultdir'} ne $installer::globals::fontsdirhostname; 481 482 $installer::globals::fontsdirname = $installer::globals::fontsdirhostname; 483 $installer::globals::fontsdirparent = $directory->{'uniqueparentname'}; 484 485 $installer::logger::Info->printf("%s, fdhn %s, dd %s, ipn %s, HN %s\n", 486 "PREDEFINED_OSSYSTEMFONTDIR", 487 $installer::globals::fontsdirhostname, 488 $directory->{'defaultdir'}, 489 $directory->{'uniqueparentname'}, 490 $directory->{'HostName'}); 491 installer::scriptitems::print_script_item($directory); 492 } 493} 494 495##################################################### 496# Creating the defaultdir for the file Director.idt 497##################################################### 498 499sub create_defaultdir_directorynames ($) 500{ 501 my ($directoryref) = @_; 502 503 my @shortnames = (); 504 if ( $installer::globals::prepare_winpatch ) { @shortnames = values(%installer::globals::saved83dirmapping); } 505 506 for ( my $i = 0; $i <= $#{$directoryref}; $i++ ) 507 { 508 my $onedir = ${$directoryref}[$i]; 509 my $hostname = $onedir->{'HostName'}; 510 511 $hostname =~ s/\Q$installer::globals::separator\E\s*$//; 512 get_last_directory_name(\$hostname); 513 # installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$hostname); # making program/classes to classes 514 my $uniquename = $onedir->{'uniquename'}; 515 my $shortstring; 516 if (( $installer::globals::prepare_winpatch ) && ( exists($installer::globals::saved83dirmapping{$uniquename}) )) 517 { 518 $shortstring = $installer::globals::saved83dirmapping{$uniquename}; 519 } 520 else 521 { 522 $shortstring = installer::windows::idtglobal::make_eight_three_conform($hostname, "dir", \@shortnames); 523 } 524 525 my $defaultdir; 526 527 if ( $shortstring eq $hostname ) 528 { 529 $defaultdir = $hostname; 530 } 531 else 532 { 533 $defaultdir = $shortstring . "|" . $hostname; 534 } 535 536 $onedir->{'defaultdir'} = $defaultdir; 537 } 538} 539 540############################################### 541# Fill content into the directory table 542############################################### 543 544sub create_directorytable_from_collection ($$) 545{ 546 my ($directorytableref, $directoryref) = @_; 547 548 foreach my $onedir (@$directoryref) 549 { 550 # Remove entries for special directories. 551 if (defined $onedir->{'HostName'} 552 && $onedir->{'HostName'} eq "" 553 && defined $onedir->{'Dir'} 554 && $onedir->{'Dir'} eq "PREDEFINED_PROGDIR") 555 { 556 next; 557 } 558 559 my $oneline = sprintf( 560 "%s\t%s\t%s\n", 561 $onedir->{'uniquename'}, 562 $onedir->{'uniqueparentname'}, 563 $onedir->{'defaultdir'}); 564 565 push @{$directorytableref}, $oneline; 566 } 567} 568 569############################################### 570# Defining the root installation structure 571############################################### 572 573sub process_root_directories ($$) 574{ 575 my ($allvariableshashref, $functor) = @_; 576 577 my $oneline = ""; 578 579 if (( ! $installer::globals::patch ) && ( ! $installer::globals::languagepack ) && ( ! $allvariableshashref->{'DONTUSESTARTMENUFOLDER'} )) 580 { 581 my $productname = $allvariableshashref->{'PRODUCTNAME'}; 582 my $productversion = $allvariableshashref->{'PRODUCTVERSION'}; 583 my $baseproductversion = $productversion; 584 585 if (( $installer::globals::prepare_winpatch ) && ( $allvariableshashref->{'BASEPRODUCTVERSION'} )) 586 { 587 $baseproductversion = $allvariableshashref->{'BASEPRODUCTVERSION'}; # for example "2.0" for OOo 588 } 589 590 my $realproductkey = $productname . " " . $productversion; 591 my $productkey = $productname . " " . $baseproductversion; 592 593 if (( $allvariableshashref->{'POSTVERSIONEXTENSION'} ) && ( ! $allvariableshashref->{'DONTUSEEXTENSIONINDEFAULTDIR'} )) 594 { 595 $productkey = $productkey . " " . $allvariableshashref->{'POSTVERSIONEXTENSION'}; 596 $realproductkey = $realproductkey . " " . $allvariableshashref->{'POSTVERSIONEXTENSION'}; 597 } 598 if ( $allvariableshashref->{'NOSPACEINDIRECTORYNAME'} ) 599 { 600 $productkey =~ s/\ /\_/g; 601 $realproductkey =~ s/\ /\_/g; 602 } 603 604 my $shortproductkey = installer::windows::idtglobal::make_eight_three_conform($productkey, "dir", undef); 605 $shortproductkey =~ s/\s/\_/g; # changing empty space to underline 606 607 &$functor( 608 $installer::globals::officemenufolder, 609 $installer::globals::programmenufolder, 610 $shortproductkey . "|". $realproductkey); 611 } 612 613 &$functor("TARGETDIR", "", "SourceDir"); 614 &$functor($installer::globals::programfilesfolder, "TARGETDIR", "."); 615 &$functor($installer::globals::programmenufolder, "TARGETDIR", "."); 616 &$functor($installer::globals::startupfolder, "TARGETDIR", "."); 617 &$functor($installer::globals::desktopfolder, "TARGETDIR", "."); 618 &$functor($installer::globals::startmenufolder, "TARGETDIR", "."); 619 &$functor($installer::globals::commonfilesfolder, "TARGETDIR", "."); 620 &$functor($installer::globals::commonappdatafolder, "TARGETDIR", "."); 621 &$functor($installer::globals::localappdatafolder, "TARGETDIR", "."); 622 623 if ( $installer::globals::usesharepointpath ) 624 { 625 &$functor("SHAREPOINTPATH", "TARGETDIR", "."); 626 } 627 628 &$functor($installer::globals::systemfolder, "TARGETDIR", "."); 629 630 my $localtemplatefoldername = $installer::globals::templatefoldername; 631 my $directorytableentry = $localtemplatefoldername; 632 my $shorttemplatefoldername = installer::windows::idtglobal::make_eight_three_conform($localtemplatefoldername, "dir"); 633 if ( $shorttemplatefoldername ne $localtemplatefoldername ) 634 { 635 $directorytableentry = $shorttemplatefoldername . "|" . $localtemplatefoldername; 636 } 637 &$functor($installer::globals::templatefolder, "TARGETDIR", $directorytableentry); 638 639 if ( $installer::globals::fontsdirname ) 640 { 641 &$functor( 642 $installer::globals::fontsfolder, 643 $installer::globals::fontsdirparent, 644 $installer::globals::fontsfoldername . ":" . $installer::globals::fontsdirname); 645 } 646 else 647 { 648 &$functor( 649 $installer::globals::fontsfolder, 650 "TARGETDIR", 651 $installer::globals::fontsfoldername); 652 } 653} 654 655sub find_missing_directories ($$) 656{ 657 my ($directories, $allvariableshashref) = @_; 658 659 # Set up the list of target directories. 660 my %target_directories = map {$_->{'uniquename'} => 1} @$directories; 661 # Add special directories. 662 process_root_directories( 663 $allvariableshashref, 664 sub($$$){ 665 my ($uniquename, $parentname, $defaultdir) = @_; 666 $target_directories{$uniquename} = 1; 667 } 668 ); 669 670 # Set up the list of source directories. 671 my $source_directory_map = $installer::globals::source_msi->GetDirectoryMap(); 672 my $source_file_map = $installer::globals::source_msi->GetFileMap(); 673 my %source_directories = map {$_->{'unique_name'} => $_} values %$source_directory_map; 674 675 # Find the missing source directories. 676 my @missing_directories = (); 677 foreach my $source_uniquename (keys %source_directories) 678 { 679 if ( ! $target_directories{$source_uniquename}) 680 { 681 push @missing_directories, $source_directories{$source_uniquename}; 682 } 683 } 684 685 # Report the missing directories. 686 $installer::logger::Info->printf("found %d missing directories\n", scalar @missing_directories); 687 my $index = 0; 688 foreach my $directory_item (@missing_directories) 689 { 690 # Print information about the directory. 691 $installer::logger::Info->printf("missing directory %d: %s\n", 692 ++$index, 693 $directory_item->{'full_target_long_name'}); 694 while (my($key,$value) = each %$directory_item) 695 { 696 $installer::logger::Info->printf(" %s -> %s\n", $key, $value); 697 } 698 699 # Print the referencing files. 700 my @filenames = (); 701 while (my ($key,$value) = each %$source_file_map) 702 { 703 if ($value->{'directory'}->{'unique_name'} eq $directory_item->{'unique_name'}) 704 { 705 push @filenames, $key; 706 } 707 } 708 $installer::logger::Info->printf(" referencing files are %s\n", join(", ", @filenames)); 709 } 710 711 foreach my $directory (@$directories) 712 { 713 $installer::logger::Lang->printf("target directory %s -> HN %s\n", 714 $directory->{'uniquename'}, 715 $directory->{'HostName'}); 716 installer::scriptitems::print_script_item($directory); 717 } 718 719 # Setup a map of directory uniquenames to verify that the new 720 # entries don't use unique names that are already in use. 721 my %unique_names = map {$_->{'uniquename'} => $_} @$directories; 722 723 # Create script items for the missing directories. 724 my @new_source_directories = (); 725 foreach my $source_directory_item (@missing_directories) 726 { 727 my $new_directory_item = { 728 'uniquename' => $source_directory_item->{'unique_name'}, 729 'uniqueparentname' => $source_directory_item->{'parent_name'}, 730 'defaultdir' => $source_directory_item->{'default_dir'}, 731 'HostName' => $source_directory_item->{'full_target_long_name'}, 732 'componentname' => $source_directory_item->{'component_name'}, 733 }; 734 735 if (defined $unique_names{$new_directory_item->{'uniquename'}}) 736 { 737 installer::logger::PrintError("newly created directory entry collides with existing directory"); 738 last; 739 } 740 741 push @new_source_directories, $new_directory_item; 742 } 743 744 return @new_source_directories; 745} 746 747sub prepare_directory_table_creation ($$) 748{ 749 my ($directories, $allvariableshashref) = @_; 750 751 foreach my $directory (@$directories) 752 { 753 delete $directory->{'uniquename'}; 754 } 755 756 overwrite_programfilesfolder($allvariableshashref); 757 create_unique_directorynames($directories); 758 check_unique_directorynames($directories); 759 create_defaultdir_directorynames($directories); # only destdir! 760 setup_global_font_directory_name($directories); 761 set_installlocation_directory($directories, $allvariableshashref); 762 763 if ($installer::globals::is_release) 764 { 765 my @new_directories = find_missing_directories($directories, $allvariableshashref); 766 push @$directories, @new_directories; 767 } 768} 769 770############################################### 771# Creating the file Director.idt dynamically 772############################################### 773 774sub create_directory_table ($$$) 775{ 776 my ($directoryref, $basedir, $allvariableshashref) = @_; 777 778 # Structure of the directory table: 779 # Directory Directory_Parent DefaultDir 780 # Directory is a unique identifier 781 # Directory_Parent is the unique identifier of the parent 782 # DefaultDir is .:APPLIC~1|Application Data with 783 # Before ":" : [sourcedir]:[destdir] (not programmed yet) 784 # After ":" : 8+3 and not 8+3 the destination directory name 785 786 $installer::logger::Lang->add_timestamp("Performance Info: Directory Table start"); 787 788 my @directorytable = (); 789 installer::windows::idtglobal::write_idt_header(\@directorytable, "directory"); 790 791 # Add entries for the root directories (and a few special directories like that for fonts). 792 process_root_directories( 793 $allvariableshashref, 794 sub($$$){ 795 push(@directorytable, join("\t", @_)."\n"); 796 } 797 ); 798 799 # Add entries for the non-root directories. 800 create_directorytable_from_collection(\@directorytable, $directoryref); 801 802 # Saving the file 803 804 my $directorytablename = $basedir . $installer::globals::separator . "Director.idt"; 805 installer::files::save_file($directorytablename ,\@directorytable); 806 $installer::logger::Lang->printf("Created idt file: %s\n", $directorytablename); 807 808 $installer::logger::Lang->add_timestamp("Performance Info: Directory Table end"); 809} 810 8111; 812