Return-Path: X-Original-To: apmail-openoffice-commits-archive@www.apache.org Delivered-To: apmail-openoffice-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id C0CEC108A3 for ; Wed, 4 Dec 2013 08:52:21 +0000 (UTC) Received: (qmail 62613 invoked by uid 500); 4 Dec 2013 08:52:14 -0000 Delivered-To: apmail-openoffice-commits-archive@openoffice.apache.org Received: (qmail 62563 invoked by uid 500); 4 Dec 2013 08:52:13 -0000 Mailing-List: contact commits-help@openoffice.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@openoffice.apache.org Delivered-To: mailing list commits@openoffice.apache.org Received: (qmail 62553 invoked by uid 99); 4 Dec 2013 08:52:13 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 04 Dec 2013 08:52:13 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 04 Dec 2013 08:51:55 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id C93102388B75; Wed, 4 Dec 2013 08:51:32 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1547732 [3/4] - in /openoffice/trunk/main: instsetoo_native/data/ instsetoo_native/util/ solenv/bin/ solenv/bin/modules/installer/ solenv/bin/modules/installer/patch/ solenv/bin/modules/installer/windows/ Date: Wed, 04 Dec 2013 08:51:31 -0000 To: commits@openoffice.apache.org From: af@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20131204085132.C93102388B75@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: openoffice/trunk/main/solenv/bin/modules/installer/windows/directory.pm URL: http://svn.apache.org/viewvc/openoffice/trunk/main/solenv/bin/modules/installer/windows/directory.pm?rev=1547732&r1=1547731&r2=1547732&view=diff ============================================================================== --- openoffice/trunk/main/solenv/bin/modules/installer/windows/directory.pm (original) +++ openoffice/trunk/main/solenv/bin/modules/installer/windows/directory.pm Wed Dec 4 08:51:30 2013 @@ -29,6 +29,7 @@ use installer::globals; use installer::pathanalyzer; use installer::windows::idtglobal; use installer::windows::msiglobal; +use installer::scriptitems; use strict; @@ -133,172 +134,305 @@ sub make_short_dir_version ($) return $shortstring; } -############################################################## -# Adding unique directory names to the directory collection -############################################################## -sub create_unique_directorynames + + +=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 ($directoryref, $allvariables) = @_; + my ($hostname, $hostnamehash) = @_; - $installer::globals::officeinstalldirectoryset = 0; + # 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; - my %completedirhashstep1 = (); - my %shortdirhash = (); - my %shortdirhashreverse = (); - my $infoline = ""; - my $errorcount = 0; + $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; - for ( my $i = 0; $i <= $#{$directoryref}; $i++ ) - { - my $onedir = ${$directoryref}[$i]; - my $uniquename = $onedir->{'HostName'}; + my $short_uniquename = make_short_dir_version($uniquename); - my $styles = ""; - if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; } + return ($uniquename, $short_uniquename); +} - $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; - # The names after this small changes must still be unique! - if ( exists($completedirhashstep1{$uniquename}) ) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 1): \"$uniquename\".", "create_unique_directorynames"); } - $completedirhashstep1{$uniquename} = 1; +=head2 check_unique_directorynames($directories) - # Starting to make unique name for the parent and its directory - my $originaluniquename = $uniquename; + 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. - $uniquename = make_short_dir_version($uniquename); + 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) = @_; - # Checking if the same directory already exists, but has another short version. - if (( exists($shortdirhash{$originaluniquename}) ) && ( $shortdirhash{$originaluniquename} ne $uniquename )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 2A): \"$uniquename\".", "create_unique_directorynames"); } + my %completedirhashstep1 = (); + my %shortdirhash = (); + my %shortdirhashreverse = (); - # Also checking vice versa - # Checking if the same short directory already exists, but has another long version. - if (( exists($shortdirhashreverse{$uniquename}) ) && ( $shortdirhashreverse{$uniquename} ne $originaluniquename )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 2B): \"$uniquename\".", "create_unique_directorynames"); } + # 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; + } +} - # Creating assignment from long to short directory names - $shortdirhash{$originaluniquename} = $uniquename; - $shortdirhashreverse{$uniquename} = $originaluniquename; - # Important: The unique parent is generated from the string $originaluniquename (with the use of underlines). - my $uniqueparentname = $originaluniquename; - my $keepparent = 1; - if ( $uniqueparentname =~ /^\s*(.*)\_(.*?)\s*$/ ) # the underline is now the separator - { - $uniqueparentname = $1; - $keepparent = 0; - } - else - { - $uniqueparentname = $installer::globals::programfilesfolder; - $keepparent = 1; - } +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); + } - 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; - } + return ($originaluniqueparentname, $uniqueparentname); +} - 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); - } - # Again checking if the same directory already exists, but has another short version. - if (( exists($shortdirhash{$originaluniqueparentname}) ) && ( $shortdirhash{$originaluniqueparentname} ne $uniqueparentname )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 3A): \"$uniqueparentname\".", "create_unique_directorynames"); } +############################################################## +# 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'} // ""; - # Also checking vice versa - # Checking if the same short directory already exists, but has another long version. - if (( exists($shortdirhashreverse{$uniqueparentname}) ) && ( $shortdirhashreverse{$uniqueparentname} ne $originaluniqueparentname )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 3B): \"$uniqueparentname\".", "create_unique_directorynames"); } + my ($originaluniquename, $uniquename) = get_unique_name( + $directory->{'HostName'}, + \%hostnamehash); + + my ($originaluniqueparentname, $uniqueparentname) = get_unique_parent_name( + $originaluniquename, + $styles); - $shortdirhash{$originaluniqueparentname} = $uniqueparentname; - $shortdirhashreverse{$uniqueparentname} = $originaluniqueparentname; # Hyphen not allowed in database $uniquename =~ s/\-/\_/g; # making "-" to "_" $uniqueparentname =~ s/\-/\_/g; # making "-" to "_" # And finally setting the values for the directories - $onedir->{'uniquename'} = $uniquename; - $onedir->{'uniqueparentname'} = $uniqueparentname; - + $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 - if ( $styles =~ /\bISINSTALLLOCATION\b/ ) - { - if ( $installer::globals::installlocationdirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag ISINSTALLLOCATION alread set: \"$installer::globals::installlocationdirectory\".", "create_unique_directorynames"); } - $installer::globals::installlocationdirectory = $uniquename; - $installer::globals::installlocationdirectoryset = 1; - } - - # setting the sundirectory - if ( $styles =~ /\bSUNDIRECTORY\b/ ) - { - if ( $installer::globals::vendordirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag SUNDIRECTORY alread set: \"$installer::globals::vendordirectory\".", "create_unique_directorynames"); } - $installer::globals::vendordirectory = $uniquename; - $installer::globals::vendordirectoryset = 1; - } - } + 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 check_sourcedir_addon +sub update_defaultdir ($$) { my ( $onedir, $allvariableshashref ) = @_; - if (($installer::globals::addchildprojects) || - ($installer::globals::patch) || - ($installer::globals::languagepack) || - ($allvariableshashref->{'CHANGETARGETDIR'})) + if ($installer::globals::addchildprojects + || $installer::globals::patch + || $installer::globals::languagepack + || $allvariableshashref->{'CHANGETARGETDIR'}) { my $sourcediraddon = "\:\."; - $onedir->{'defaultdir'} = $onedir->{'defaultdir'} . $sourcediraddon; + return $onedir->{'defaultdir'} . $sourcediraddon; } - + else + { + return $onedir->{'defaultdir'}; + } } ##################################################### @@ -310,7 +444,12 @@ 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"); } + 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++ ) { @@ -319,12 +458,12 @@ sub set_installlocation_directory if ( $onedir->{'uniquename'} eq $installer::globals::installlocationdirectory ) { $onedir->{'uniquename'} = "INSTALLLOCATION"; - check_sourcedir_addon($onedir, $allvariableshashref); + $onedir->{'defaultdir'} = update_defaultdir($onedir, $allvariableshashref); } if ( $onedir->{'uniquename'} eq $installer::globals::vendordirectory ) { - check_sourcedir_addon($onedir, $allvariableshashref); + $onedir->{'defaultdir'} = update_defaultdir($onedir, $allvariableshashref); } if ( $onedir->{'uniqueparentname'} eq $installer::globals::installlocationdirectory ) @@ -349,6 +488,31 @@ sub get_last_directory_name } } +sub setup_global_font_directory_name ($) +{ + my ($directories) = @_; + + foreach my $directory (@$directories) + { + next unless defined $directory->{'Dir'}; + next unless defined $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); + } +} + ##################################################### # Creating the defaultdir for the file Director.idt ##################################################### @@ -391,18 +555,6 @@ sub create_defaultdir_directorynames ($) } $onedir->{'defaultdir'} = $defaultdir; - - 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::globals::fontsdirname = $onedir->{'defaultdir'}; - $installer::globals::fontsdirparent = $onedir->{'uniqueparentname'}; - } } } @@ -410,23 +562,28 @@ sub create_defaultdir_directorynames ($) # Fill content into the directory table ############################################### -sub create_directorytable_from_collection +sub create_directorytable_from_collection ($$) { my ($directorytableref, $directoryref) = @_; - for ( my $i = 0; $i <= $#{$directoryref}; $i++ ) + foreach my $onedir (@$directoryref) { - my $onedir = ${$directoryref}[$i]; - my $hostname = $onedir->{'HostName'}; - my $dir = ""; - - if ( $onedir->{'Dir'} ) { $dir = $onedir->{'Dir'}; } - - if (( $dir eq "PREDEFINED_PROGDIR" ) && ( $hostname eq "" )) { next; } # removing files from root directory - - my $oneline = $onedir->{'uniquename'} . "\t" . $onedir->{'uniqueparentname'} . "\t" . $onedir->{'defaultdir'} . "\n"; + # 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); + push @{$directorytableref}, $oneline; } } @@ -434,19 +591,10 @@ sub create_directorytable_from_collectio # Defining the root installation structure ############################################### -sub add_root_directories +sub process_root_directories ($$) { - my ($directorytableref, $allvariableshashref) = @_; + my ($allvariableshashref, $functor) = @_; -# my $sourcediraddon = ""; -# if (($installer::globals::addchildprojects) || -# ($installer::globals::patch) || -# ($installer::globals::languagepack) || -# ($allvariableshashref->{'CHANGETARGETDIR'})) -# { -# $sourcediraddon = "\:\."; -# } - my $oneline = ""; if (( ! $installer::globals::patch ) && ( ! $installer::globals::languagepack ) && ( ! $allvariableshashref->{'DONTUSESTARTMENUFOLDER'} )) @@ -474,76 +622,188 @@ sub add_root_directories $realproductkey =~ s/\ /\_/g; } - my $shortproductkey = installer::windows::idtglobal::make_eight_three_conform($productkey, "dir"); # third parameter not used + my $shortproductkey = installer::windows::idtglobal::make_eight_three_conform($productkey, "dir", undef); $shortproductkey =~ s/\s/\_/g; # changing empty space to underline - - $oneline = "$installer::globals::officemenufolder\t$installer::globals::programmenufolder\t$shortproductkey|$realproductkey\n"; - push(@{$directorytableref}, $oneline); - } - - $oneline = "TARGETDIR\t\tSourceDir\n"; - push(@{$directorytableref}, $oneline); - - $oneline = "$installer::globals::programfilesfolder\tTARGETDIR\t.\n"; - push(@{$directorytableref}, $oneline); - - $oneline = "$installer::globals::programmenufolder\tTARGETDIR\t.\n"; - push(@{$directorytableref}, $oneline); - - $oneline = "$installer::globals::startupfolder\tTARGETDIR\t.\n"; - push(@{$directorytableref}, $oneline); - $oneline = "$installer::globals::desktopfolder\tTARGETDIR\t.\n"; - push(@{$directorytableref}, $oneline); - - $oneline = "$installer::globals::startmenufolder\tTARGETDIR\t.\n"; - push(@{$directorytableref}, $oneline); - - $oneline = "$installer::globals::commonfilesfolder\tTARGETDIR\t.\n"; - push(@{$directorytableref}, $oneline); - - $oneline = "$installer::globals::commonappdatafolder\tTARGETDIR\t.\n"; - push(@{$directorytableref}, $oneline); + &$functor( + $installer::globals::officemenufolder, + $installer::globals::programmenufolder, + $shortproductkey . "|". $realproductkey); + } - $oneline = "$installer::globals::localappdatafolder\tTARGETDIR\t.\n"; - push(@{$directorytableref}, $oneline); + &$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 ) { - $oneline = "SHAREPOINTPATH\tTARGETDIR\t.\n"; - push(@{$directorytableref}, $oneline); + &$functor("SHAREPOINTPATH", "TARGETDIR", "."); } - $oneline = "$installer::globals::systemfolder\tTARGETDIR\t.\n"; - push(@{$directorytableref}, $oneline); + &$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"; } - $oneline = "$installer::globals::templatefolder\tTARGETDIR\t$directorytableentry\n"; - push(@{$directorytableref}, $oneline); + if ( $shorttemplatefoldername ne $localtemplatefoldername ) + { + $directorytableentry = $shorttemplatefoldername . "|" . $localtemplatefoldername; + } + &$functor($installer::globals::templatefolder, "TARGETDIR", $directorytableentry); if ( $installer::globals::fontsdirname ) { - $oneline = "$installer::globals::fontsfolder\t$installer::globals::fontsdirparent\t$installer::globals::fontsfoldername\:$installer::globals::fontsdirname\n"; + &$functor( + $installer::globals::fontsfolder, + $installer::globals::fontsdirparent, + $installer::globals::fontsfoldername . ":" . $installer::globals::fontsdirname); } else { - $oneline = "$installer::globals::fontsfolder\tTARGETDIR\t$installer::globals::fontsfoldername\n"; + &$functor( + $installer::globals::fontsfolder, + "TARGETDIR", + $installer::globals::fontsfoldername); } +} + + - push(@{$directorytableref}, $oneline); +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'}, + '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 ($$$$) +sub create_directory_table ($$$) { - my ($directoryref, $basedir, $allvariableshashref, $loggingdir) = @_; + my ($directoryref, $basedir, $allvariableshashref) = @_; # Structure of the directory table: # Directory Directory_Parent DefaultDir @@ -556,14 +816,17 @@ sub create_directory_table ($$$$) $installer::logger::Lang->add_timestamp("Performance Info: Directory Table start"); my @directorytable = (); - my $infoline; - - overwrite_programfilesfolder($allvariableshashref); - create_unique_directorynames($directoryref, $allvariableshashref); - create_defaultdir_directorynames($directoryref); # only destdir! - set_installlocation_directory($directoryref, $allvariableshashref); installer::windows::idtglobal::write_idt_header(\@directorytable, "directory"); - add_root_directories(\@directorytable, $allvariableshashref); + + # 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 @@ -575,4 +838,5 @@ sub create_directory_table ($$$$) $installer::logger::Lang->add_timestamp("Performance Info: Directory Table end"); } + 1; Modified: openoffice/trunk/main/solenv/bin/modules/installer/windows/file.pm URL: http://svn.apache.org/viewvc/openoffice/trunk/main/solenv/bin/modules/installer/windows/file.pm?rev=1547732&r1=1547731&r2=1547732&view=diff ============================================================================== --- openoffice/trunk/main/solenv/bin/modules/installer/windows/file.pm (original) +++ openoffice/trunk/main/solenv/bin/modules/installer/windows/file.pm Wed Dec 4 08:51:30 2013 @@ -35,6 +35,11 @@ use installer::windows::font; use installer::windows::idtglobal; use installer::windows::msiglobal; use installer::windows::language; +use installer::patch::InstallationSet; +use installer::patch::FileSequenceList; +use File::Basename; +use File::Spec; +use strict; ########################################################################## # Assigning one cabinet file to each file. This is requrired, @@ -357,19 +362,23 @@ sub get_component_from_assigned_file # In most cases this is simply the filename. #################################################################### -sub generate_unique_filename_for_filetable ($$) +sub generate_unique_filename_for_filetable ($) { - my ($fileref, $component) = @_; + my ($oldname) = @_; # This new filename has to be saved into $fileref, because this is needed to find the source. # The filename sbasic.idx/OFFSETS is changed to OFFSETS, but OFFSETS is not unique. # In this procedure names like OFFSETS5 are produced. And exactly this string has to be added to # the array of all files. - my $uniquefilename = ""; - my $counter = 0; + my $uniquefilename = $oldname; + if ( ! defined $uniquefilename || $uniquefilename eq "") + { + installer::logger::PrintError("file name does not exist or is empty, can not create unique name for it."); + die; + return; + } - if ( $fileref->{'Name'} ) { $uniquefilename = $fileref->{'Name'}; } # making /registry/schema/org/openoffice/VCL.xcs to VCL.xcs installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$uniquefilename); @@ -398,6 +407,7 @@ sub generate_unique_filename_for_filetab my $uniquefilenamebase = $uniquefilename; + my $counter = 0; do { $counter++; @@ -491,7 +501,7 @@ sub get_filesize sub get_fileversion { - my ($onefile, $allvariables, $styles) = @_; + my ($onefile, $allvariables) = @_; my $fileversion = ""; @@ -532,6 +542,204 @@ sub get_fileversion return $fileversion; } + + + +sub retrieve_sequence_and_uniquename ($$) +{ + my ($file_list, $source_data) = @_; + + my @added_files = (); + + # Read the sequence numbers of the previous version. + if ($installer::globals::is_release) + { + foreach my $file (@$file_list) + { + # Use the source path of the file as key to retrieve sequence number and unique name. + # The source path is the part of the 'destination' without the first part. + # There is a special case when 'Dir' is PREDEFINED_OSSHELLNEWDIR. + my $source_path; + if (defined $file->{'Dir'} && $file->{'Dir'} eq "PREDEFINED_OSSHELLNEWDIR") + { + $source_path = $installer::globals::templatefoldername + . $installer::globals::separator + . $file->{'Name'}; + } + else + { + $source_path = $file->{'destination'}; + $source_path =~ s/^[^\/]+\///; + } + my ($sequence, $uniquename) = $source_data->get_sequence_and_unique_name($source_path); + if (defined $sequence && defined $uniquename) + { + $file->{'sequencenumber'} = $sequence; + $file->{'uniquename'} = $uniquename; + } + else + { + # No data found in the source release. File has been added. + push @added_files, $file; + } + } + } + + return @added_files; +} + + + + +=head2 assign_mssing_sequence_numbers ($file_list) + + Assign sequence numbers where still missing. + + When we are preparing a patch then all files that have no sequence numbers + at this point are new. Otherwise no file has a sequence number yet. + +=cut +sub assign_missing_sequence_numbers ($) +{ + my ($file_list) = @_; + + # First, set up a hash on the sequence numbers that are already in use. + my %used_sequence_numbers = (); + foreach my $file (@$file_list) + { + next unless defined $file->{'sequencenumber'}; + $used_sequence_numbers{$file->{'sequencenumber'}} = 1; + } + + # Assign sequence numbers. Try consecutive numbers, starting at 1. + my $current_sequence_number = 1; + foreach my $file (@$file_list) + { + # Skip over all files that already have sequence numbers. + next if defined $file->{'sequencenumber'}; + + # Find the next available number. + while (defined $used_sequence_numbers{$current_sequence_number}) + { + ++$current_sequence_number; + } + + # Use the number and mark it as used. + $file->{'sequencenumber'} = $current_sequence_number; + $used_sequence_numbers{$current_sequence_number} = 1; + } +} + + + + +sub create_items_for_missing_files ($$$) +{ + my ($missing_items, $msi, $directory_list) = @_; + + # For creation of the FeatureComponent table (in a later step) we + # have to provide references from the file to component and + # modules (ie features). Note that Each file belongs to exactly + # one component but one component can belong to multiple features. + my $component_to_features_map = create_feature_component_map($msi); + + my @new_files = (); + foreach my $row (@$missing_items) + { + $installer::logger::Info->printf("creating new file item for '%s'\n", $row->GetValue('File')); + my $file_item = create_script_item_for_deleted_file($row, $msi, $component_to_features_map); + push @new_files, $file_item; + } + + return @new_files; +} + + + + +sub create_script_item_for_deleted_file ($$$) +{ + my ($file_row, $msi, $component_to_features_map) = @_; + + my $uniquename = $file_row->GetValue('File'); + + my $file_map = $msi->GetFileMap(); + + my $directory_item = $file_map->{$uniquename}->{'directory'}; + my $source_path = $directory_item->{'full_source_long_name'}; + my $target_path = $directory_item->{'full_target_long_name'}; + my $full_source_name = File::Spec->catfile( + installer::patch::InstallationSet::GetUnpackedCabPath( + $msi->{'version'}, + $msi->{'is_current_version'}, + $msi->{'language'}, + $msi->{'package_format'}, + $msi->{'product_name'}), + $source_path, + $uniquename); + my ($long_name, undef) = installer::patch::Msi::SplitLongShortName($file_row->GetValue("FileName")); + my $target_name = File::Spec->catfile($target_path, $long_name); + if ( ! -f $full_source_name) + { + installer::logger::PrintError("can not find file '%s' in previous version (tried '%s')\n", + $uniquename, + $full_source_name); + return undef; + } + my $cygwin_full_source_name = qx(cygpath -w '$full_source_name'); + my $component_name = $file_row->GetValue('Component_'); + my $module_names = join(",", @{$component_to_features_map->{$component_name}}); + my $sequence_number = $file_row->GetValue('Sequence'); + + return { + 'uniquename' => $uniquename, + 'destination' => $target_name, + 'componentname' => $component_name, + 'modules' => $module_names, + 'UnixRights' => 444, + 'Name' => $long_name, + 'sourcepath' => $full_source_name, + 'cyg_sourcepath' => $cygwin_full_source_name, + 'sequencenumber' => $sequence_number + }; +} + + + + +=head2 create_feature_component_maps($msi) + + Return a hash map that maps from component names to arrays of + feature names. In most cases the array of features contains only + one element. But there can be cases where the number is greater. + +=cut +sub create_feature_component_map ($) +{ + my ($msi) = @_; + + my $component_to_features_map = {}; + my $feature_component_table = $msi->GetTable("FeatureComponents"); + my $feature_column_index = $feature_component_table->GetColumnIndex("Feature_"); + my $component_column_index = $feature_component_table->GetColumnIndex("Component_"); + foreach my $row (@{$feature_component_table->GetAllRows()}) + { + my $feature = $row->GetValue($feature_column_index); + my $component = $row->GetValue($component_column_index); + if ( ! defined $component_to_features_map->{$component}) + { + $component_to_features_map->{$component} = [$feature]; + } + else + { + push @{$component_to_features_map->{$component}}, $feature; + } + } + + return $component_to_features_map; +} + + ############################################# # Returning the Windows language of a file ############################################# @@ -576,6 +784,7 @@ sub generate_registry_keypath return $keypath; } + ################################################################### # Collecting further conditions for the component table. # This is used by multilayer products, to enable installation @@ -636,225 +845,344 @@ sub collect_shortnames_from_old_database } } -############################################ -# Creating the file File.idt dynamically -############################################ -sub create_files_table ($$$$) +sub process_language_conditions ($) { - my ($filesref, $allfilecomponentsref, $basedir, $allvariables) = @_; - - $installer::logger::Lang->add_timestamp("Performance Info: File Table start"); - - # Structure of the files table: - # File Component_ FileName FileSize Version Language Attributes Sequence - # In this function, all components are created. - # - # $allfilecomponentsref is empty at the beginning - - my $infoline; + my ($onefile) = @_; + + # Collecting all languages specific conditions + if ( $onefile->{'ismultilingual'} ) + { + if ( $onefile->{'ComponentCondition'} ) + { + installer::exiter::exit_program( + "ERROR: Cannot set language condition. There is already another component condition for file $onefile->{'gid'}: \"$onefile->{'ComponentCondition'}\" !", "create_files_table"); + } - my @allfiles = (); - my @filetable = (); - my @filehashtable = (); - my %allfilecomponents = (); - my $counter = 0; + if ( $onefile->{'specificlanguage'} eq "" ) + { + installer::exiter::exit_program( + "ERROR: There is no specific language for file at language module: $onefile->{'gid'} !", "create_files_table"); + } + my $locallanguage = $onefile->{'specificlanguage'}; + my $property = "IS" . $onefile->{'windows_language'}; + my $value = 1; + my $condition = $property . "=" . $value; + + $onefile->{'ComponentCondition'} = $condition; - if ( $^O =~ /cygwin/i ) { installer::worker::generate_cygwin_pathes($filesref); } - - # The filenames must be collected because of uniqueness - # 01-44-~1.DAT, 01-44-~2.DAT, ... - # my @shortnames = (); - my %shortnames = (); - - installer::windows::idtglobal::write_idt_header(\@filetable, "file"); - installer::windows::idtglobal::write_idt_header(\@filehashtable, "filehash"); - - for ( my $i = 0; $i <= $#{$filesref}; $i++ ) - { - my %file = (); + if ( exists($installer::globals::componentcondition{$onefile->{'componentname'}})) + { + if ( $installer::globals::componentcondition{$onefile->{'componentname'}} ne $condition ) + { + installer::exiter::exit_program( + sprintf( + "ERROR: There is already another component condition for file %s: \"%s\" and \"%s\" !", + $onefile->{'gid'}, + $installer::globals::componentcondition{$onefile->{'componentname'}}, + $condition), + "create_files_table"); + } + } + else + { + $installer::globals::componentcondition{$onefile->{'componentname'}} = $condition; + } - my $onefile = ${$filesref}[$i]; + # collecting all properties for table Property + if ( ! exists($installer::globals::languageproperties{$property}) ) + { + $installer::globals::languageproperties{$property} = $value; + } + } +} - my $styles = ""; - if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } - if (( $styles =~ /\bJAVAFILE\b/ ) && ( ! ($allvariables->{'JAVAPRODUCT'} ))) { next; } - $file{'Component_'} = get_file_component_name($onefile, $filesref); - $file{'File'} = generate_unique_filename_for_filetable($onefile, $file{'Component_'}); - - $onefile->{'uniquename'} = $file{'File'}; - $onefile->{'componentname'} = $file{'Component_'}; - # Collecting all components - # if (!(installer::existence::exists_in_array($file{'Component_'}, $allfilecomponentsref))) { push(@{$allfilecomponentsref}, $file{'Component_'}); } - if ( ! exists($allfilecomponents{$file{'Component_'}}) ) { $allfilecomponents{$file{'Component_'}} = 1; } +sub has_style ($$) +{ + my ($style_list_string, $style_name) = @_; - $file{'FileName'} = generate_filename_for_filetable($onefile, \%shortnames); + return 0 unless defined $style_list_string; + return $style_list_string =~ /\b$style_name\b/ ? 1 : 0; +} - $file{'FileSize'} = get_filesize($onefile); - $file{'Version'} = get_fileversion($onefile, $allvariables, $styles); - $file{'Language'} = get_language_for_file($onefile); - - if ( $styles =~ /\bDONT_PACK\b/ ) { $file{'Attributes'} = "8192"; } - else { $file{'Attributes'} = "16384"; } - # $file{'Attributes'} = "16384"; # Sourcefile is packed - # $file{'Attributes'} = "8192"; # Sourcefile is unpacked +sub prepare_file_table_creation ($$$) +{ + my ($file_list, $directory_list, $allvariables) = @_; + + if ( $^O =~ /cygwin/i ) + { + installer::worker::generate_cygwin_pathes($file_list); + } - $installer::globals::insert_file_at_end = 0; - $counter++; - $file{'Sequence'} = $counter; + # Reset the fields 'sequencenumber' and 'uniquename'. They should not yet exist but better be sure. + foreach my $file (@$file_list) + { + delete $file->{'sequencenumber'}; + delete $file->{'uniquename'}; + } - $onefile->{'sequencenumber'} = $file{'Sequence'}; + # Create FileSequenceList object for the old sequence data. + if (defined $installer::globals::source_msi) + { + my $previous_sequence_data = new installer::patch::FileSequenceList(); + $previous_sequence_data->SetFromMsi($installer::globals::source_msi); + my @added_files = retrieve_sequence_and_uniquename($file_list, $previous_sequence_data); + + # Extract just the unique names. + my %target_unique_names = map {$_->{'uniquename'} => 1} @$file_list; + my @removed_items = $previous_sequence_data->get_removed_files(\%target_unique_names); + + $installer::logger::Lang->printf( + "there are %d files that have been removed from source and %d files added\n", + scalar @removed_items, + scalar @added_files); + + my $file_map = $installer::globals::source_msi->GetFileMap(); + my $index = 0; + foreach my $removed_row (@removed_items) + { + $installer::logger::Lang->printf(" removed file %d: %s\n", + ++$index, + $removed_row->GetValue('File')); + my $directory = $file_map->{$removed_row->GetValue('File')}->{'directory'}; + while (my ($key,$value) = each %$directory) + { + $installer::logger::Lang->printf(" %16s -> %s\n", $key, $value); + } + } + $index = 0; + foreach my $added_file (@added_files) + { + $installer::logger::Lang->printf(" added file %d: %s\n", + ++$index, + $added_file->{'uniquename'}); + installer::scriptitems::print_script_item($added_file); + } + my @new_files = create_items_for_missing_files( + \@removed_items, + $installer::globals::source_msi, + $directory_list); + push @$file_list, @new_files; + } + assign_missing_sequence_numbers($file_list); - my $oneline = $file{'File'} . "\t" . $file{'Component_'} . "\t" . $file{'FileName'} . "\t" - . $file{'FileSize'} . "\t" . $file{'Version'} . "\t" . $file{'Language'} . "\t" - . $file{'Attributes'} . "\t" . $file{'Sequence'} . "\n"; + foreach my $file (@$file_list) + { + if ( ! defined $file->{'componentname'}) + { + $file->{'componentname'} = get_file_component_name($file, $file_list); + } + if ( ! defined $file->{'uniquename'}) + { + $file->{'uniquename'} = generate_unique_filename_for_filetable($file->{'Name'}); + } - push(@filetable, $oneline); - - if ( ! $installer::globals::insert_file_at_end ) { push(@allfiles, $onefile); } - # Collecting all component conditions - if ( $onefile->{'ComponentCondition'} ) + if ( $file->{'ComponentCondition'} ) { - if ( ! exists($installer::globals::componentcondition{$file{'Component_'}})) + if ( ! exists($installer::globals::componentcondition{$file->{'componentname'}})) { - $installer::globals::componentcondition{$file{'Component_'}} = $onefile->{'ComponentCondition'}; + $installer::globals::componentcondition{$file->{'componentname'}} + = $file->{'ComponentCondition'}; } } - # Collecting also all tree conditions for multilayer products - get_tree_condition_for_component($onefile, $file{'Component_'}); + get_tree_condition_for_component($file, $file->{'componentname'}); # Collecting all component names, that have flag VERSION_INDEPENDENT_COMP_ID # This should be all components with constant API, for example URE - if ( $styles =~ /\bVERSION_INDEPENDENT_COMP_ID\b/ ) + if (has_style($file->{'Styles'}, "VERSION_INDEPENDENT_COMP_ID")) { - $installer::globals::base_independent_components{$onefile->{'componentname'}} = 1; + $installer::globals::base_independent_components{$file->{'componentname'}} = 1; } - # Collecting all component ids, that are defined at files in scp project (should not be used anymore) - if ( $onefile->{'CompID'} ) - { - if ( ! exists($installer::globals::componentid{$onefile->{'componentname'}})) - { - $installer::globals::componentid{$onefile->{'componentname'}} = $onefile->{'CompID'}; - } - else - { - if ( $installer::globals::componentid{$onefile->{'componentname'}} ne $onefile->{'CompID'} ) - { - installer::exiter::exit_program("ERROR: There is already a ComponentID for component \"$onefile->{'componentname'}\" : \"$installer::globals::componentid{$onefile->{'componentname'}}\" . File \"$onefile->{'gid'}\" uses \"$onefile->{'CompID'}\" !", "create_files_table"); - } - } - - # Also checking vice versa. Is this ComponentID already used? If yes, is the componentname the same? - - if ( ! exists($installer::globals::comparecomponentname{$onefile->{'CompID'}})) - { - $installer::globals::comparecomponentname{$onefile->{'CompID'}} = $onefile->{'componentname'}; - } - else - { - if ( $installer::globals::comparecomponentname{$onefile->{'CompID'}} ne $onefile->{'componentname'} ) - { - installer::exiter::exit_program("ERROR: There is already a component for ComponentID \"$onefile->{'CompID'}\" : \"$installer::globals::comparecomponentname{$onefile->{'CompID'}}\" . File \"$onefile->{'gid'}\" has same component id but is included in component \"$onefile->{'componentname'}\" !", "create_files_table"); - } - } - } + # Special handling for files in PREDEFINED_OSSHELLNEWDIR. These components + # need as KeyPath a RegistryItem in HKCU + if ($file->{'needs_user_registry_key'} + || (defined $file->{'Dir'} && $file->{'Dir'} =~ /\bPREDEFINED_OSSHELLNEWDIR\b/)) + { + my $keypath = generate_registry_keypath($file); + $file->{'userregkeypath'} = $keypath; + push(@installer::globals::userregistrycollector, $file); + $installer::globals::addeduserregitrykeys = 1; + } - # Collecting all language specific conditions - # if ( $onefile->{'haslanguagemodule'} ) - if ( $onefile->{'ismultilingual'} ) - { - if ( $onefile->{'ComponentCondition'} ) { installer::exiter::exit_program("ERROR: Cannot set language condition. There is already another component condition for file $onefile->{'gid'}: \"$onefile->{'ComponentCondition'}\" !", "create_files_table"); } - - if ( $onefile->{'specificlanguage'} eq "" ) { installer::exiter::exit_program("ERROR: There is no specific language for file at language module: $onefile->{'gid'} !", "create_files_table"); } - my $locallanguage = $onefile->{'specificlanguage'}; - my $property = "IS" . $file{'Language'}; - my $value = 1; - my $condition = $property . "=" . $value; - - $onefile->{'ComponentCondition'} = $condition; + $file->{'windows_language'} = get_language_for_file($file); - if ( exists($installer::globals::componentcondition{$file{'Component_'}})) - { - if ( $installer::globals::componentcondition{$file{'Component_'}} ne $condition ) { installer::exiter::exit_program("ERROR: There is already another component condition for file $onefile->{'gid'}: \"$installer::globals::componentcondition{$file{'Component_'}}\" and \"$condition\" !", "create_files_table"); } - } - else - { - $installer::globals::componentcondition{$file{'Component_'}} = $condition; - } + process_language_conditions($file); + } - # collecting all properties for table Property - if ( ! exists($installer::globals::languageproperties{$property}) ) { $installer::globals::languageproperties{$property} = $value; } - } + # The filenames must be collected because of uniqueness + # 01-44-~1.DAT, 01-44-~2.DAT, ... + my %shortnames = (); + foreach my $file (@$file_list) + { + $file->{'short_name'} = generate_filename_for_filetable($file, \%shortnames); + } +} - if ( $installer::globals::prepare_winpatch ) - { - my $path = $onefile->{'sourcepath'}; - if ( $^O =~ /cygwin/i ) { $path = $onefile->{'cyg_sourcepath'}; } - open(FILE, $path) or die "ERROR: Can't open $path for creating file hash"; - binmode(FILE); - my $hashinfo = pack("l", 20); - $hashinfo .= Digest::MD5->new->addfile(*FILE)->digest; - my @i = unpack ('x[l]l4', $hashinfo); - $oneline = $file{'File'} . "\t" . - "0" . "\t" . - $i[0] . "\t" . - $i[1] . "\t" . - $i[2] . "\t" . - $i[3] . "\n"; - push (@filehashtable, $oneline); - } - # Saving the sequence number in a hash with uniquefilename as key. - # This is used for better performance in "save_packorder" - $installer::globals::uniquefilenamesequence{$onefile->{'uniquename'}} = $onefile->{'sequencenumber'}; - - # Special handling for files in PREDEFINED_OSSHELLNEWDIR. These components - # need as KeyPath a RegistryItem in HKCU - my $destdir = ""; - if ( $onefile->{'Dir'} ) { $destdir = $onefile->{'Dir'}; } +sub create_file_table_data ($$) +{ + my ($file_list, $allvariables) = @_; + + my @file_table_data = (); + foreach my $file (@$file_list) + { + my $attributes; + if (has_style($file->{'Styles'}, "DONT_PACK")) + { + # Sourcefile is unpacked (msidbFileAttributesNoncompressed). + $attributes = "8192"; + } + else + { + # Sourcefile is packed (msidbFileAttributesCompressed). + $attributes = "16384"; + } - if (( $destdir =~ /\bPREDEFINED_OSSHELLNEWDIR\b/ ) || ( $onefile->{'needs_user_registry_key'} )) - { - my $keypath = generate_registry_keypath($onefile); - $onefile->{'userregkeypath'} = $keypath; - push(@installer::globals::userregistrycollector, $onefile); - $installer::globals::addeduserregitrykeys = 1; - } + my $row_data = { + 'File' => $file->{'uniquename'}, + 'Component_' => $file->{'componentname'}, + 'FileName' => $file->{'short_name'}, + 'FileSize' => get_filesize($file), + 'Version' => get_fileversion($file, $allvariables), + 'Language' => $file->{'windows_language'}, + 'Attributes' => $attributes, + 'Sequence' => $file->{'sequencenumber'} + }; + push @file_table_data, $row_data; } - # putting content from %allfilecomponents to $allfilecomponentsref for later usage - foreach $localkey (keys %allfilecomponents ) { push( @{$allfilecomponentsref}, $localkey); } + return \@file_table_data; +} + + + + +sub collect_components ($) +{ + my ($file_list) = @_; + + my %components = (); + foreach my $file (@$file_list) + { + $components{$file->{'componentname'}} = 1; + } + return keys %components; +} + + + + +=head filter_files($file_list, $allvariables) + + Filter out Java files when not building a Java product. + + Is this still triggered? + +=cut +sub filter_files ($$) +{ + my ($file_list, $allvariables) = @_; + + if ($allvariables->{'JAVAPRODUCT'}) + { + return $file_list; + } + else + { + my @filtered_files = (); + foreach my $file (@$file_list) + { + if ( ! has_style($file->{'Styles'}, "JAVAFILE")) + { + push @filtered_files, $file; + } + } + return \@filtered_files; + } +} + + + + +# Structure of the files table: +# File Component_ FileName FileSize Version Language Attributes Sequence +sub create_file_table ($$) +{ + my ($file_table_data, $basedir) = @_; + + # Set up the 'File' table. + my @filetable = (); + installer::windows::idtglobal::write_idt_header(\@filetable, "file"); + my @keys = ('File', 'Component_', 'FileName', 'FileSize', 'Version', 'Language', 'Attributes', 'Sequence'); + my $index = 0; + foreach my $row_data (@$file_table_data) + { + ++$index; + my @values = map {$row_data->{$_}} @keys; + my $line = join("\t", @values) . "\n"; + push(@filetable, $line); + } - my $filetablename = $basedir . $installer::globals::separator . "File.idt"; + my $filetablename = $basedir . $installer::globals::separator . "File.idt"; installer::files::save_file($filetablename ,\@filetable); $installer::logger::Lang->print("\n"); $installer::logger::Lang->printf("Created idt file: %s\n", $filetablename); +} - $installer::logger::Lang->add_timestamp("Performance Info: File Table end"); - - my $filehashtablename = $basedir . $installer::globals::separator . "MsiFileHash.idt"; - installer::files::save_file($filehashtablename ,\@filehashtable); - $installer::logger::Lang->print("\n"); - $installer::logger::Lang->printf("Created idt file: %s\n", $filehashtablename); - # Now the new files can be added to the files collector (only in update packaging processes) - if ( $installer::globals::newfilesexist ) - { - foreach my $seq (sort keys %installer::globals::newfilescollector) { push(@allfiles, $installer::globals::newfilescollector{$seq}) } - } - return \@allfiles; + +sub create_filehash_table ($$) +{ + my ($file_list, $basedir) = @_; + + my @filehashtable = (); + + if ( $installer::globals::prepare_winpatch ) + { + + installer::windows::idtglobal::write_idt_header(\@filehashtable, "filehash"); + + foreach my $file (@$file_list) + { + my $path = $file->{'sourcepath'}; + if ($^O =~ /cygwin/i) + { + $path = $file->{'cyg_sourcepath'}; + } + + open(FILE, $path) or die "ERROR: Can't open $path for creating file hash"; + binmode(FILE); + my $hashinfo = pack("l", 20); + $hashinfo .= Digest::MD5->new->addfile(*FILE)->digest; + + my @i = unpack ('x[l]l4', $hashinfo); + my $oneline = join("\t", + ( + $file->{'uniquename'}, + "0", + @i + )); + push (@filehashtable, $oneline . "\n"); + } + + my $filehashtablename = $basedir . $installer::globals::separator . "MsiFileHash.idt"; + installer::files::save_file($filehashtablename ,\@filehashtable); + $installer::logger::Lang->print("\n"); + $installer::logger::Lang->printf("Created idt file: %s\n", $filehashtablename); + } } + 1; Modified: openoffice/trunk/main/solenv/bin/modules/installer/windows/msiglobal.pm URL: http://svn.apache.org/viewvc/openoffice/trunk/main/solenv/bin/modules/installer/windows/msiglobal.pm?rev=1547732&r1=1547731&r2=1547732&view=diff ============================================================================== --- openoffice/trunk/main/solenv/bin/modules/installer/windows/msiglobal.pm (original) +++ openoffice/trunk/main/solenv/bin/modules/installer/windows/msiglobal.pm Wed Dec 4 08:51:30 2013 @@ -37,6 +37,8 @@ use installer::systemactions; use installer::worker; use installer::windows::idtglobal; use installer::windows::language; +use installer::patch::ReleasesList; + use strict; ########################################################################### @@ -498,11 +500,7 @@ sub get_packagecode_for_sis { # always generating a new package code for each package - my $guidref = get_guid_list(1, 1); # only one GUID shall be generated - - ${$guidref}[0] =~ s/\s*$//; # removing ending spaces - - my $guid = "\{" . ${$guidref}[0] . "\}"; + my $guid = "\{" . create_guid() . "\}"; my $infoline = "PackageCode: $guid\n"; $installer::logger::Lang->print($infoline); @@ -1127,47 +1125,19 @@ sub copy_child_projects_into_installset } } -################################################################# -# Getting a list of GUID using uuidgen.exe. -# This works only on Windows -################################################################# -sub get_guid_list -{ - my ($number, $log) = @_; - if ( $log ) { installer::logger::include_header_into_logfile("Generating $number GUID"); } - - my $uuidgen = "uuidgen.exe"; # Has to be in the path - - # "-c" for uppercase output - - # my $systemcall = "$uuidgen -n$number -c |"; - my $systemcall = "$uuidgen -n$number |"; - open (UUIDGEN, "$systemcall" ) or die("uuidgen is missing."); - my @uuidlist = ; - close (UUIDGEN); +=head2 create_guid () - my $infoline = "Systemcall: $systemcall\n"; - if ( $log ) { $installer::logger::Lang->print($infoline); } - - my $comparenumber = $#uuidlist + 1; - - if ( $comparenumber == $number ) - { - $infoline = "Success: Executed $uuidgen successfully!\n"; - if ( $log ) { $installer::logger::Lang->print($infoline); } - } - else - { - $infoline = "ERROR: Could not execute $uuidgen successfully!\n"; - if ( $log ) { $installer::logger::Lang->print($infoline); } - } - - # uppercase, no longer "-c", because this is only supported in uuidgen.exe v.1.01 - for ( my $i = 0; $i <= $#uuidlist; $i++ ) { $uuidlist[$i] = uc($uuidlist[$i]); } - - return \@uuidlist; + Create a single UUID aka GUID via calling the external executable 'uuidgen'. + There are Perl modules for that, but do they exist on the build bots? + +=cut +sub create_guid () +{ + my $uuid = qx("uuidgen"); + $uuid =~ s/\s*$//; + return uc($uuid); } ################################################################# @@ -1188,6 +1158,9 @@ sub calculate_guid # my $id = pack("A32", $digest); my ($first, $second, $third, $fourth, $fifth) = unpack ('A8 A4 A4 A4 A12', $digest); $guid = "$first-$second-$third-$fourth-$fifth"; + + $installer::logger::Lang->printf("guid for '%s' is %s\n", + $string, $guid); return $guid; } @@ -1264,7 +1237,7 @@ sub create_new_component_file # This works only on Windows ################################################################# -sub set_uuid_into_component_table +sub __set_uuid_into_component_table { my ($idtdirbase, $allvariables) = @_; @@ -1303,19 +1276,32 @@ sub set_uuid_into_component_table { # Calculating new GUID with the help of the component name. my $useooobaseversion = 1; - if ( exists($installer::globals::base_independent_components{$componentname})) { $useooobaseversion = 0; } + if ( exists($installer::globals::base_independent_components{$componentname})) + { + $useooobaseversion = 0; + } my $sourcestring = $componentname; if ( $useooobaseversion ) { - if ( ! exists($allvariables->{'OOOBASEVERSION'}) ) { installer::exiter::exit_program("ERROR: Could not find variable \"OOOBASEVERSION\" (required value for GUID creation)!", "set_uuid_into_component_table"); } + if ( ! exists($allvariables->{'OOOBASEVERSION'}) ) + { + installer::exiter::exit_program( + "ERROR: Could not find variable \"OOOBASEVERSION\" (required value for GUID creation)!", + "set_uuid_into_component_table"); + } $sourcestring = $sourcestring . "_" . $allvariables->{'OOOBASEVERSION'}; } $uuid = calculate_guid($sourcestring); $counter++; # checking, if there is a conflict with an already created guid - if ( exists($installer::globals::allcalculated_guids{$uuid}) ) { installer::exiter::exit_program("ERROR: \"$uuid\" was already created before!", "set_uuid_into_component_table"); } + if ( exists($installer::globals::allcalculated_guids{$uuid}) ) + { + installer::exiter::exit_program( + "ERROR: \"$uuid\" was already created before!", + "set_uuid_into_component_table"); + } $installer::globals::allcalculated_guids{$uuid} = 1; $installer::globals::calculated_component_guids{$componentname} = $uuid; @@ -1631,107 +1617,138 @@ sub execute_packaging $installer::logger::Lang->print($infoline); } -############################################################### -# Setting the global variables ProductCode and the UpgradeCode -############################################################### -sub set_global_code_variables ($$) -{ - my ($languagesref, $allvariableshashref) = @_; +=head2 get_source_codes($languagesref) - # In the msi template directory a files "codes.txt" has to exist, in which the ProductCode - # and the UpgradeCode for the product are defined. - # The name "codes.txt" can be overwritten in Product definition with CODEFILENAME . - # Default $installer::globals::codefilename is defined in parameter.pm. - - if ( $allvariableshashref->{'CODEFILENAME'} ) - { - $installer::globals::codefilename = $installer::globals::idttemplatepath . $installer::globals::separator . $allvariableshashref->{'CODEFILENAME'}; - installer::files::check_file($installer::globals::codefilename); - } - - my $infoline = "Using Codes file: $installer::globals::codefilename \n"; - $installer::logger::Lang->print($infoline); - - my $codefile = installer::files::read_file($installer::globals::codefilename); - - my $isopensource = 0; - if ( $allvariableshashref->{'OPENSOURCE'} ) { $isopensource = $allvariableshashref->{'OPENSOURCE'}; } + Return product code and upgrade code from the source version. + When no source version is defined then return undef for both. + +=cut +sub get_source_codes ($) +{ + my ($languagesref) = @_; + + if ( ! defined $installer::globals::source_version) + { + return; + } + + my $onelanguage = installer::languages::get_key_language($languagesref); + + my $release_data = installer::patch::ReleasesList::Instance() + ->{$installer::globals::source_version} + ->{$installer::globals::packageformat}; + if (defined $release_data) + { + my $language_data = $release_data->{$onelanguage}; + if (defined $language_data) + { + $installer::logger::Lang->printf("source product code is %s\n", $language_data->{'product-code'}); + $installer::logger::Lang->printf("source upgrade code is %s\n", $release_data->{'upgrade-code'}); + + return ( + $language_data->{'product-code'}, + $release_data->{'upgrade-code'} + ); + } + else + { + $installer::logger::Info->printf( + "Warning: can not access information about previous version %s and language %s\n", + $installer::globals::source_version, + $onelanguage); + return (undef,undef); + } + } + else + { + $installer::logger::Info->printf("Warning: can not access information about previous version %s\n", + $installer::globals::source_version); + return (undef,undef); + } +} - my $onelanguage = ""; - - if ( $#{$languagesref} > 0 ) # more than one language - { - if (( $installer::globals::added_english ) && ( $#{$languagesref} == 1 )) # only multilingual because of added English - { - $onelanguage = ${$languagesref}[1]; # setting the first language, that is not english - } - else - { - if (( ${$languagesref}[1] =~ /jp/ ) || - ( ${$languagesref}[1] =~ /ko/ ) || - ( ${$languagesref}[1] =~ /zh/ )) - { - $onelanguage = "multiasia"; - } - else - { - $onelanguage = "multiwestern"; - } - } - } - else # only one language - { - $onelanguage = ${$languagesref}[0]; - } - # ProductCode must not change, if Windows patches shall be applied - if ( $installer::globals::prepare_winpatch ) - { - # ProductCode has to be specified in each language - my $searchstring = "PRODUCTCODE"; - my $codeblock = installer::windows::idtglobal::get_language_block_from_language_file($searchstring, $codefile); - $installer::globals::productcode = installer::windows::idtglobal::get_code_from_code_block($codeblock, $onelanguage); - } else { - my $guidref = get_guid_list(1, 1); # only one GUID shall be generated - ${$guidref}[0] =~ s/\s*$//; # removing ending spaces - $installer::globals::productcode = "\{" . ${$guidref}[0] . "\}"; - } - if ( $installer::globals::patch ) # patch upgrade codes are defined in soffice.lst - { - if ( $allvariableshashref->{'PATCHUPGRADECODE'} ) { $installer::globals::upgradecode = $allvariableshashref->{'PATCHUPGRADECODE'}; } - else { installer::exiter::exit_program("ERROR: PATCHUPGRADECODE not defined in list file!", "set_global_code_variables"); } - } - else - { - # UpgradeCode can take english as default, if not defined in specified language - my $searchstring = "UPGRADECODE"; # searching in the codes.txt file - my $codeblock = installer::windows::idtglobal::get_language_block_from_language_file($searchstring, $codefile); - $installer::globals::upgradecode = installer::windows::idtglobal::get_language_string_from_language_block($codeblock, $onelanguage, ""); - } - - # if (( $installer::globals::productcode eq "" ) && ( ! $isopensource )) { installer::exiter::exit_program("ERROR: ProductCode for language $onelanguage not defined in $installer::globals::codefilename !", "set_global_code_variables"); } - if ( $installer::globals::upgradecode eq "" ) { installer::exiter::exit_program("ERROR: UpgradeCode not defined in $installer::globals::codefilename !", "set_global_code_variables"); } +=head2 set_global_code_variables ($languagesref, $allvariableshashref) + + Determine values for the product code and upgrade code of the target version. + + As perparation for building a Windows patch, certain conditions have to be fullfilled. + - The upgrade code changes from old to new version + - The product code remains the same + In order to inforce that we have to access information about the source version. + + The resulting values are stored as global variables + $installer::globals::productcode + $installer::globals::upgradecode + and as variables in the given hash + $allvariableshashref->{'PRODUCTCODE'} + $allvariableshashref->{'UPGRADECODE'} - $infoline = "Setting ProductCode to: $installer::globals::productcode \n"; - $installer::logger::Lang->print($infoline); - $infoline = "Setting UpgradeCode to: $installer::globals::upgradecode \n"; - $installer::logger::Lang->print($infoline); +=cut +sub set_global_code_variables ($$) +{ + my ($languagesref, $allvariableshashref) = @_; - # Adding both variables into the variables array + my ($source_product_code, $source_upgrade_code) = get_source_codes($languagesref); + my ($target_product_code, $target_upgrade_code) = (undef, undef); + + if (defined $source_product_code && defined $source_upgrade_code) + { + if ($installer::globals::is_major_release) + { + # For a major release we have to change the product code. + $target_product_code = "{" . create_guid() . "}"; + $installer::logger::Lang->printf("building a major release, created new product code %s\n", + $target_product_code); + + # Let's do a paranoia check that the new and the old guids are + # different. In reality the new guid really has to be + # different from all other guids used for * codes, components, + # etc. + if ($target_product_code eq $source_product_code) + { + installer::logger::PrintError( + "new GUID for product code is the same as the old product code but should be different."); + } + } + else + { + # For minor or micro releases we have to keeep the old product code. + $target_product_code = "{" . $source_product_code . "}"; + $installer::logger::Lang->printf("building a minor or micro release, reusing product code %s\n", + $target_product_code); + } + + $target_upgrade_code = "{" . create_guid() . "}"; + # Again, just one test for paranoia. + if ($target_upgrade_code eq $source_upgrade_code) + { + installer::logger::PrintError( + "new GUID for upgrade code is the same as the old upgrade code but should be different."); + } + } + else + { + # There is no previous version with which to compare the product code. + # Just create two new uuids. + $target_product_code = "{" . create_guid() . "}"; + $target_upgrade_code = "{" . create_guid() . "}"; + } + + $installer::globals::productcode = $target_product_code; + $installer::globals::upgradecode = $target_upgrade_code; + $allvariableshashref->{'PRODUCTCODE'} = $target_product_code; + $allvariableshashref->{'UPGRADECODE'} = $target_upgrade_code; - $allvariableshashref->{'PRODUCTCODE'} = $installer::globals::productcode; - $allvariableshashref->{'UPGRADECODE'} = $installer::globals::upgradecode; + $installer::logger::Lang->printf("target product code is %s\n", $target_product_code); + $installer::logger::Lang->printf("target upgrade code is %s\n", $target_upgrade_code); +} - $infoline = "Defined variable PRODUCTCODE: $installer::globals::productcode \n"; - $installer::logger::Lang->print($infoline); - $infoline = "Defined variable UPGRADECODE: $installer::globals::upgradecode \n"; - $installer::logger::Lang->print($infoline); -} ############################################################### # Setting the product version used in property table and Modified: openoffice/trunk/main/solenv/bin/modules/installer/windows/registry.pm URL: http://svn.apache.org/viewvc/openoffice/trunk/main/solenv/bin/modules/installer/windows/registry.pm?rev=1547732&r1=1547731&r2=1547732&view=diff ============================================================================== --- openoffice/trunk/main/solenv/bin/modules/installer/windows/registry.pm (original) +++ openoffice/trunk/main/solenv/bin/modules/installer/windows/registry.pm Wed Dec 4 08:51:30 2013 @@ -29,6 +29,8 @@ use installer::worker; use installer::windows::msiglobal; use installer::windows::idtglobal; +use strict; + ##################################################### # Generating the component name from a registryitem ##################################################### @@ -284,25 +286,6 @@ sub get_registry_val64 return $value; } -############################################################## -# Returning component for registry table. -############################################################## - -sub get_registry_component -{ - my ($registry, $allvariables) = @_; - - # All registry items belonging to one module can - # be included into one component - - my $componentname = get_registry_component_name($registry, $allvariables); - - # saving componentname in the registryitem collector - - $registry->{'componentname'} = $componentname; - - return $componentname; -} ###################################################### # Adding the content of @@ -345,20 +328,13 @@ sub add_userregs_to_registry_table # Content: # Registry Root Key Name Value Component_ ###################################################### - -sub create_registry_table +sub prepare_registry_table ($$$) { - my ($registryref, $allregistrycomponentsref, $basedir, $languagesarrayref, $allvariableshashref) = @_; + my ($registryref, $languagesarrayref, $allvariableshashref) = @_; my %table_data = (); foreach my $onelanguage (@$languagesarrayref) { - - my @registrytable = (); - my @reg64table = (); - - installer::windows::idtglobal::write_idt_header(\@registrytable, "registry"); - installer::windows::idtglobal::write_idt_header(\@reg64table, "reg64"); my $table_items = []; foreach my $oneregistry (@$registryref) { @@ -381,12 +357,6 @@ sub create_registry_table $oneregistry->{'componentname'} = $component_name; $registry{'Component_'} = $component_name; - # Collecting all components - if (!(installer::existence::exists_in_array($registry{'Component_'}, $allregistrycomponentsref))) - { - push(@{$allregistrycomponentsref}, $registry{'Component_'}); - } - # Collecting all components with DONT_DELETE style my $style = $oneregistry->{'Styles'} // ""; $registry{'styles'} = $style; @@ -420,14 +390,93 @@ sub create_registry_table } } - my $oneline = $registry{'Registry'} . "\t" . $registry{'Root'} . "\t" . $registry{'Key'} . "\t" - . $registry{'Name'} . "\t" . $registry{'Value'} . "\t" . $registry{'Component_'} . "\n"; + push @$table_items, \%registry; + } + $table_data{$onelanguage} = $table_items; + } + + return \%table_data; +} + + + + +sub collect_registry_components ($) +{ + my ($table_data) = @_; + + my %components = (); + foreach my $language_data (values %$table_data) + { + foreach my $item (@$language_data) + { + $components{$item->{'Component_'}} = 1; + } + } + return keys %components; +} + + - my $oneline64 = $registry{'Registry'} . "\t" . $registry{'Root'} . "\t" . $registry{'Key'} . "\t" - . $registry{'Name'} . "\t" . $registry{'Val64'} . "\t" . $registry{'Component_'} . "\n"; - if ( ! ( $style =~ /\bX64_ONLY\b/ )) { push(@registrytable, $oneline); } # standard registry table for 32 Bit - if (( $style =~ /\bX64\b/ ) || ( $style =~ /\bX64_ONLY\b/ )) { push(@reg64table , $oneline64); } +sub translate_component_names ($$$) +{ + my ($translation_map, $registry_items, $table_data) = @_; + + my $replacement_count = 0; + foreach my $item (@$registry_items) + { + my $translated_name = $translation_map->{$item->{'componentname'}}; + if (defined $translated_name) + { + $item->{'componentname'} = $translated_name; + ++$replacement_count; + } + } + $installer::logger::Lang->printf("replaced %d component names in registry items\n", $replacement_count); + + $replacement_count = 0; + foreach my $language_data (values %$table_data) + { + foreach my $item (@$language_data) + { + my $translated_name = $translation_map->{$item->{'Component_'}}; + if (defined $translated_name) + { + $item->{'Component_'} = $translated_name; + ++$replacement_count; + } + } + } + $installer::logger::Lang->printf("replaced %d component names in registry table\n", $replacement_count); +} + + + + +sub create_registry_table_32 ($$$$) +{ + my ($basedir, $languagesarrayref, $allvariableshashref, $table_data) = @_; + + foreach my $onelanguage (@$languagesarrayref) + { + my @registrytable = (); + installer::windows::idtglobal::write_idt_header(\@registrytable, "registry"); + + foreach my $item (@{$table_data->{$onelanguage}}) + { + next if $item->{'styles'} =~ /\bX64_ONLY\b/; + + my $oneline = join("\t", + $item->{'Registry'}, + $item->{'Root'}, + $item->{'Key'}, + $item->{'Name'}, + $item->{'Value'}, + $item->{'Component_'}) + . "\n"; + + push(@registrytable, $oneline); } # If there are added user registry keys for files collected in @@ -436,15 +485,47 @@ sub create_registry_table # files in PREDEFINED_OSSHELLNEWDIR, because their component # needs as KeyPath a RegistryItem in HKCU. - if ( $installer::globals::addeduserregitrykeys ) { add_userregs_to_registry_table(\@registrytable, $allvariableshashref); } + if ( $installer::globals::addeduserregitrykeys ) + { + add_userregs_to_registry_table(\@registrytable, $allvariableshashref); + } - # Saving the file - + # Save the database file. my $registrytablename = $basedir . $installer::globals::separator . "Registry.idt" . "." . $onelanguage; installer::files::save_file($registrytablename ,\@registrytable); $installer::logger::Lang->printf("Created idt file: %s\n", $registrytablename); + } +} + + + + +sub create_registry_table_64 ($$$$) +{ + my ($basedir, $languagesarrayref, $allvariableshashref, $table_data) = @_; + + foreach my $onelanguage (@$languagesarrayref) + { + my @reg64table = (); + installer::windows::idtglobal::write_idt_header(\@reg64table, "reg64"); + foreach my $item (@{$table_data->{$onelanguage}}) + { + next unless $item->{'styles'} =~ /\b(X64|X64_ONLY)\b/; + + my $oneline64 = join("\t", + $item->{'Registry'}, + $item->{'Root'}, + $item->{'Key'}, + $item->{'Name'}, + $item->{'Val64'}, + $item->{'Component_'}) + . "\n"; + + push(@reg64table , $oneline64); + } - $registrytablename = $basedir . $installer::globals::separator . "Reg64.idt" . "." . $onelanguage; + # Save the database file. + my $registrytablename = $basedir . $installer::globals::separator . "Reg64.idt" . "." . $onelanguage; installer::files::save_file($registrytablename ,\@reg64table ); $installer::logger::Lang->printf("Created idt file: %s\n", $registrytablename); }