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