| #************************************************************** |
| # |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| # |
| #************************************************************** |
| |
| |
| |
| package installer::windows::directory; |
| |
| use installer::exiter; |
| use installer::files; |
| use installer::globals; |
| use installer::pathanalyzer; |
| use installer::windows::idtglobal; |
| use installer::windows::msiglobal; |
| use installer::scriptitems; |
| |
| use strict; |
| |
| ############################################################## |
| # Collecting all directory trees in global hash |
| ############################################################## |
| |
| sub collectdirectorytrees |
| { |
| my ( $directoryref ) = @_; |
| |
| for ( my $i = 0; $i <= $#{$directoryref}; $i++ ) |
| { |
| my $onedir = ${$directoryref}[$i]; |
| my $styles = ""; |
| if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; } |
| |
| if ( $styles ne "" ) |
| { |
| foreach my $treestyle ( keys %installer::globals::treestyles ) |
| { |
| if ( $styles =~ /\b$treestyle\b/ ) |
| { |
| my $hostname = $onedir->{'HostName'}; |
| # -> hostname is the key, the style the value! |
| $installer::globals::hostnametreestyles{$hostname} = $treestyle; |
| } |
| } |
| } |
| } |
| } |
| |
| ############################################################## |
| # Overwriting global programfilesfolder, if required |
| ############################################################## |
| |
| sub overwrite_programfilesfolder |
| { |
| my ( $allvariables ) = @_; |
| |
| if ( $allvariables->{'PROGRAMFILESFOLDERNAME'} ) |
| { |
| $installer::globals::programfilesfolder = $allvariables->{'PROGRAMFILESFOLDERNAME'}; |
| } |
| } |
| |
| |
| |
| |
| =head2 make_short_dir_version($longstring) |
| |
| Transform the given string into one that is at most 70 characters long. |
| That is done in two steps: |
| - Cut all parts separated by '_' or '-' down to a length of 5. |
| - Cut down the result to a length of 60 and fill it up to length 70 |
| with the MD5 checksum. |
| |
| This transform always returns the same result for the same string. |
| There is no counter and reference to a global set of names to make the string unique. |
| |
| =cut |
| sub make_short_dir_version ($) |
| { |
| my ($longstring) = @_; |
| |
| my $shortstring = ""; |
| my $cutlength = 60; |
| my $length = 5; # So the directory can still be recognized |
| my $longstring_save = $longstring; |
| |
| # Splitting the string at each "underline" and allowing only $length characters per directory name. |
| # Checking also uniqueness and length. |
| |
| my @outer_parts = split(/_/, $longstring); |
| foreach my $onestring (@outer_parts) |
| { |
| my $partstring = ""; |
| |
| if ( $onestring =~ /\-/ ) |
| { |
| my @inner_parts = split(/-/, $onestring); |
| @inner_parts = map {substr($_,0,$length)} @inner_parts; |
| $partstring = join("-", @inner_parts); |
| $partstring =~ s/^\s*\-//; |
| } |
| else |
| { |
| $partstring = substr($onestring, 0, $length); |
| } |
| |
| $shortstring .= "_" . $partstring; |
| } |
| |
| $shortstring =~ s/^\s*\_//; |
| |
| # Setting unique ID to each directory |
| # No counter allowed, process must be absolute reproducable due to patch creation process. |
| |
| my $subid = installer::windows::msiglobal::calculate_id($longstring_save, 9); # taking only the first 9 digits |
| $shortstring = substr($shortstring, 0, $cutlength) . "_" . $subid; |
| |
| return $shortstring; |
| } |
| |
| |
| |
| |
| =head2 get_unique_name ($hostname, $unique_map, $shortdirhash, $shortdirhashreverse) |
| |
| Return a long and a short unique name for the given $hostname. |
| Despite the function name and unlike the generation of unique |
| names for files, the returned names are not really unique. Quite |
| the opposite. The returned names are quaranteed to return the |
| same result for the same input. |
| |
| The returned short name has at most length 70. |
| |
| =cut |
| sub get_unique_name ($$) |
| { |
| my ($hostname, $hostnamehash) = @_; |
| |
| # Make sure that we where not called for this hostname before. Otherwise the other test would be triggered. |
| if (defined $hostnamehash->{$hostname}) |
| { |
| installer::exiter::exit_program( |
| "ERROR: get_unique_name was already called for hostname ".$hostname, |
| "get_unique_name"); |
| } |
| $hostnamehash->{$hostname} = 1; |
| |
| my $uniquename = $hostname; |
| |
| $uniquename =~ s/^\s*//g; # removing beginning white spaces |
| $uniquename =~ s/\s*$//g; # removing ending white spaces |
| $uniquename =~ s/\s//g; # removing white spaces |
| $uniquename =~ s/\_//g; # removing existing underlines |
| $uniquename =~ s/\.//g; # removing dots in directoryname |
| $uniquename =~ s/OpenOffice/OO/g; |
| |
| $uniquename =~ s/\Q$installer::globals::separator\E/\_/g; # replacing slash and backslash with underline |
| |
| $uniquename =~ s/_registry/_rgy/g; |
| $uniquename =~ s/_registration/_rgn/g; |
| $uniquename =~ s/_extension/_ext/g; |
| $uniquename =~ s/_frame/_frm/g; |
| $uniquename =~ s/_table/_tbl/g; |
| $uniquename =~ s/_chart/_crt/g; |
| |
| my $short_uniquename = make_short_dir_version($uniquename); |
| |
| return ($uniquename, $short_uniquename); |
| } |
| |
| |
| |
| |
| =head2 check_unique_directorynames($directories) |
| |
| The one really important check is made in get_unique_name(). It |
| checks that get_unique_name() is not called twice for the same |
| directory host name. The tests in this function contain the |
| legacy tests that basically only check if there where a collision |
| of the partial MD5 sum that is used to make the short unique names |
| unique. |
| |
| The maps $unique_map, $shortdirhash, $shortdirhashreverse are used |
| only to check that _different_ input names are mapped to different |
| results. They are not used to influence the result. That assumes |
| that this function is called only once for every directory |
| hostname. |
| =cut |
| sub check_unique_directorynames ($) |
| { |
| my ($directories) = @_; |
| |
| my %completedirhashstep1 = (); |
| my %shortdirhash = (); |
| my %shortdirhashreverse = (); |
| |
| # Check unique name of directories. |
| foreach my $directory (@$directories) |
| { |
| my ($long_uniquename, $short_uniquename) = ($directory->{'long_uniquename'}, $directory->{'uniquename'}); |
| |
| # The names after this small changes must still be unique! |
| if (exists($completedirhashstep1{$long_uniquename})) |
| { |
| installer::exiter::exit_program( |
| sprintf("ERROR: Unallowed modification of directory name, not unique (step 1): \"%s\".", |
| $short_uniquename), |
| "check_unique_directorynames"); |
| } |
| $completedirhashstep1{$long_uniquename} = 1; |
| |
| |
| # Checking if the same directory already exists, but has another short version. |
| if (exists($shortdirhash{$long_uniquename}) |
| && ( $shortdirhash{$long_uniquename} ne $short_uniquename )) |
| { |
| installer::exiter::exit_program( |
| sprintf( |
| "ERROR: Unallowed modification of directory name, not unique (step 2A): \"%s\".", |
| $short_uniquename), |
| "check_unique_directorynames"); |
| } |
| $shortdirhash{$long_uniquename} = $short_uniquename; |
| |
| # Also checking vice versa |
| # Checking if the same short directory already exists, but has another long version. |
| if (exists($shortdirhashreverse{$short_uniquename}) |
| && ( $shortdirhashreverse{$short_uniquename} ne $long_uniquename )) |
| { |
| installer::exiter::exit_program( |
| sprintf( |
| "ERROR: Unallowed modification of directory name, not unique (step 2B): \"%s\".", |
| $short_uniquename), |
| "check_unique_directorynames"); |
| } |
| $shortdirhashreverse{$short_uniquename} = $long_uniquename; |
| } |
| |
| # Check unique name of parents |
| foreach my $directory (@$directories) |
| { |
| my ($long_uniquename, $short_uniquename) |
| = ($directory->{'long_uniqueparentname'}, $directory->{'uniqueparentname'}); |
| |
| # Again checking if the same directory already exists, but has another short version. |
| if (exists($shortdirhash{$long_uniquename}) |
| && ( $shortdirhash{$long_uniquename} ne $short_uniquename )) |
| { |
| installer::exiter::exit_program( |
| sprintf( |
| "ERROR: Unallowed modification of directory name, not unique (step 3A): \"%s\".", |
| $short_uniquename), |
| "check_unique_directorynames"); |
| } |
| $shortdirhash{$long_uniquename} = $short_uniquename; |
| |
| # Also checking vice versa |
| # Checking if the same short directory already exists, but has another long version. |
| if (exists($shortdirhashreverse{$short_uniquename}) |
| && ( $shortdirhashreverse{$short_uniquename} ne $long_uniquename )) |
| { |
| installer::exiter::exit_program( |
| sprintf( |
| "ERROR: Unallowed modification of directory name, not unique (step 3B): \"%s\".", |
| $short_uniquename), |
| "check_unique_directorynames"); |
| } |
| $shortdirhashreverse{$short_uniquename} = $long_uniquename; |
| } |
| } |
| |
| |
| |
| |
| sub get_unique_parent_name ($$) |
| { |
| my ($uniqueparentname, $styles) = @_; |
| |
| my $keepparent = 1; |
| |
| if ( $uniqueparentname =~ /^\s*(.*)\_(.*?)\s*$/ ) # the underline is now the separator |
| { |
| $uniqueparentname = $1; |
| $keepparent = 0; |
| } |
| else |
| { |
| $uniqueparentname = $installer::globals::programfilesfolder; |
| $keepparent = 1; |
| } |
| |
| if ( $styles =~ /\bPROGRAMFILESFOLDER\b/ ) |
| { |
| $uniqueparentname = $installer::globals::programfilesfolder; |
| $keepparent = 1; |
| } |
| if ( $styles =~ /\bCOMMONFILESFOLDER\b/ ) |
| { |
| $uniqueparentname = $installer::globals::commonfilesfolder; |
| $keepparent = 1; |
| } |
| if ( $styles =~ /\bCOMMONAPPDATAFOLDER\b/ ) |
| { |
| $uniqueparentname = $installer::globals::commonappdatafolder; |
| $keepparent = 1; |
| } |
| if ( $styles =~ /\bLOCALAPPDATAFOLDER\b/ ) |
| { |
| $uniqueparentname = $installer::globals::localappdatafolder; |
| $keepparent = 1; |
| } |
| |
| if ( $styles =~ /\bSHAREPOINTPATH\b/ ) |
| { |
| $uniqueparentname = "SHAREPOINTPATH"; |
| $installer::globals::usesharepointpath = 1; |
| $keepparent = 1; |
| } |
| |
| # also setting short directory name for the parent |
| |
| my $originaluniqueparentname = $uniqueparentname; |
| |
| if ( ! $keepparent ) |
| { |
| $uniqueparentname = make_short_dir_version($uniqueparentname); |
| } |
| |
| return ($originaluniqueparentname, $uniqueparentname); |
| } |
| |
| |
| |
| |
| ############################################################## |
| # Adding unique directory names to the directory collection |
| ############################################################## |
| |
| sub create_unique_directorynames ($) |
| { |
| my ($directories) = @_; |
| |
| $installer::globals::officeinstalldirectoryset = 0; |
| |
| my %hostnamehash = (); |
| my $infoline = ""; |
| my $errorcount = 0; |
| |
| foreach my $directory (@$directories) |
| { |
| next if defined $directory->{'uniquename'}; |
| |
| my $styles = $directory->{'Styles'}; |
| $styles = "" unless defined $styles; |
| |
| my ($originaluniquename, $uniquename) = get_unique_name( |
| $directory->{'HostName'}, |
| \%hostnamehash); |
| |
| my ($originaluniqueparentname, $uniqueparentname) = get_unique_parent_name( |
| $originaluniquename, |
| $styles); |
| |
| |
| # Hyphen not allowed in database |
| $uniquename =~ s/\-/\_/g; # making "-" to "_" |
| $uniqueparentname =~ s/\-/\_/g; # making "-" to "_" |
| |
| # And finally setting the values for the directories |
| $directory->{'uniquename'} = $uniquename; |
| $directory->{'uniqueparentname'} = $uniqueparentname; |
| $directory->{'long_uniquename'} = $originaluniquename; |
| $directory->{'long_uniqueparentname'} = $originaluniqueparentname; |
| } |
| |
| # Find the installation directory. |
| foreach my $directory (@$directories) |
| { |
| next unless defined $directory->{'Styles'}; |
| |
| # setting the installlocation directory |
| next unless $directory->{'Styles'} =~ /\bISINSTALLLOCATION\b/; |
| |
| if ( $installer::globals::installlocationdirectoryset ) |
| { |
| installer::exiter::exit_program( |
| sprintf( |
| "ERROR: Directory with flag ISINSTALLLOCATION alread set: \"%s\".", |
| $installer::globals::installlocationdirectory), |
| "create_unique_directorynames"); |
| } |
| |
| $installer::globals::installlocationdirectory = $directory->{'uniquename'}; |
| $installer::globals::installlocationdirectoryset = 1; |
| } |
| } |
| |
| |
| |
| |
| ##################################################### |
| # Adding ":." to selected default directory names |
| ##################################################### |
| |
| sub update_defaultdir ($$) |
| { |
| my ( $onedir, $allvariableshashref ) = @_; |
| |
| if ($installer::globals::addchildprojects |
| || $installer::globals::patch |
| || $installer::globals::languagepack |
| || $allvariableshashref->{'CHANGETARGETDIR'}) |
| { |
| my $sourcediraddon = "\:\."; |
| return $onedir->{'defaultdir'} . $sourcediraddon; |
| } |
| else |
| { |
| return $onedir->{'defaultdir'}; |
| } |
| } |
| |
| ##################################################### |
| # The directory with the style ISINSTALLLOCATION |
| # will be replaced by INSTALLLOCATION |
| ##################################################### |
| |
| sub set_installlocation_directory |
| { |
| my ( $directoryref, $allvariableshashref ) = @_; |
| |
| if ( ! $installer::globals::installlocationdirectoryset ) |
| { |
| installer::exiter::exit_program( |
| "ERROR: Directory with flag ISINSTALLLOCATION not set!", |
| "set_installlocation_directory"); |
| } |
| |
| for ( my $i = 0; $i <= $#{$directoryref}; $i++ ) |
| { |
| my $onedir = ${$directoryref}[$i]; |
| |
| if ( $onedir->{'uniquename'} eq $installer::globals::installlocationdirectory ) |
| { |
| $onedir->{'uniquename'} = "INSTALLLOCATION"; |
| $onedir->{'defaultdir'} = update_defaultdir($onedir, $allvariableshashref); |
| } |
| |
| if ( $onedir->{'uniquename'} eq $installer::globals::vendordirectory ) |
| { |
| $onedir->{'defaultdir'} = update_defaultdir($onedir, $allvariableshashref); |
| } |
| |
| if ( $onedir->{'uniqueparentname'} eq $installer::globals::installlocationdirectory ) |
| { |
| $onedir->{'uniqueparentname'} = "INSTALLLOCATION"; |
| } |
| } |
| } |
| |
| ##################################################### |
| # Getting the name of the top level directory. This |
| # can have only one letter |
| ##################################################### |
| |
| sub get_last_directory_name |
| { |
| my ($completepathref) = @_; |
| |
| if ( $$completepathref =~ /^.*[\/\\](.+?)\s*$/ ) |
| { |
| $$completepathref = $1; |
| } |
| } |
| |
| sub setup_global_font_directory_name ($) |
| { |
| my ($directories) = @_; |
| |
| $installer::logger::Info->printf("setup_global_font_directory_name, checking %d entries\n", |
| scalar @$directories); |
| $installer::logger::Info->printf(" fontsdirhostname is %s\n", |
| $installer::globals::fontsdirhostname); |
| $installer::logger::Info->printf(" fontsdirname is %s\n", |
| $installer::globals::fontsdirname); |
| foreach my $directory (@$directories) |
| { |
| next unless defined $directory->{'Dir'}; |
| next unless defined $directory->{'defaultdir'}; |
| |
| $installer::logger::Info->printf(" Dir is %s\n", $directory->{'Dir'}); |
| $installer::logger::Info->printf(" defaultdir is %s\n", $directory->{'defaultdir'}); |
| next if $directory->{'Dir'} ne "PREDEFINED_OSSYSTEMFONTDIR"; |
| next if $directory->{'defaultdir'} ne $installer::globals::fontsdirhostname; |
| |
| $installer::globals::fontsdirname = $installer::globals::fontsdirhostname; |
| $installer::globals::fontsdirparent = $directory->{'uniqueparentname'}; |
| |
| $installer::logger::Info->printf("%s, fdhn %s, dd %s, ipn %s, HN %s\n", |
| "PREDEFINED_OSSYSTEMFONTDIR", |
| $installer::globals::fontsdirhostname, |
| $directory->{'defaultdir'}, |
| $directory->{'uniqueparentname'}, |
| $directory->{'HostName'}); |
| installer::scriptitems::print_script_item($directory); |
| } |
| foreach my $onedir (@$directories) |
| { |
| my $fontdir = ""; |
| if ( $onedir->{'Dir'} ) { $fontdir = $onedir->{'Dir'}; } |
| |
| my $fontdefaultdir = ""; |
| if ( $onedir->{'defaultdir'} ) { $fontdefaultdir = $onedir->{'defaultdir'}; } |
| |
| if (( $fontdir eq "PREDEFINED_OSSYSTEMFONTDIR" ) && ( $fontdefaultdir eq $installer::globals::fontsdirhostname )) |
| { |
| $installer::logger::Info->printf("fontsdirname = %s\n", $onedir->{'defaultdir'}); |
| $installer::logger::Info->printf(" is %s\n", $installer::globals::fontsdirname); |
| $installer::logger::Info->printf("fontsdirparent = %s\n", $onedir->{'uniqueparentname'}); |
| $installer::logger::Info->printf(" is %s\n", $installer::globals::fontsdirparent); |
| } |
| } |
| } |
| |
| ##################################################### |
| # Creating the defaultdir for the file Director.idt |
| ##################################################### |
| |
| sub create_defaultdir_directorynames ($) |
| { |
| my ($directoryref) = @_; |
| |
| my @shortnames = (); |
| if ( $installer::globals::prepare_winpatch ) { @shortnames = values(%installer::globals::saved83dirmapping); } |
| |
| for ( my $i = 0; $i <= $#{$directoryref}; $i++ ) |
| { |
| my $onedir = ${$directoryref}[$i]; |
| my $hostname = $onedir->{'HostName'}; |
| |
| $hostname =~ s/\Q$installer::globals::separator\E\s*$//; |
| get_last_directory_name(\$hostname); |
| # installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$hostname); # making program/classes to classes |
| my $uniquename = $onedir->{'uniquename'}; |
| my $shortstring; |
| if (( $installer::globals::prepare_winpatch ) && ( exists($installer::globals::saved83dirmapping{$uniquename}) )) |
| { |
| $shortstring = $installer::globals::saved83dirmapping{$uniquename}; |
| } |
| else |
| { |
| $shortstring = installer::windows::idtglobal::make_eight_three_conform($hostname, "dir", \@shortnames); |
| } |
| |
| my $defaultdir; |
| |
| if ( $shortstring eq $hostname ) |
| { |
| $defaultdir = $hostname; |
| } |
| else |
| { |
| $defaultdir = $shortstring . "|" . $hostname; |
| } |
| |
| $onedir->{'defaultdir'} = $defaultdir; |
| } |
| } |
| |
| ############################################### |
| # Fill content into the directory table |
| ############################################### |
| |
| sub create_directorytable_from_collection ($$) |
| { |
| my ($directorytableref, $directoryref) = @_; |
| |
| foreach my $onedir (@$directoryref) |
| { |
| # Remove entries for special directories. |
| if (defined $onedir->{'HostName'} |
| && $onedir->{'HostName'} eq "" |
| && defined $onedir->{'Dir'} |
| && $onedir->{'Dir'} eq "PREDEFINED_PROGDIR") |
| { |
| next; |
| } |
| |
| my $oneline = sprintf( |
| "%s\t%s\t%s\n", |
| $onedir->{'uniquename'}, |
| $onedir->{'uniqueparentname'}, |
| $onedir->{'defaultdir'}); |
| |
| push @{$directorytableref}, $oneline; |
| } |
| } |
| |
| ############################################### |
| # Defining the root installation structure |
| ############################################### |
| |
| sub process_root_directories ($$) |
| { |
| my ($allvariableshashref, $functor) = @_; |
| |
| my $oneline = ""; |
| |
| if (( ! $installer::globals::patch ) && ( ! $installer::globals::languagepack ) && ( ! $allvariableshashref->{'DONTUSESTARTMENUFOLDER'} )) |
| { |
| my $productname = $allvariableshashref->{'PRODUCTNAME'}; |
| my $productversion = $allvariableshashref->{'PRODUCTVERSION'}; |
| my $baseproductversion = $productversion; |
| |
| if (( $installer::globals::prepare_winpatch ) && ( $allvariableshashref->{'BASEPRODUCTVERSION'} )) |
| { |
| $baseproductversion = $allvariableshashref->{'BASEPRODUCTVERSION'}; # for example "2.0" for OOo |
| } |
| |
| my $realproductkey = $productname . " " . $productversion; |
| my $productkey = $productname . " " . $baseproductversion; |
| |
| if (( $allvariableshashref->{'POSTVERSIONEXTENSION'} ) && ( ! $allvariableshashref->{'DONTUSEEXTENSIONINDEFAULTDIR'} )) |
| { |
| $productkey = $productkey . " " . $allvariableshashref->{'POSTVERSIONEXTENSION'}; |
| $realproductkey = $realproductkey . " " . $allvariableshashref->{'POSTVERSIONEXTENSION'}; |
| } |
| if ( $allvariableshashref->{'NOSPACEINDIRECTORYNAME'} ) |
| { |
| $productkey =~ s/\ /\_/g; |
| $realproductkey =~ s/\ /\_/g; |
| } |
| |
| my $shortproductkey = installer::windows::idtglobal::make_eight_three_conform($productkey, "dir", undef); |
| $shortproductkey =~ s/\s/\_/g; # changing empty space to underline |
| |
| &$functor( |
| $installer::globals::officemenufolder, |
| $installer::globals::programmenufolder, |
| $shortproductkey . "|". $realproductkey); |
| } |
| |
| &$functor("TARGETDIR", "", "SourceDir"); |
| &$functor($installer::globals::programfilesfolder, "TARGETDIR", "."); |
| &$functor($installer::globals::programmenufolder, "TARGETDIR", "."); |
| &$functor($installer::globals::startupfolder, "TARGETDIR", "."); |
| &$functor($installer::globals::desktopfolder, "TARGETDIR", "."); |
| &$functor($installer::globals::startmenufolder, "TARGETDIR", "."); |
| &$functor($installer::globals::commonfilesfolder, "TARGETDIR", "."); |
| &$functor($installer::globals::commonappdatafolder, "TARGETDIR", "."); |
| &$functor($installer::globals::localappdatafolder, "TARGETDIR", "."); |
| |
| if ( $installer::globals::usesharepointpath ) |
| { |
| &$functor("SHAREPOINTPATH", "TARGETDIR", "."); |
| } |
| |
| &$functor($installer::globals::systemfolder, "TARGETDIR", "."); |
| |
| my $localtemplatefoldername = $installer::globals::templatefoldername; |
| my $directorytableentry = $localtemplatefoldername; |
| my $shorttemplatefoldername = installer::windows::idtglobal::make_eight_three_conform($localtemplatefoldername, "dir"); |
| if ( $shorttemplatefoldername ne $localtemplatefoldername ) |
| { |
| $directorytableentry = $shorttemplatefoldername . "|" . $localtemplatefoldername; |
| } |
| &$functor($installer::globals::templatefolder, "TARGETDIR", $directorytableentry); |
| |
| $installer::logger::Info->printf("process_root_directories: fontsdirname=%s, fontsfoldername=%s\n", |
| $installer::globals::fontsdirname, |
| $installer::globals::fontsfoldername); |
| if ( $installer::globals::fontsdirname ) |
| { |
| &$functor( |
| $installer::globals::fontsfolder, |
| $installer::globals::fontsdirparent, |
| $installer::globals::fontsfoldername . ":" . $installer::globals::fontsdirname); |
| } |
| else |
| { |
| &$functor( |
| $installer::globals::fontsfolder, |
| "TARGETDIR", |
| $installer::globals::fontsfoldername); |
| } |
| } |
| |
| |
| |
| |
| sub find_missing_directories ($$) |
| { |
| my ($directories, $allvariableshashref) = @_; |
| |
| # Set up the list of target directories. |
| my %target_directories = map {$_->{'uniquename'} => 1} @$directories; |
| # Add special directories. |
| process_root_directories( |
| $allvariableshashref, |
| sub($$$){ |
| my ($uniquename, $parentname, $defaultdir) = @_; |
| $target_directories{$uniquename} = 1; |
| } |
| ); |
| |
| # Set up the list of source directories. |
| my $source_directory_map = $installer::globals::source_msi->GetDirectoryMap(); |
| my $source_file_map = $installer::globals::source_msi->GetFileMap(); |
| my %source_directories = map {$_->{'unique_name'} => $_} values %$source_directory_map; |
| |
| # Find the missing source directories. |
| my @missing_directories = (); |
| foreach my $source_uniquename (keys %source_directories) |
| { |
| if ( ! $target_directories{$source_uniquename}) |
| { |
| push @missing_directories, $source_directories{$source_uniquename}; |
| } |
| } |
| |
| # Report the missing directories. |
| $installer::logger::Info->printf("found %d missing directories\n", scalar @missing_directories); |
| my $index = 0; |
| foreach my $directory_item (@missing_directories) |
| { |
| # Print information about the directory. |
| $installer::logger::Info->printf("missing directory %d: %s\n", |
| ++$index, |
| $directory_item->{'full_target_long_name'}); |
| while (my($key,$value) = each %$directory_item) |
| { |
| $installer::logger::Info->printf(" %s -> %s\n", $key, $value); |
| } |
| |
| # Print the referencing files. |
| my @filenames = (); |
| while (my ($key,$value) = each %$source_file_map) |
| { |
| if ($value->{'directory'}->{'unique_name'} eq $directory_item->{'unique_name'}) |
| { |
| push @filenames, $key; |
| } |
| } |
| $installer::logger::Info->printf(" referencing files are %s\n", join(", ", @filenames)); |
| } |
| |
| foreach my $directory (@$directories) |
| { |
| $installer::logger::Lang->printf("target directory %s -> HN %s\n", |
| $directory->{'uniquename'}, |
| $directory->{'HostName'}); |
| installer::scriptitems::print_script_item($directory); |
| } |
| |
| # Setup a map of directory uniquenames to verify that the new |
| # entries don't use unique names that are already in use. |
| my %unique_names = map {$_->{'uniquename'} => $_} @$directories; |
| |
| # Create script items for the missing directories. |
| my @new_source_directories = (); |
| foreach my $source_directory_item (@missing_directories) |
| { |
| my $new_directory_item = { |
| 'uniquename' => $source_directory_item->{'unique_name'}, |
| 'uniqueparentname' => $source_directory_item->{'parent_name'}, |
| 'defaultdir' => $source_directory_item->{'default_dir'}, |
| 'HostName' => $source_directory_item->{'full_target_long_name'}, |
| 'componentname' => $source_directory_item->{'component_name'}, |
| }; |
| |
| if (defined $unique_names{$new_directory_item->{'uniquename'}}) |
| { |
| installer::logger::PrintError("newly created directory entry collides with existing directory"); |
| last; |
| } |
| |
| push @new_source_directories, $new_directory_item; |
| } |
| |
| return @new_source_directories; |
| } |
| |
| |
| |
| |
| sub prepare_directory_table_creation ($$) |
| { |
| my ($directories, $allvariableshashref) = @_; |
| |
| foreach my $directory (@$directories) |
| { |
| delete $directory->{'uniquename'}; |
| } |
| |
| overwrite_programfilesfolder($allvariableshashref); |
| create_unique_directorynames($directories); |
| check_unique_directorynames($directories); |
| create_defaultdir_directorynames($directories); # only destdir! |
| setup_global_font_directory_name($directories); |
| set_installlocation_directory($directories, $allvariableshashref); |
| |
| if ($installer::globals::is_release) |
| { |
| my @new_directories = find_missing_directories($directories, $allvariableshashref); |
| push @$directories, @new_directories; |
| } |
| } |
| |
| |
| |
| |
| ############################################### |
| # Creating the file Director.idt dynamically |
| ############################################### |
| |
| sub create_directory_table ($$$) |
| { |
| my ($directoryref, $basedir, $allvariableshashref) = @_; |
| |
| # Structure of the directory table: |
| # Directory Directory_Parent DefaultDir |
| # Directory is a unique identifier |
| # Directory_Parent is the unique identifier of the parent |
| # DefaultDir is .:APPLIC~1|Application Data with |
| # Before ":" : [sourcedir]:[destdir] (not programmed yet) |
| # After ":" : 8+3 and not 8+3 the destination directory name |
| |
| $installer::logger::Lang->add_timestamp("Performance Info: Directory Table start"); |
| |
| my @directorytable = (); |
| installer::windows::idtglobal::write_idt_header(\@directorytable, "directory"); |
| |
| # Add entries for the root directories (and a few special directories like that for fonts). |
| process_root_directories( |
| $allvariableshashref, |
| sub($$$){ |
| push(@directorytable, join("\t", @_)."\n"); |
| } |
| ); |
| |
| # Add entries for the non-root directories. |
| create_directorytable_from_collection(\@directorytable, $directoryref); |
| |
| # Saving the file |
| |
| my $directorytablename = $basedir . $installer::globals::separator . "Director.idt"; |
| installer::files::save_file($directorytablename ,\@directorytable); |
| $installer::logger::Lang->printf("Created idt file: %s\n", $directorytablename); |
| |
| $installer::logger::Lang->add_timestamp("Performance Info: Directory Table end"); |
| } |
| |
| |
| 1; |