1*b1cdbd2cSJim Jagielski#************************************************************** 2*b1cdbd2cSJim Jagielski# 3*b1cdbd2cSJim Jagielski# Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski# or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski# distributed with this work for additional information 6*b1cdbd2cSJim Jagielski# regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski# to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski# "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski# with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski# 11*b1cdbd2cSJim Jagielski# http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski# 13*b1cdbd2cSJim Jagielski# Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski# software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski# KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski# specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski# under the License. 19*b1cdbd2cSJim Jagielski# 20*b1cdbd2cSJim Jagielski#************************************************************** 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski 23*b1cdbd2cSJim Jagielski 24*b1cdbd2cSJim Jagielskipackage installer::windows::file; 25*b1cdbd2cSJim Jagielski 26*b1cdbd2cSJim Jagielskiuse Digest::MD5; 27*b1cdbd2cSJim Jagielskiuse installer::existence; 28*b1cdbd2cSJim Jagielskiuse installer::exiter; 29*b1cdbd2cSJim Jagielskiuse installer::files; 30*b1cdbd2cSJim Jagielskiuse installer::globals; 31*b1cdbd2cSJim Jagielskiuse installer::logger; 32*b1cdbd2cSJim Jagielskiuse installer::pathanalyzer; 33*b1cdbd2cSJim Jagielskiuse installer::worker; 34*b1cdbd2cSJim Jagielskiuse installer::windows::font; 35*b1cdbd2cSJim Jagielskiuse installer::windows::idtglobal; 36*b1cdbd2cSJim Jagielskiuse installer::windows::msiglobal; 37*b1cdbd2cSJim Jagielskiuse installer::windows::language; 38*b1cdbd2cSJim Jagielskiuse installer::patch::InstallationSet; 39*b1cdbd2cSJim Jagielskiuse installer::patch::FileSequenceList; 40*b1cdbd2cSJim Jagielskiuse File::Basename; 41*b1cdbd2cSJim Jagielskiuse File::Spec; 42*b1cdbd2cSJim Jagielskiuse strict; 43*b1cdbd2cSJim Jagielski 44*b1cdbd2cSJim Jagielski########################################################################## 45*b1cdbd2cSJim Jagielski# Assigning one cabinet file to each file. This is requrired, 46*b1cdbd2cSJim Jagielski# if cabinet files shall be equivalent to packages. 47*b1cdbd2cSJim Jagielski########################################################################## 48*b1cdbd2cSJim Jagielski 49*b1cdbd2cSJim Jagielskisub assign_cab_to_files 50*b1cdbd2cSJim Jagielski{ 51*b1cdbd2cSJim Jagielski my ( $filesref ) = @_; 52*b1cdbd2cSJim Jagielski 53*b1cdbd2cSJim Jagielski my $infoline = ""; 54*b1cdbd2cSJim Jagielski 55*b1cdbd2cSJim Jagielski foreach my $file (@$filesref) 56*b1cdbd2cSJim Jagielski { 57*b1cdbd2cSJim Jagielski if ( ! exists($file->{'modules'}) ) 58*b1cdbd2cSJim Jagielski { 59*b1cdbd2cSJim Jagielski installer::exiter::exit_program( 60*b1cdbd2cSJim Jagielski sprintf("ERROR: No module assignment found for %s", $file->{'gid'}), 61*b1cdbd2cSJim Jagielski "assign_cab_to_files"); 62*b1cdbd2cSJim Jagielski } 63*b1cdbd2cSJim Jagielski my $module = $file->{'modules'}; 64*b1cdbd2cSJim Jagielski # If modules contains a list of modules, only taking the first one. 65*b1cdbd2cSJim Jagielski if ( $module =~ /^\s*(.*?)\,/ ) { $module = $1; } 66*b1cdbd2cSJim Jagielski 67*b1cdbd2cSJim Jagielski if ( ! exists($installer::globals::allcabinetassigns{$module}) ) 68*b1cdbd2cSJim Jagielski { 69*b1cdbd2cSJim Jagielski installer::exiter::exit_program( 70*b1cdbd2cSJim Jagielski sprintf("ERROR: No cabinet file assigned to module \"%s\" %s", 71*b1cdbd2cSJim Jagielski $module, 72*b1cdbd2cSJim Jagielski $file->{'gid'}), 73*b1cdbd2cSJim Jagielski "assign_cab_to_files"); 74*b1cdbd2cSJim Jagielski } 75*b1cdbd2cSJim Jagielski $file->{'assignedcabinetfile'} = $installer::globals::allcabinetassigns{$module}; 76*b1cdbd2cSJim Jagielski 77*b1cdbd2cSJim Jagielski # Counting the files in each cabinet file 78*b1cdbd2cSJim Jagielski if ( ! exists($installer::globals::cabfilecounter{$file->{'assignedcabinetfile'}}) ) 79*b1cdbd2cSJim Jagielski { 80*b1cdbd2cSJim Jagielski $installer::globals::cabfilecounter{$file->{'assignedcabinetfile'}} = 1; 81*b1cdbd2cSJim Jagielski } 82*b1cdbd2cSJim Jagielski else 83*b1cdbd2cSJim Jagielski { 84*b1cdbd2cSJim Jagielski $installer::globals::cabfilecounter{$file->{'assignedcabinetfile'}}++; 85*b1cdbd2cSJim Jagielski } 86*b1cdbd2cSJim Jagielski } 87*b1cdbd2cSJim Jagielski 88*b1cdbd2cSJim Jagielski # assigning startsequencenumbers for each cab file 89*b1cdbd2cSJim Jagielski 90*b1cdbd2cSJim Jagielski my %count = (); 91*b1cdbd2cSJim Jagielski my $offset = 1; 92*b1cdbd2cSJim Jagielski foreach my $cabfile ( sort keys %installer::globals::cabfilecounter ) 93*b1cdbd2cSJim Jagielski { 94*b1cdbd2cSJim Jagielski my $filecount = $installer::globals::cabfilecounter{$cabfile}; 95*b1cdbd2cSJim Jagielski $count{$cabfile} = $filecount; 96*b1cdbd2cSJim Jagielski $installer::globals::cabfilecounter{$cabfile} = $offset; 97*b1cdbd2cSJim Jagielski $offset = $offset + $filecount; 98*b1cdbd2cSJim Jagielski 99*b1cdbd2cSJim Jagielski $installer::globals::lastsequence{$cabfile} = $offset - 1; 100*b1cdbd2cSJim Jagielski } 101*b1cdbd2cSJim Jagielski 102*b1cdbd2cSJim Jagielski # logging the number of files in each cabinet file 103*b1cdbd2cSJim Jagielski 104*b1cdbd2cSJim Jagielski $installer::logger::Lang->print("\n"); 105*b1cdbd2cSJim Jagielski $installer::logger::Lang->print("Cabinet files:\n"); 106*b1cdbd2cSJim Jagielski foreach my $cabfile (sort keys %installer::globals::cabfilecounter) 107*b1cdbd2cSJim Jagielski { 108*b1cdbd2cSJim Jagielski $installer::logger::Lang->printf( 109*b1cdbd2cSJim Jagielski "%-30s : %4s files, from %4d to %4d\n", 110*b1cdbd2cSJim Jagielski $cabfile, 111*b1cdbd2cSJim Jagielski $count{$cabfile}, 112*b1cdbd2cSJim Jagielski $installer::globals::cabfilecounter{$cabfile}, 113*b1cdbd2cSJim Jagielski $installer::globals::lastsequence{$cabfile}); 114*b1cdbd2cSJim Jagielski } 115*b1cdbd2cSJim Jagielski} 116*b1cdbd2cSJim Jagielski 117*b1cdbd2cSJim Jagielski########################################################################## 118*b1cdbd2cSJim Jagielski# Assigning sequencenumbers to files. This is requrired, 119*b1cdbd2cSJim Jagielski# if cabinet files shall be equivalent to packages. 120*b1cdbd2cSJim Jagielski########################################################################## 121*b1cdbd2cSJim Jagielski 122*b1cdbd2cSJim Jagielskisub assign_sequencenumbers_to_files 123*b1cdbd2cSJim Jagielski{ 124*b1cdbd2cSJim Jagielski my ( $filesref ) = @_; 125*b1cdbd2cSJim Jagielski 126*b1cdbd2cSJim Jagielski my %directaccess = (); 127*b1cdbd2cSJim Jagielski my %allassigns = (); 128*b1cdbd2cSJim Jagielski 129*b1cdbd2cSJim Jagielski for ( my $i = 0; $i <= $#{$filesref}; $i++ ) 130*b1cdbd2cSJim Jagielski { 131*b1cdbd2cSJim Jagielski my $onefile = ${$filesref}[$i]; 132*b1cdbd2cSJim Jagielski 133*b1cdbd2cSJim Jagielski # Keeping order in cabinet files 134*b1cdbd2cSJim Jagielski # -> collecting all files in one cabinet file 135*b1cdbd2cSJim Jagielski # -> sorting files and assigning numbers 136*b1cdbd2cSJim Jagielski 137*b1cdbd2cSJim Jagielski # Saving counter $i for direct access into files array 138*b1cdbd2cSJim Jagielski # "destination" of the file is a unique identifier ('Name' is not unique!) 139*b1cdbd2cSJim Jagielski if ( exists($directaccess{$onefile->{'destination'}}) ) { installer::exiter::exit_program("ERROR: 'destination' at file not unique: $onefile->{'destination'}", "assign_sequencenumbers_to_files"); } 140*b1cdbd2cSJim Jagielski $directaccess{$onefile->{'destination'}} = $i; 141*b1cdbd2cSJim Jagielski 142*b1cdbd2cSJim Jagielski my $cabfilename = $onefile->{'assignedcabinetfile'}; 143*b1cdbd2cSJim Jagielski # collecting files in cabinet files 144*b1cdbd2cSJim Jagielski if ( ! exists($allassigns{$cabfilename}) ) 145*b1cdbd2cSJim Jagielski { 146*b1cdbd2cSJim Jagielski my %onecabfile = (); 147*b1cdbd2cSJim Jagielski $onecabfile{$onefile->{'destination'}} = 1; 148*b1cdbd2cSJim Jagielski $allassigns{$cabfilename} = \%onecabfile; 149*b1cdbd2cSJim Jagielski } 150*b1cdbd2cSJim Jagielski else 151*b1cdbd2cSJim Jagielski { 152*b1cdbd2cSJim Jagielski $allassigns{$cabfilename}->{$onefile->{'destination'}} = 1; 153*b1cdbd2cSJim Jagielski } 154*b1cdbd2cSJim Jagielski } 155*b1cdbd2cSJim Jagielski 156*b1cdbd2cSJim Jagielski # Sorting each hash and assigning numbers 157*b1cdbd2cSJim Jagielski # The destination of the file determines the sort order, not the filename! 158*b1cdbd2cSJim Jagielski my $cabfile; 159*b1cdbd2cSJim Jagielski foreach $cabfile ( sort keys %allassigns ) 160*b1cdbd2cSJim Jagielski { 161*b1cdbd2cSJim Jagielski my $counter = $installer::globals::cabfilecounter{$cabfile}; 162*b1cdbd2cSJim Jagielski my $dest; 163*b1cdbd2cSJim Jagielski foreach $dest ( sort keys %{$allassigns{$cabfile}} ) # <- sorting the destination! 164*b1cdbd2cSJim Jagielski { 165*b1cdbd2cSJim Jagielski my $directaccessnumber = $directaccess{$dest}; 166*b1cdbd2cSJim Jagielski ${$filesref}[$directaccessnumber]->{'assignedsequencenumber'} = $counter; 167*b1cdbd2cSJim Jagielski $counter++; 168*b1cdbd2cSJim Jagielski } 169*b1cdbd2cSJim Jagielski } 170*b1cdbd2cSJim Jagielski} 171*b1cdbd2cSJim Jagielski 172*b1cdbd2cSJim Jagielski######################################################### 173*b1cdbd2cSJim Jagielski# Create a shorter version of a long component name, 174*b1cdbd2cSJim Jagielski# because maximum length in msi database is 72. 175*b1cdbd2cSJim Jagielski# Attention: In multi msi installation sets, the short 176*b1cdbd2cSJim Jagielski# names have to be unique over all packages, because 177*b1cdbd2cSJim Jagielski# this string is used to create the globally unique id 178*b1cdbd2cSJim Jagielski# -> no resetting of 179*b1cdbd2cSJim Jagielski# %installer::globals::allshortcomponents 180*b1cdbd2cSJim Jagielski# after a package was created. 181*b1cdbd2cSJim Jagielski# Using no counter because of reproducibility. 182*b1cdbd2cSJim Jagielski######################################################### 183*b1cdbd2cSJim Jagielski 184*b1cdbd2cSJim Jagielskisub generate_new_short_componentname 185*b1cdbd2cSJim Jagielski{ 186*b1cdbd2cSJim Jagielski my ($componentname) = @_; 187*b1cdbd2cSJim Jagielski 188*b1cdbd2cSJim Jagielski my $startversion = substr($componentname, 0, 60); # taking only the first 60 characters 189*b1cdbd2cSJim Jagielski my $subid = installer::windows::msiglobal::calculate_id($componentname, 9); # taking only the first 9 digits 190*b1cdbd2cSJim Jagielski my $shortcomponentname = $startversion . "_" . $subid; 191*b1cdbd2cSJim Jagielski 192*b1cdbd2cSJim Jagielski if ( exists($installer::globals::allshortcomponents{$shortcomponentname}) ) { installer::exiter::exit_program("Failed to create unique component name: \"$shortcomponentname\"", "generate_new_short_componentname"); } 193*b1cdbd2cSJim Jagielski 194*b1cdbd2cSJim Jagielski $installer::globals::allshortcomponents{$shortcomponentname} = 1; 195*b1cdbd2cSJim Jagielski 196*b1cdbd2cSJim Jagielski return $shortcomponentname; 197*b1cdbd2cSJim Jagielski} 198*b1cdbd2cSJim Jagielski 199*b1cdbd2cSJim Jagielski############################################### 200*b1cdbd2cSJim Jagielski# Generating the component name from a file 201*b1cdbd2cSJim Jagielski############################################### 202*b1cdbd2cSJim Jagielski 203*b1cdbd2cSJim Jagielskisub get_file_component_name 204*b1cdbd2cSJim Jagielski{ 205*b1cdbd2cSJim Jagielski my ($fileref, $filesref) = @_; 206*b1cdbd2cSJim Jagielski 207*b1cdbd2cSJim Jagielski my $componentname = ""; 208*b1cdbd2cSJim Jagielski 209*b1cdbd2cSJim Jagielski # Special handling for files with ASSIGNCOMPOMENT 210*b1cdbd2cSJim Jagielski 211*b1cdbd2cSJim Jagielski my $styles = ""; 212*b1cdbd2cSJim Jagielski if ( $fileref->{'Styles'} ) { $styles = $fileref->{'Styles'}; } 213*b1cdbd2cSJim Jagielski if ( $styles =~ /\bASSIGNCOMPOMENT\b/ ) 214*b1cdbd2cSJim Jagielski { 215*b1cdbd2cSJim Jagielski $componentname = get_component_from_assigned_file($fileref->{'AssignComponent'}, $filesref); 216*b1cdbd2cSJim Jagielski } 217*b1cdbd2cSJim Jagielski else 218*b1cdbd2cSJim Jagielski { 219*b1cdbd2cSJim Jagielski # In this function exists the rule to create components from files 220*b1cdbd2cSJim Jagielski # Rule: 221*b1cdbd2cSJim Jagielski # Two files get the same componentid, if: 222*b1cdbd2cSJim Jagielski # both have the same destination directory. 223*b1cdbd2cSJim Jagielski # both have the same "gid" -> both were packed in the same zip file 224*b1cdbd2cSJim Jagielski # All other files are included into different components! 225*b1cdbd2cSJim Jagielski 226*b1cdbd2cSJim Jagielski # my $componentname = $fileref->{'gid'} . "_" . $fileref->{'Dir'}; 227*b1cdbd2cSJim Jagielski 228*b1cdbd2cSJim Jagielski # $fileref->{'Dir'} is not sufficient! All files in a zip file have the same $fileref->{'Dir'}, 229*b1cdbd2cSJim Jagielski # but can be in different subdirectories. 230*b1cdbd2cSJim Jagielski # Solution: destination=share\Scripts\beanshell\Capitalise\capitalise.bsh 231*b1cdbd2cSJim Jagielski # in which the filename (capitalise.bsh) has to be removed and all backslashes (slashes) are 232*b1cdbd2cSJim Jagielski # converted into underline. 233*b1cdbd2cSJim Jagielski 234*b1cdbd2cSJim Jagielski my $destination = $fileref->{'destination'}; 235*b1cdbd2cSJim Jagielski installer::pathanalyzer::get_path_from_fullqualifiedname(\$destination); 236*b1cdbd2cSJim Jagielski $destination =~ s/\s//g; 237*b1cdbd2cSJim Jagielski $destination =~ s/\\/\_/g; 238*b1cdbd2cSJim Jagielski $destination =~ s/\//\_/g; 239*b1cdbd2cSJim Jagielski $destination =~ s/\_\s*$//g; # removing ending underline 240*b1cdbd2cSJim Jagielski 241*b1cdbd2cSJim Jagielski $componentname = $fileref->{'gid'} . "__" . $destination; 242*b1cdbd2cSJim Jagielski 243*b1cdbd2cSJim Jagielski # Files with different languages, need to be packed into different components. 244*b1cdbd2cSJim Jagielski # Then the installation of the language specific component is determined by a language condition. 245*b1cdbd2cSJim Jagielski 246*b1cdbd2cSJim Jagielski if ( $fileref->{'ismultilingual'} ) 247*b1cdbd2cSJim Jagielski { 248*b1cdbd2cSJim Jagielski my $officelanguage = $fileref->{'specificlanguage'}; 249*b1cdbd2cSJim Jagielski $componentname = $componentname . "_" . $officelanguage; 250*b1cdbd2cSJim Jagielski } 251*b1cdbd2cSJim Jagielski 252*b1cdbd2cSJim Jagielski $componentname = lc($componentname); # componentnames always lowercase 253*b1cdbd2cSJim Jagielski 254*b1cdbd2cSJim Jagielski $componentname =~ s/\-/\_/g; # converting "-" to "_" 255*b1cdbd2cSJim Jagielski $componentname =~ s/\./\_/g; # converting "-" to "_" 256*b1cdbd2cSJim Jagielski 257*b1cdbd2cSJim Jagielski # Attention: Maximum length for the componentname is 72 258*b1cdbd2cSJim Jagielski # %installer::globals::allcomponents_in_this_database : resetted for each database 259*b1cdbd2cSJim Jagielski # %installer::globals::allcomponents : not resetted for each database 260*b1cdbd2cSJim Jagielski # Component strings must be unique for the complete product, because they are used for 261*b1cdbd2cSJim Jagielski # the creation of the globally unique identifier. 262*b1cdbd2cSJim Jagielski 263*b1cdbd2cSJim Jagielski my $fullname = $componentname; # This can be longer than 72 264*b1cdbd2cSJim Jagielski 265*b1cdbd2cSJim Jagielski if (( exists($installer::globals::allcomponents{$fullname}) ) && ( ! exists($installer::globals::allcomponents_in_this_database{$fullname}) )) 266*b1cdbd2cSJim Jagielski { 267*b1cdbd2cSJim Jagielski # This is not allowed: One component cannot be installed with different packages. 268*b1cdbd2cSJim Jagielski installer::exiter::exit_program("ERROR: Component \"$fullname\" is already included into another package. This is not allowed.", "get_file_component_name"); 269*b1cdbd2cSJim Jagielski } 270*b1cdbd2cSJim Jagielski 271*b1cdbd2cSJim Jagielski if ( exists($installer::globals::allcomponents{$fullname}) ) 272*b1cdbd2cSJim Jagielski { 273*b1cdbd2cSJim Jagielski $componentname = $installer::globals::allcomponents{$fullname}; 274*b1cdbd2cSJim Jagielski } 275*b1cdbd2cSJim Jagielski else 276*b1cdbd2cSJim Jagielski { 277*b1cdbd2cSJim Jagielski if ( length($componentname) > 70 ) 278*b1cdbd2cSJim Jagielski { 279*b1cdbd2cSJim Jagielski $componentname = generate_new_short_componentname($componentname); # This has to be unique for the complete product, not only one package 280*b1cdbd2cSJim Jagielski } 281*b1cdbd2cSJim Jagielski 282*b1cdbd2cSJim Jagielski $installer::globals::allcomponents{$fullname} = $componentname; 283*b1cdbd2cSJim Jagielski $installer::globals::allcomponents_in_this_database{$fullname} = 1; 284*b1cdbd2cSJim Jagielski } 285*b1cdbd2cSJim Jagielski 286*b1cdbd2cSJim Jagielski # $componentname =~ s/gid_file_/g_f_/g; 287*b1cdbd2cSJim Jagielski # $componentname =~ s/_extra_/_e_/g; 288*b1cdbd2cSJim Jagielski # $componentname =~ s/_config_/_c_/g; 289*b1cdbd2cSJim Jagielski # $componentname =~ s/_org_openoffice_/_o_o_/g; 290*b1cdbd2cSJim Jagielski # $componentname =~ s/_program_/_p_/g; 291*b1cdbd2cSJim Jagielski # $componentname =~ s/_typedetection_/_td_/g; 292*b1cdbd2cSJim Jagielski # $componentname =~ s/_linguistic_/_l_/g; 293*b1cdbd2cSJim Jagielski # $componentname =~ s/_module_/_m_/g; 294*b1cdbd2cSJim Jagielski # $componentname =~ s/_optional_/_opt_/g; 295*b1cdbd2cSJim Jagielski # $componentname =~ s/_packages/_pack/g; 296*b1cdbd2cSJim Jagielski # $componentname =~ s/_menubar/_mb/g; 297*b1cdbd2cSJim Jagielski # $componentname =~ s/_common_/_cm_/g; 298*b1cdbd2cSJim Jagielski # $componentname =~ s/_export_/_exp_/g; 299*b1cdbd2cSJim Jagielski # $componentname =~ s/_table_/_tb_/g; 300*b1cdbd2cSJim Jagielski # $componentname =~ s/_sofficecfg_/_sc_/g; 301*b1cdbd2cSJim Jagielski # $componentname =~ s/_soffice_cfg_/_sc_/g; 302*b1cdbd2cSJim Jagielski # $componentname =~ s/_startmodulecommands_/_smc_/g; 303*b1cdbd2cSJim Jagielski # $componentname =~ s/_drawimpresscommands_/_dic_/g; 304*b1cdbd2cSJim Jagielski # $componentname =~ s/_basiccommands_/_bac_/g; 305*b1cdbd2cSJim Jagielski # $componentname =~ s/_basicidecommands_/_baic_/g; 306*b1cdbd2cSJim Jagielski # $componentname =~ s/_genericcommands_/_genc_/g; 307*b1cdbd2cSJim Jagielski # $componentname =~ s/_bibliographycommands_/_bibc_/g; 308*b1cdbd2cSJim Jagielski # $componentname =~ s/_gentiumbookbasicbolditalic_/_gbbbi_/g; 309*b1cdbd2cSJim Jagielski # $componentname =~ s/_share_/_s_/g; 310*b1cdbd2cSJim Jagielski # $componentname =~ s/_extension_/_ext_/g; 311*b1cdbd2cSJim Jagielski # $componentname =~ s/_extensions_/_exs_/g; 312*b1cdbd2cSJim Jagielski # $componentname =~ s/_modules_/_ms_/g; 313*b1cdbd2cSJim Jagielski # $componentname =~ s/_uiconfig_zip_/_ucz_/g; 314*b1cdbd2cSJim Jagielski # $componentname =~ s/_productivity_/_pr_/g; 315*b1cdbd2cSJim Jagielski # $componentname =~ s/_wizard_/_wz_/g; 316*b1cdbd2cSJim Jagielski # $componentname =~ s/_import_/_im_/g; 317*b1cdbd2cSJim Jagielski # $componentname =~ s/_javascript_/_js_/g; 318*b1cdbd2cSJim Jagielski # $componentname =~ s/_template_/_tpl_/g; 319*b1cdbd2cSJim Jagielski # $componentname =~ s/_tplwizletter_/_twl_/g; 320*b1cdbd2cSJim Jagielski # $componentname =~ s/_beanshell_/_bs_/g; 321*b1cdbd2cSJim Jagielski # $componentname =~ s/_presentation_/_bs_/g; 322*b1cdbd2cSJim Jagielski # $componentname =~ s/_columns_/_cls_/g; 323*b1cdbd2cSJim Jagielski # $componentname =~ s/_python_/_py_/g; 324*b1cdbd2cSJim Jagielski 325*b1cdbd2cSJim Jagielski # $componentname =~ s/_tools/_ts/g; 326*b1cdbd2cSJim Jagielski # $componentname =~ s/_transitions/_trs/g; 327*b1cdbd2cSJim Jagielski # $componentname =~ s/_scriptbinding/_scrb/g; 328*b1cdbd2cSJim Jagielski # $componentname =~ s/_spreadsheet/_ssh/g; 329*b1cdbd2cSJim Jagielski # $componentname =~ s/_publisher/_pub/g; 330*b1cdbd2cSJim Jagielski # $componentname =~ s/_presenter/_pre/g; 331*b1cdbd2cSJim Jagielski # $componentname =~ s/_registry/_reg/g; 332*b1cdbd2cSJim Jagielski 333*b1cdbd2cSJim Jagielski # $componentname =~ s/screen/sc/g; 334*b1cdbd2cSJim Jagielski # $componentname =~ s/wordml/wm/g; 335*b1cdbd2cSJim Jagielski # $componentname =~ s/openoffice/oo/g; 336*b1cdbd2cSJim Jagielski } 337*b1cdbd2cSJim Jagielski 338*b1cdbd2cSJim Jagielski return $componentname; 339*b1cdbd2cSJim Jagielski} 340*b1cdbd2cSJim Jagielski 341*b1cdbd2cSJim Jagielski#################################################################### 342*b1cdbd2cSJim Jagielski# Returning the component name for a defined file gid. 343*b1cdbd2cSJim Jagielski# This is necessary for files with flag ASSIGNCOMPOMENT 344*b1cdbd2cSJim Jagielski#################################################################### 345*b1cdbd2cSJim Jagielski 346*b1cdbd2cSJim Jagielskisub get_component_from_assigned_file 347*b1cdbd2cSJim Jagielski{ 348*b1cdbd2cSJim Jagielski my ($gid, $filesref) = @_; 349*b1cdbd2cSJim Jagielski 350*b1cdbd2cSJim Jagielski my $onefile = installer::existence::get_specified_file($filesref, $gid); 351*b1cdbd2cSJim Jagielski my $componentname = ""; 352*b1cdbd2cSJim Jagielski if ( $onefile->{'componentname'} ) { $componentname = $onefile->{'componentname'}; } 353*b1cdbd2cSJim Jagielski else { installer::exiter::exit_program("ERROR: No component defined for file: $gid", "get_component_from_assigned_file"); } 354*b1cdbd2cSJim Jagielski 355*b1cdbd2cSJim Jagielski return $componentname; 356*b1cdbd2cSJim Jagielski} 357*b1cdbd2cSJim Jagielski 358*b1cdbd2cSJim Jagielski#################################################################### 359*b1cdbd2cSJim Jagielski# Generating the special filename for the database file File.idt 360*b1cdbd2cSJim Jagielski# Sample: CONTEXTS, CONTEXTS1 361*b1cdbd2cSJim Jagielski# This name has to be unique. 362*b1cdbd2cSJim Jagielski# In most cases this is simply the filename. 363*b1cdbd2cSJim Jagielski#################################################################### 364*b1cdbd2cSJim Jagielski 365*b1cdbd2cSJim Jagielskisub generate_unique_filename_for_filetable ($) 366*b1cdbd2cSJim Jagielski{ 367*b1cdbd2cSJim Jagielski my ($oldname) = @_; 368*b1cdbd2cSJim Jagielski 369*b1cdbd2cSJim Jagielski # This new filename has to be saved into $fileref, because this is needed to find the source. 370*b1cdbd2cSJim Jagielski # The filename sbasic.idx/OFFSETS is changed to OFFSETS, but OFFSETS is not unique. 371*b1cdbd2cSJim Jagielski # In this procedure names like OFFSETS5 are produced. And exactly this string has to be added to 372*b1cdbd2cSJim Jagielski # the array of all files. 373*b1cdbd2cSJim Jagielski 374*b1cdbd2cSJim Jagielski my $uniquefilename = $oldname; 375*b1cdbd2cSJim Jagielski if ( ! defined $uniquefilename || $uniquefilename eq "") 376*b1cdbd2cSJim Jagielski { 377*b1cdbd2cSJim Jagielski installer::logger::PrintError("file name does not exist or is empty, can not create unique name for it."); 378*b1cdbd2cSJim Jagielski die; 379*b1cdbd2cSJim Jagielski return; 380*b1cdbd2cSJim Jagielski } 381*b1cdbd2cSJim Jagielski 382*b1cdbd2cSJim Jagielski # making /registry/schema/org/openoffice/VCL.xcs to VCL.xcs 383*b1cdbd2cSJim Jagielski installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$uniquefilename); 384*b1cdbd2cSJim Jagielski 385*b1cdbd2cSJim Jagielski $uniquefilename =~ s/\-/\_/g; # no "-" allowed 386*b1cdbd2cSJim Jagielski $uniquefilename =~ s/\@/\_/g; # no "@" allowed 387*b1cdbd2cSJim Jagielski $uniquefilename =~ s/\$/\_/g; # no "$" allowed 388*b1cdbd2cSJim Jagielski $uniquefilename =~ s/^\s*\./\_/g; # no "." at the beginning allowed allowed 389*b1cdbd2cSJim Jagielski $uniquefilename =~ s/^\s*\d/\_d/g; # no number at the beginning allowed allowed (even file "0.gif", replacing to "_d.gif") 390*b1cdbd2cSJim Jagielski $uniquefilename =~ s/org_openoffice_/ooo_/g; # shorten the unique file name 391*b1cdbd2cSJim Jagielski 392*b1cdbd2cSJim Jagielski my $lcuniquefilename = lc($uniquefilename); # only lowercase names 393*b1cdbd2cSJim Jagielski 394*b1cdbd2cSJim Jagielski my $newname = 0; 395*b1cdbd2cSJim Jagielski 396*b1cdbd2cSJim Jagielski if ( ! exists($installer::globals::alllcuniquefilenames{$lcuniquefilename})) 397*b1cdbd2cSJim Jagielski { 398*b1cdbd2cSJim Jagielski $installer::globals::alluniquefilenames{$uniquefilename} = 1; 399*b1cdbd2cSJim Jagielski $installer::globals::alllcuniquefilenames{$lcuniquefilename} = 1; 400*b1cdbd2cSJim Jagielski $newname = 1; 401*b1cdbd2cSJim Jagielski } 402*b1cdbd2cSJim Jagielski 403*b1cdbd2cSJim Jagielski if ( ! $newname ) 404*b1cdbd2cSJim Jagielski { 405*b1cdbd2cSJim Jagielski # adding a number until the name is really unique: OFFSETS, OFFSETS1, OFFSETS2, ... 406*b1cdbd2cSJim Jagielski # But attention: Making "abc.xcu" to "abc1.xcu" 407*b1cdbd2cSJim Jagielski 408*b1cdbd2cSJim Jagielski my $uniquefilenamebase = $uniquefilename; 409*b1cdbd2cSJim Jagielski 410*b1cdbd2cSJim Jagielski my $counter = 0; 411*b1cdbd2cSJim Jagielski do 412*b1cdbd2cSJim Jagielski { 413*b1cdbd2cSJim Jagielski $counter++; 414*b1cdbd2cSJim Jagielski 415*b1cdbd2cSJim Jagielski if ( $uniquefilenamebase =~ /\./ ) 416*b1cdbd2cSJim Jagielski { 417*b1cdbd2cSJim Jagielski $uniquefilename = $uniquefilenamebase; 418*b1cdbd2cSJim Jagielski $uniquefilename =~ s/\./$counter\./; 419*b1cdbd2cSJim Jagielski } 420*b1cdbd2cSJim Jagielski else 421*b1cdbd2cSJim Jagielski { 422*b1cdbd2cSJim Jagielski $uniquefilename = $uniquefilenamebase . $counter; 423*b1cdbd2cSJim Jagielski } 424*b1cdbd2cSJim Jagielski 425*b1cdbd2cSJim Jagielski $newname = 0; 426*b1cdbd2cSJim Jagielski $lcuniquefilename = lc($uniquefilename); # only lowercase names 427*b1cdbd2cSJim Jagielski 428*b1cdbd2cSJim Jagielski if ( ! exists($installer::globals::alllcuniquefilenames{$lcuniquefilename})) 429*b1cdbd2cSJim Jagielski { 430*b1cdbd2cSJim Jagielski $installer::globals::alluniquefilenames{$uniquefilename} = 1; 431*b1cdbd2cSJim Jagielski $installer::globals::alllcuniquefilenames{$lcuniquefilename} = 1; 432*b1cdbd2cSJim Jagielski $newname = 1; 433*b1cdbd2cSJim Jagielski } 434*b1cdbd2cSJim Jagielski } 435*b1cdbd2cSJim Jagielski until ( $newname ) 436*b1cdbd2cSJim Jagielski } 437*b1cdbd2cSJim Jagielski 438*b1cdbd2cSJim Jagielski return $uniquefilename; 439*b1cdbd2cSJim Jagielski} 440*b1cdbd2cSJim Jagielski 441*b1cdbd2cSJim Jagielski#################################################################### 442*b1cdbd2cSJim Jagielski# Generating the special file column for the database file File.idt 443*b1cdbd2cSJim Jagielski# Sample: NAMETR~1.TAB|.nametranslation.table 444*b1cdbd2cSJim Jagielski# The first part has to be 8.3 conform. 445*b1cdbd2cSJim Jagielski#################################################################### 446*b1cdbd2cSJim Jagielski 447*b1cdbd2cSJim Jagielskisub generate_filename_for_filetable ($$) 448*b1cdbd2cSJim Jagielski{ 449*b1cdbd2cSJim Jagielski my ($fileref, $shortnamesref) = @_; 450*b1cdbd2cSJim Jagielski 451*b1cdbd2cSJim Jagielski my $returnstring = ""; 452*b1cdbd2cSJim Jagielski 453*b1cdbd2cSJim Jagielski my $filename = $fileref->{'Name'}; 454*b1cdbd2cSJim Jagielski 455*b1cdbd2cSJim Jagielski # making /registry/schema/org/openoffice/VCL.xcs to VCL.xcs 456*b1cdbd2cSJim Jagielski installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$filename); 457*b1cdbd2cSJim Jagielski 458*b1cdbd2cSJim Jagielski my $shortstring = installer::windows::idtglobal::make_eight_three_conform_with_hash($filename, "file", $shortnamesref); 459*b1cdbd2cSJim Jagielski 460*b1cdbd2cSJim Jagielski if ( $shortstring eq $filename ) 461*b1cdbd2cSJim Jagielski { 462*b1cdbd2cSJim Jagielski # nothing changed 463*b1cdbd2cSJim Jagielski $returnstring = $filename; 464*b1cdbd2cSJim Jagielski } 465*b1cdbd2cSJim Jagielski else 466*b1cdbd2cSJim Jagielski { 467*b1cdbd2cSJim Jagielski $returnstring = $shortstring . "\|" . $filename; 468*b1cdbd2cSJim Jagielski } 469*b1cdbd2cSJim Jagielski 470*b1cdbd2cSJim Jagielski return $returnstring; 471*b1cdbd2cSJim Jagielski} 472*b1cdbd2cSJim Jagielski 473*b1cdbd2cSJim Jagielski######################################### 474*b1cdbd2cSJim Jagielski# Returning the filesize of a file 475*b1cdbd2cSJim Jagielski######################################### 476*b1cdbd2cSJim Jagielski 477*b1cdbd2cSJim Jagielskisub get_filesize 478*b1cdbd2cSJim Jagielski{ 479*b1cdbd2cSJim Jagielski my ($fileref) = @_; 480*b1cdbd2cSJim Jagielski 481*b1cdbd2cSJim Jagielski my $file = $fileref->{'sourcepath'}; 482*b1cdbd2cSJim Jagielski 483*b1cdbd2cSJim Jagielski my $filesize; 484*b1cdbd2cSJim Jagielski 485*b1cdbd2cSJim Jagielski if ( -f $file ) # test of existence. For instance services.rdb does not always exist 486*b1cdbd2cSJim Jagielski { 487*b1cdbd2cSJim Jagielski $filesize = ( -s $file ); # file size can be "0" 488*b1cdbd2cSJim Jagielski } 489*b1cdbd2cSJim Jagielski else 490*b1cdbd2cSJim Jagielski { 491*b1cdbd2cSJim Jagielski $filesize = -1; 492*b1cdbd2cSJim Jagielski } 493*b1cdbd2cSJim Jagielski 494*b1cdbd2cSJim Jagielski return $filesize; 495*b1cdbd2cSJim Jagielski} 496*b1cdbd2cSJim Jagielski 497*b1cdbd2cSJim Jagielski############################################# 498*b1cdbd2cSJim Jagielski# Returning the file version, if required 499*b1cdbd2cSJim Jagielski# Sample: "8.0.1.8976"; 500*b1cdbd2cSJim Jagielski############################################# 501*b1cdbd2cSJim Jagielski 502*b1cdbd2cSJim Jagielskisub get_fileversion 503*b1cdbd2cSJim Jagielski{ 504*b1cdbd2cSJim Jagielski my ($onefile, $allvariables) = @_; 505*b1cdbd2cSJim Jagielski 506*b1cdbd2cSJim Jagielski my $fileversion = ""; 507*b1cdbd2cSJim Jagielski 508*b1cdbd2cSJim Jagielski if ( $allvariables->{'USE_FILEVERSION'} ) 509*b1cdbd2cSJim Jagielski { 510*b1cdbd2cSJim Jagielski if ( ! $allvariables->{'LIBRARYVERSION'} ) 511*b1cdbd2cSJim Jagielski { 512*b1cdbd2cSJim Jagielski installer::exiter::exit_program("ERROR: USE_FILEVERSION is set, but not LIBRARYVERSION", "get_fileversion"); 513*b1cdbd2cSJim Jagielski } 514*b1cdbd2cSJim Jagielski my $libraryversion = $allvariables->{'LIBRARYVERSION'}; 515*b1cdbd2cSJim Jagielski if ( $libraryversion =~ /^\s*(\d+)\.(\d+)\.(\d+)\s*$/ ) 516*b1cdbd2cSJim Jagielski { 517*b1cdbd2cSJim Jagielski my $major = $1; 518*b1cdbd2cSJim Jagielski my $minor = $2; 519*b1cdbd2cSJim Jagielski my $micro = $3; 520*b1cdbd2cSJim Jagielski my $concat = 100 * $minor + $micro; 521*b1cdbd2cSJim Jagielski $libraryversion = $major . "\." . $concat; 522*b1cdbd2cSJim Jagielski } 523*b1cdbd2cSJim Jagielski my $vendornumber = 0; 524*b1cdbd2cSJim Jagielski if ( $allvariables->{'VENDORPATCHVERSION'} ) 525*b1cdbd2cSJim Jagielski { 526*b1cdbd2cSJim Jagielski $vendornumber = $allvariables->{'VENDORPATCHVERSION'}; 527*b1cdbd2cSJim Jagielski } 528*b1cdbd2cSJim Jagielski $fileversion = $libraryversion . "\." . $installer::globals::buildid . "\." . $vendornumber; 529*b1cdbd2cSJim Jagielski if ( $onefile->{'FileVersion'} ) 530*b1cdbd2cSJim Jagielski { 531*b1cdbd2cSJim Jagielski # overriding FileVersion in scp 532*b1cdbd2cSJim Jagielski $fileversion = $onefile->{'FileVersion'}; 533*b1cdbd2cSJim Jagielski } 534*b1cdbd2cSJim Jagielski } 535*b1cdbd2cSJim Jagielski 536*b1cdbd2cSJim Jagielski if ( $installer::globals::prepare_winpatch ) 537*b1cdbd2cSJim Jagielski { 538*b1cdbd2cSJim Jagielski # Windows patches do not allow this version # -> who says so? 539*b1cdbd2cSJim Jagielski $fileversion = ""; 540*b1cdbd2cSJim Jagielski } 541*b1cdbd2cSJim Jagielski 542*b1cdbd2cSJim Jagielski return $fileversion; 543*b1cdbd2cSJim Jagielski} 544*b1cdbd2cSJim Jagielski 545*b1cdbd2cSJim Jagielski 546*b1cdbd2cSJim Jagielski 547*b1cdbd2cSJim Jagielski 548*b1cdbd2cSJim Jagielskisub retrieve_sequence_and_uniquename ($$) 549*b1cdbd2cSJim Jagielski{ 550*b1cdbd2cSJim Jagielski my ($file_list, $source_data) = @_; 551*b1cdbd2cSJim Jagielski 552*b1cdbd2cSJim Jagielski my @added_files = (); 553*b1cdbd2cSJim Jagielski 554*b1cdbd2cSJim Jagielski # Read the sequence numbers of the previous version. 555*b1cdbd2cSJim Jagielski if ($installer::globals::is_release) 556*b1cdbd2cSJim Jagielski { 557*b1cdbd2cSJim Jagielski foreach my $file (@$file_list) 558*b1cdbd2cSJim Jagielski { 559*b1cdbd2cSJim Jagielski # Use the source path of the file as key to retrieve sequence number and unique name. 560*b1cdbd2cSJim Jagielski # The source path is the part of the 'destination' without the first part. 561*b1cdbd2cSJim Jagielski # There is a special case when 'Dir' is PREDEFINED_OSSHELLNEWDIR. 562*b1cdbd2cSJim Jagielski my $source_path; 563*b1cdbd2cSJim Jagielski if (defined $file->{'Dir'} && $file->{'Dir'} eq "PREDEFINED_OSSHELLNEWDIR") 564*b1cdbd2cSJim Jagielski { 565*b1cdbd2cSJim Jagielski $source_path = $installer::globals::templatefoldername 566*b1cdbd2cSJim Jagielski . $installer::globals::separator 567*b1cdbd2cSJim Jagielski . $file->{'Name'}; 568*b1cdbd2cSJim Jagielski } 569*b1cdbd2cSJim Jagielski else 570*b1cdbd2cSJim Jagielski { 571*b1cdbd2cSJim Jagielski $source_path = $file->{'destination'}; 572*b1cdbd2cSJim Jagielski $source_path =~ s/^[^\/]+\///; 573*b1cdbd2cSJim Jagielski } 574*b1cdbd2cSJim Jagielski my ($sequence, $uniquename) = $source_data->get_sequence_and_unique_name($source_path); 575*b1cdbd2cSJim Jagielski if (defined $sequence && defined $uniquename) 576*b1cdbd2cSJim Jagielski { 577*b1cdbd2cSJim Jagielski $file->{'sequencenumber'} = $sequence; 578*b1cdbd2cSJim Jagielski $file->{'uniquename'} = $uniquename; 579*b1cdbd2cSJim Jagielski } 580*b1cdbd2cSJim Jagielski else 581*b1cdbd2cSJim Jagielski { 582*b1cdbd2cSJim Jagielski # No data found in the source release. File has been added. 583*b1cdbd2cSJim Jagielski push @added_files, $file; 584*b1cdbd2cSJim Jagielski } 585*b1cdbd2cSJim Jagielski } 586*b1cdbd2cSJim Jagielski } 587*b1cdbd2cSJim Jagielski 588*b1cdbd2cSJim Jagielski return @added_files; 589*b1cdbd2cSJim Jagielski} 590*b1cdbd2cSJim Jagielski 591*b1cdbd2cSJim Jagielski 592*b1cdbd2cSJim Jagielski 593*b1cdbd2cSJim Jagielski 594*b1cdbd2cSJim Jagielski=head2 assign_mssing_sequence_numbers ($file_list) 595*b1cdbd2cSJim Jagielski 596*b1cdbd2cSJim Jagielski Assign sequence numbers where still missing. 597*b1cdbd2cSJim Jagielski 598*b1cdbd2cSJim Jagielski When we are preparing a patch then all files that have no sequence numbers 599*b1cdbd2cSJim Jagielski at this point are new. Otherwise no file has a sequence number yet. 600*b1cdbd2cSJim Jagielski 601*b1cdbd2cSJim Jagielski=cut 602*b1cdbd2cSJim Jagielskisub assign_missing_sequence_numbers ($) 603*b1cdbd2cSJim Jagielski{ 604*b1cdbd2cSJim Jagielski my ($file_list) = @_; 605*b1cdbd2cSJim Jagielski 606*b1cdbd2cSJim Jagielski # First, set up a hash on the sequence numbers that are already in use. 607*b1cdbd2cSJim Jagielski my %used_sequence_numbers = (); 608*b1cdbd2cSJim Jagielski foreach my $file (@$file_list) 609*b1cdbd2cSJim Jagielski { 610*b1cdbd2cSJim Jagielski next unless defined $file->{'sequencenumber'}; 611*b1cdbd2cSJim Jagielski $used_sequence_numbers{$file->{'sequencenumber'}} = 1; 612*b1cdbd2cSJim Jagielski } 613*b1cdbd2cSJim Jagielski 614*b1cdbd2cSJim Jagielski # Assign sequence numbers. Try consecutive numbers, starting at 1. 615*b1cdbd2cSJim Jagielski my $current_sequence_number = 1; 616*b1cdbd2cSJim Jagielski foreach my $file (@$file_list) 617*b1cdbd2cSJim Jagielski { 618*b1cdbd2cSJim Jagielski # Skip over all files that already have sequence numbers. 619*b1cdbd2cSJim Jagielski next if defined $file->{'sequencenumber'}; 620*b1cdbd2cSJim Jagielski 621*b1cdbd2cSJim Jagielski # Find the next available number. 622*b1cdbd2cSJim Jagielski while (defined $used_sequence_numbers{$current_sequence_number}) 623*b1cdbd2cSJim Jagielski { 624*b1cdbd2cSJim Jagielski ++$current_sequence_number; 625*b1cdbd2cSJim Jagielski } 626*b1cdbd2cSJim Jagielski 627*b1cdbd2cSJim Jagielski # Use the number and mark it as used. 628*b1cdbd2cSJim Jagielski $file->{'sequencenumber'} = $current_sequence_number; 629*b1cdbd2cSJim Jagielski $used_sequence_numbers{$current_sequence_number} = 1; 630*b1cdbd2cSJim Jagielski } 631*b1cdbd2cSJim Jagielski} 632*b1cdbd2cSJim Jagielski 633*b1cdbd2cSJim Jagielski 634*b1cdbd2cSJim Jagielski 635*b1cdbd2cSJim Jagielski 636*b1cdbd2cSJim Jagielskisub create_items_for_missing_files ($$$) 637*b1cdbd2cSJim Jagielski{ 638*b1cdbd2cSJim Jagielski my ($missing_items, $source_msi, $directory_list) = @_; 639*b1cdbd2cSJim Jagielski 640*b1cdbd2cSJim Jagielski # For creation of the FeatureComponent table (in a later step) we 641*b1cdbd2cSJim Jagielski # have to provide references from the file to component and 642*b1cdbd2cSJim Jagielski # modules (ie features). Note that Each file belongs to exactly 643*b1cdbd2cSJim Jagielski # one component but one component can belong to multiple features. 644*b1cdbd2cSJim Jagielski my $component_to_features_map = create_feature_component_map($source_msi); 645*b1cdbd2cSJim Jagielski 646*b1cdbd2cSJim Jagielski my @new_files = (); 647*b1cdbd2cSJim Jagielski foreach my $row (@$missing_items) 648*b1cdbd2cSJim Jagielski { 649*b1cdbd2cSJim Jagielski $installer::logger::Info->printf("creating new file item for '%s'\n", $row->GetValue('File')); 650*b1cdbd2cSJim Jagielski my $file_item = create_script_item_for_deleted_file($row, $source_msi, $component_to_features_map); 651*b1cdbd2cSJim Jagielski push @new_files, $file_item; 652*b1cdbd2cSJim Jagielski } 653*b1cdbd2cSJim Jagielski 654*b1cdbd2cSJim Jagielski return @new_files; 655*b1cdbd2cSJim Jagielski} 656*b1cdbd2cSJim Jagielski 657*b1cdbd2cSJim Jagielski 658*b1cdbd2cSJim Jagielski 659*b1cdbd2cSJim Jagielski 660*b1cdbd2cSJim Jagielski=head2 create_script_item_for_deleted_file (($file_row, $source_msi, $component_to_features_map) 661*b1cdbd2cSJim Jagielski 662*b1cdbd2cSJim Jagielski Create a new script item for a file that was present in the 663*b1cdbd2cSJim Jagielski previous release but isn't anymore. Most of the necessary 664*b1cdbd2cSJim Jagielski information is taken from the 'File' table of the source release. 665*b1cdbd2cSJim Jagielski 666*b1cdbd2cSJim Jagielski The values of 'sourcepath' and 'cyg_sourcepath' will point to the 667*b1cdbd2cSJim Jagielski respective file in the unpacked source release. An alternative 668*b1cdbd2cSJim Jagielski would be to let them point to an empty file. That, however, might 669*b1cdbd2cSJim Jagielski make the patch bigger (diff between identical file contents is 670*b1cdbd2cSJim Jagielski (almost) empty, diff between file and empty file is the 'inverse' 671*b1cdbd2cSJim Jagielski of the file). 672*b1cdbd2cSJim Jagielski 673*b1cdbd2cSJim Jagielski=cut 674*b1cdbd2cSJim Jagielski 675*b1cdbd2cSJim Jagielskimy $use_source_files_for_missing_files = 1; 676*b1cdbd2cSJim Jagielski 677*b1cdbd2cSJim Jagielskisub create_script_item_for_deleted_file ($$$) 678*b1cdbd2cSJim Jagielski{ 679*b1cdbd2cSJim Jagielski my ($file_row, $source_msi, $component_to_features_map) = @_; 680*b1cdbd2cSJim Jagielski 681*b1cdbd2cSJim Jagielski my $uniquename = $file_row->GetValue('File'); 682*b1cdbd2cSJim Jagielski 683*b1cdbd2cSJim Jagielski my $file_map = $source_msi->GetFileMap(); 684*b1cdbd2cSJim Jagielski 685*b1cdbd2cSJim Jagielski my $file_item = $file_map->{$uniquename}; 686*b1cdbd2cSJim Jagielski my $directory_item = $file_item->{'directory'}; 687*b1cdbd2cSJim Jagielski my $source_path = $directory_item->{'full_source_long_name'}; 688*b1cdbd2cSJim Jagielski my $target_path = $directory_item->{'full_target_long_name'}; 689*b1cdbd2cSJim Jagielski my $full_source_name = undef; 690*b1cdbd2cSJim Jagielski if ($use_source_files_for_missing_files) 691*b1cdbd2cSJim Jagielski { 692*b1cdbd2cSJim Jagielski $full_source_name = File::Spec->catfile( 693*b1cdbd2cSJim Jagielski installer::patch::InstallationSet::GetUnpackedCabPath( 694*b1cdbd2cSJim Jagielski $source_msi->{'version'}, 695*b1cdbd2cSJim Jagielski $source_msi->{'is_current_version'}, 696*b1cdbd2cSJim Jagielski $source_msi->{'language'}, 697*b1cdbd2cSJim Jagielski $source_msi->{'package_format'}, 698*b1cdbd2cSJim Jagielski $source_msi->{'product_name'}), 699*b1cdbd2cSJim Jagielski $source_path, 700*b1cdbd2cSJim Jagielski $file_item->{'long_name'}); 701*b1cdbd2cSJim Jagielski } 702*b1cdbd2cSJim Jagielski else 703*b1cdbd2cSJim Jagielski { 704*b1cdbd2cSJim Jagielski $full_source_name = "/c/tmp/missing/".$uniquename; 705*b1cdbd2cSJim Jagielski installer::patch::Tools::touch($full_source_name); 706*b1cdbd2cSJim Jagielski } 707*b1cdbd2cSJim Jagielski my ($long_name, undef) = installer::patch::Msi::SplitLongShortName($file_row->GetValue("FileName")); 708*b1cdbd2cSJim Jagielski my $target_name = File::Spec->catfile($target_path, $long_name); 709*b1cdbd2cSJim Jagielski if ( ! -f $full_source_name) 710*b1cdbd2cSJim Jagielski { 711*b1cdbd2cSJim Jagielski installer::logger::PrintError("can not find file '%s' in previous version (tried '%s')\n", 712*b1cdbd2cSJim Jagielski $uniquename, 713*b1cdbd2cSJim Jagielski $full_source_name); 714*b1cdbd2cSJim Jagielski return undef; 715*b1cdbd2cSJim Jagielski } 716*b1cdbd2cSJim Jagielski my $cygwin_full_source_name = qx(cygpath -w '$full_source_name'); 717*b1cdbd2cSJim Jagielski my $component_name = $file_row->GetValue('Component_'); 718*b1cdbd2cSJim Jagielski my $module_names = join(",", @{$component_to_features_map->{$component_name}}); 719*b1cdbd2cSJim Jagielski my $sequence_number = $file_row->GetValue('Sequence'); 720*b1cdbd2cSJim Jagielski 721*b1cdbd2cSJim Jagielski return { 722*b1cdbd2cSJim Jagielski 'uniquename' => $uniquename, 723*b1cdbd2cSJim Jagielski 'destination' => $target_name, 724*b1cdbd2cSJim Jagielski 'componentname' => $component_name, 725*b1cdbd2cSJim Jagielski 'modules' => $module_names, 726*b1cdbd2cSJim Jagielski 'UnixRights' => 444, 727*b1cdbd2cSJim Jagielski 'Name' => $long_name, 728*b1cdbd2cSJim Jagielski 'sourcepath' => $full_source_name, 729*b1cdbd2cSJim Jagielski 'cyg_sourcepath' => $cygwin_full_source_name, 730*b1cdbd2cSJim Jagielski 'sequencenumber' => $sequence_number 731*b1cdbd2cSJim Jagielski }; 732*b1cdbd2cSJim Jagielski} 733*b1cdbd2cSJim Jagielski 734*b1cdbd2cSJim Jagielski 735*b1cdbd2cSJim Jagielski 736*b1cdbd2cSJim Jagielski 737*b1cdbd2cSJim Jagielski=head2 create_feature_component_maps($msi) 738*b1cdbd2cSJim Jagielski 739*b1cdbd2cSJim Jagielski Return a hash map that maps from component names to arrays of 740*b1cdbd2cSJim Jagielski feature names. In most cases the array of features contains only 741*b1cdbd2cSJim Jagielski one element. But there can be cases where the number is greater. 742*b1cdbd2cSJim Jagielski 743*b1cdbd2cSJim Jagielski=cut 744*b1cdbd2cSJim Jagielskisub create_feature_component_map ($) 745*b1cdbd2cSJim Jagielski{ 746*b1cdbd2cSJim Jagielski my ($msi) = @_; 747*b1cdbd2cSJim Jagielski 748*b1cdbd2cSJim Jagielski my $component_to_features_map = {}; 749*b1cdbd2cSJim Jagielski my $feature_component_table = $msi->GetTable("FeatureComponents"); 750*b1cdbd2cSJim Jagielski my $feature_column_index = $feature_component_table->GetColumnIndex("Feature_"); 751*b1cdbd2cSJim Jagielski my $component_column_index = $feature_component_table->GetColumnIndex("Component_"); 752*b1cdbd2cSJim Jagielski foreach my $row (@{$feature_component_table->GetAllRows()}) 753*b1cdbd2cSJim Jagielski { 754*b1cdbd2cSJim Jagielski my $feature = $row->GetValue($feature_column_index); 755*b1cdbd2cSJim Jagielski my $component = $row->GetValue($component_column_index); 756*b1cdbd2cSJim Jagielski if ( ! defined $component_to_features_map->{$component}) 757*b1cdbd2cSJim Jagielski { 758*b1cdbd2cSJim Jagielski $component_to_features_map->{$component} = [$feature]; 759*b1cdbd2cSJim Jagielski } 760*b1cdbd2cSJim Jagielski else 761*b1cdbd2cSJim Jagielski { 762*b1cdbd2cSJim Jagielski push @{$component_to_features_map->{$component}}, $feature; 763*b1cdbd2cSJim Jagielski } 764*b1cdbd2cSJim Jagielski } 765*b1cdbd2cSJim Jagielski 766*b1cdbd2cSJim Jagielski return $component_to_features_map; 767*b1cdbd2cSJim Jagielski} 768*b1cdbd2cSJim Jagielski 769*b1cdbd2cSJim Jagielski 770*b1cdbd2cSJim Jagielski############################################# 771*b1cdbd2cSJim Jagielski# Returning the Windows language of a file 772*b1cdbd2cSJim Jagielski############################################# 773*b1cdbd2cSJim Jagielski 774*b1cdbd2cSJim Jagielskisub get_language_for_file 775*b1cdbd2cSJim Jagielski{ 776*b1cdbd2cSJim Jagielski my ($fileref) = @_; 777*b1cdbd2cSJim Jagielski 778*b1cdbd2cSJim Jagielski my $language = ""; 779*b1cdbd2cSJim Jagielski 780*b1cdbd2cSJim Jagielski if ( $fileref->{'specificlanguage'} ) { $language = $fileref->{'specificlanguage'}; } 781*b1cdbd2cSJim Jagielski 782*b1cdbd2cSJim Jagielski if ( $language eq "" ) 783*b1cdbd2cSJim Jagielski { 784*b1cdbd2cSJim Jagielski $language = 0; # language independent 785*b1cdbd2cSJim Jagielski # If this is not a font, the return value should be "0" (Check ICE 60) 786*b1cdbd2cSJim Jagielski my $styles = ""; 787*b1cdbd2cSJim Jagielski if ( $fileref->{'Styles'} ) { $styles = $fileref->{'Styles'}; } 788*b1cdbd2cSJim Jagielski if ( $styles =~ /\bFONT\b/ ) { $language = ""; } 789*b1cdbd2cSJim Jagielski } 790*b1cdbd2cSJim Jagielski else 791*b1cdbd2cSJim Jagielski { 792*b1cdbd2cSJim Jagielski $language = installer::windows::language::get_windows_language($language); 793*b1cdbd2cSJim Jagielski } 794*b1cdbd2cSJim Jagielski 795*b1cdbd2cSJim Jagielski return $language; 796*b1cdbd2cSJim Jagielski} 797*b1cdbd2cSJim Jagielski 798*b1cdbd2cSJim Jagielski#################################################################### 799*b1cdbd2cSJim Jagielski# Creating a new KeyPath for components in TemplatesFolder. 800*b1cdbd2cSJim Jagielski#################################################################### 801*b1cdbd2cSJim Jagielski 802*b1cdbd2cSJim Jagielskisub generate_registry_keypath 803*b1cdbd2cSJim Jagielski{ 804*b1cdbd2cSJim Jagielski my ($onefile) = @_; 805*b1cdbd2cSJim Jagielski 806*b1cdbd2cSJim Jagielski my $keypath = $onefile->{'Name'}; 807*b1cdbd2cSJim Jagielski $keypath =~ s/\.//g; 808*b1cdbd2cSJim Jagielski $keypath = lc($keypath); 809*b1cdbd2cSJim Jagielski $keypath = "userreg_" . $keypath; 810*b1cdbd2cSJim Jagielski 811*b1cdbd2cSJim Jagielski return $keypath; 812*b1cdbd2cSJim Jagielski} 813*b1cdbd2cSJim Jagielski 814*b1cdbd2cSJim Jagielski 815*b1cdbd2cSJim Jagielski################################################################### 816*b1cdbd2cSJim Jagielski# Collecting further conditions for the component table. 817*b1cdbd2cSJim Jagielski# This is used by multilayer products, to enable installation 818*b1cdbd2cSJim Jagielski# of separate layers. 819*b1cdbd2cSJim Jagielski################################################################### 820*b1cdbd2cSJim Jagielski 821*b1cdbd2cSJim Jagielskisub get_tree_condition_for_component 822*b1cdbd2cSJim Jagielski{ 823*b1cdbd2cSJim Jagielski my ($onefile, $componentname) = @_; 824*b1cdbd2cSJim Jagielski 825*b1cdbd2cSJim Jagielski if ( $onefile->{'destination'} ) 826*b1cdbd2cSJim Jagielski { 827*b1cdbd2cSJim Jagielski my $dest = $onefile->{'destination'}; 828*b1cdbd2cSJim Jagielski 829*b1cdbd2cSJim Jagielski # Comparing the destination path with 830*b1cdbd2cSJim Jagielski # $installer::globals::hostnametreestyles{$hostname} = $treestyle; 831*b1cdbd2cSJim Jagielski # (-> hostname is the key, the style the value!) 832*b1cdbd2cSJim Jagielski 833*b1cdbd2cSJim Jagielski foreach my $hostname ( keys %installer::globals::hostnametreestyles ) 834*b1cdbd2cSJim Jagielski { 835*b1cdbd2cSJim Jagielski if (( $dest eq $hostname ) || ( $dest =~ /^\s*\Q$hostname\E\\/ )) 836*b1cdbd2cSJim Jagielski { 837*b1cdbd2cSJim Jagielski # the value is the style 838*b1cdbd2cSJim Jagielski my $style = $installer::globals::hostnametreestyles{$hostname}; 839*b1cdbd2cSJim Jagielski # the condition is saved in %installer::globals::treestyles 840*b1cdbd2cSJim Jagielski my $condition = $installer::globals::treestyles{$style}; 841*b1cdbd2cSJim Jagielski # Saving condition to be added in table Property 842*b1cdbd2cSJim Jagielski $installer::globals::usedtreeconditions{$condition} = 1; 843*b1cdbd2cSJim Jagielski $condition = $condition . "=1"; 844*b1cdbd2cSJim Jagielski # saving this condition 845*b1cdbd2cSJim Jagielski $installer::globals::treeconditions{$componentname} = $condition; 846*b1cdbd2cSJim Jagielski 847*b1cdbd2cSJim Jagielski # saving also at the file, for usage in fileinfo 848*b1cdbd2cSJim Jagielski $onefile->{'layer'} = $installer::globals::treelayername{$style}; 849*b1cdbd2cSJim Jagielski } 850*b1cdbd2cSJim Jagielski } 851*b1cdbd2cSJim Jagielski } 852*b1cdbd2cSJim Jagielski} 853*b1cdbd2cSJim Jagielski 854*b1cdbd2cSJim Jagielski############################################ 855*b1cdbd2cSJim Jagielski# Collecting all short names, that are 856*b1cdbd2cSJim Jagielski# already used by the old database 857*b1cdbd2cSJim Jagielski############################################ 858*b1cdbd2cSJim Jagielski 859*b1cdbd2cSJim Jagielskisub collect_shortnames_from_old_database 860*b1cdbd2cSJim Jagielski{ 861*b1cdbd2cSJim Jagielski my ($uniquefilenamehashref, $shortnameshashref) = @_; 862*b1cdbd2cSJim Jagielski 863*b1cdbd2cSJim Jagielski foreach my $key ( keys %{$uniquefilenamehashref} ) 864*b1cdbd2cSJim Jagielski { 865*b1cdbd2cSJim Jagielski my $value = $uniquefilenamehashref->{$key}; # syntax of $value: ($uniquename;$shortname) 866*b1cdbd2cSJim Jagielski 867*b1cdbd2cSJim Jagielski if ( $value =~ /^\s*(.*?)\;\s*(.*?)\s*$/ ) 868*b1cdbd2cSJim Jagielski { 869*b1cdbd2cSJim Jagielski my $shortstring = $2; 870*b1cdbd2cSJim Jagielski $shortnameshashref->{$shortstring} = 1; # adding the shortname to the array of all shortnames 871*b1cdbd2cSJim Jagielski } 872*b1cdbd2cSJim Jagielski } 873*b1cdbd2cSJim Jagielski} 874*b1cdbd2cSJim Jagielski 875*b1cdbd2cSJim Jagielski 876*b1cdbd2cSJim Jagielskisub process_language_conditions ($) 877*b1cdbd2cSJim Jagielski{ 878*b1cdbd2cSJim Jagielski my ($onefile) = @_; 879*b1cdbd2cSJim Jagielski 880*b1cdbd2cSJim Jagielski # Collecting all languages specific conditions 881*b1cdbd2cSJim Jagielski if ( $onefile->{'ismultilingual'} ) 882*b1cdbd2cSJim Jagielski { 883*b1cdbd2cSJim Jagielski if ( $onefile->{'ComponentCondition'} ) 884*b1cdbd2cSJim Jagielski { 885*b1cdbd2cSJim Jagielski installer::exiter::exit_program( 886*b1cdbd2cSJim Jagielski "ERROR: Cannot set language condition. There is already another component condition for file $onefile->{'gid'}: \"$onefile->{'ComponentCondition'}\" !", "create_files_table"); 887*b1cdbd2cSJim Jagielski } 888*b1cdbd2cSJim Jagielski 889*b1cdbd2cSJim Jagielski if ( $onefile->{'specificlanguage'} eq "" ) 890*b1cdbd2cSJim Jagielski { 891*b1cdbd2cSJim Jagielski installer::exiter::exit_program( 892*b1cdbd2cSJim Jagielski "ERROR: There is no specific language for file at language module: $onefile->{'gid'} !", "create_files_table"); 893*b1cdbd2cSJim Jagielski } 894*b1cdbd2cSJim Jagielski my $locallanguage = $onefile->{'specificlanguage'}; 895*b1cdbd2cSJim Jagielski my $property = "IS" . $onefile->{'windows_language'}; 896*b1cdbd2cSJim Jagielski my $value = 1; 897*b1cdbd2cSJim Jagielski my $condition = $property . "=" . $value; 898*b1cdbd2cSJim Jagielski 899*b1cdbd2cSJim Jagielski $onefile->{'ComponentCondition'} = $condition; 900*b1cdbd2cSJim Jagielski 901*b1cdbd2cSJim Jagielski if ( exists($installer::globals::componentcondition{$onefile->{'componentname'}})) 902*b1cdbd2cSJim Jagielski { 903*b1cdbd2cSJim Jagielski if ( $installer::globals::componentcondition{$onefile->{'componentname'}} ne $condition ) 904*b1cdbd2cSJim Jagielski { 905*b1cdbd2cSJim Jagielski installer::exiter::exit_program( 906*b1cdbd2cSJim Jagielski sprintf( 907*b1cdbd2cSJim Jagielski "ERROR: There is already another component condition for file %s: \"%s\" and \"%s\" !", 908*b1cdbd2cSJim Jagielski $onefile->{'gid'}, 909*b1cdbd2cSJim Jagielski $installer::globals::componentcondition{$onefile->{'componentname'}}, 910*b1cdbd2cSJim Jagielski $condition), 911*b1cdbd2cSJim Jagielski "create_files_table"); 912*b1cdbd2cSJim Jagielski } 913*b1cdbd2cSJim Jagielski } 914*b1cdbd2cSJim Jagielski else 915*b1cdbd2cSJim Jagielski { 916*b1cdbd2cSJim Jagielski $installer::globals::componentcondition{$onefile->{'componentname'}} = $condition; 917*b1cdbd2cSJim Jagielski } 918*b1cdbd2cSJim Jagielski 919*b1cdbd2cSJim Jagielski # collecting all properties for table Property 920*b1cdbd2cSJim Jagielski if ( ! exists($installer::globals::languageproperties{$property}) ) 921*b1cdbd2cSJim Jagielski { 922*b1cdbd2cSJim Jagielski $installer::globals::languageproperties{$property} = $value; 923*b1cdbd2cSJim Jagielski } 924*b1cdbd2cSJim Jagielski } 925*b1cdbd2cSJim Jagielski} 926*b1cdbd2cSJim Jagielski 927*b1cdbd2cSJim Jagielski 928*b1cdbd2cSJim Jagielski 929*b1cdbd2cSJim Jagielski 930*b1cdbd2cSJim Jagielskisub has_style ($$) 931*b1cdbd2cSJim Jagielski{ 932*b1cdbd2cSJim Jagielski my ($style_list_string, $style_name) = @_; 933*b1cdbd2cSJim Jagielski 934*b1cdbd2cSJim Jagielski return 0 unless defined $style_list_string; 935*b1cdbd2cSJim Jagielski return $style_list_string =~ /\b$style_name\b/ ? 1 : 0; 936*b1cdbd2cSJim Jagielski} 937*b1cdbd2cSJim Jagielski 938*b1cdbd2cSJim Jagielski 939*b1cdbd2cSJim Jagielski 940*b1cdbd2cSJim Jagielski 941*b1cdbd2cSJim Jagielskisub prepare_file_table_creation ($$$) 942*b1cdbd2cSJim Jagielski{ 943*b1cdbd2cSJim Jagielski my ($file_list, $directory_list, $allvariables) = @_; 944*b1cdbd2cSJim Jagielski 945*b1cdbd2cSJim Jagielski if ( $^O =~ /cygwin/i ) 946*b1cdbd2cSJim Jagielski { 947*b1cdbd2cSJim Jagielski installer::worker::generate_cygwin_pathes($file_list); 948*b1cdbd2cSJim Jagielski } 949*b1cdbd2cSJim Jagielski 950*b1cdbd2cSJim Jagielski # Reset the fields 'sequencenumber' and 'uniquename'. They should not yet exist but better be sure. 951*b1cdbd2cSJim Jagielski foreach my $file (@$file_list) 952*b1cdbd2cSJim Jagielski { 953*b1cdbd2cSJim Jagielski delete $file->{'sequencenumber'}; 954*b1cdbd2cSJim Jagielski delete $file->{'uniquename'}; 955*b1cdbd2cSJim Jagielski } 956*b1cdbd2cSJim Jagielski 957*b1cdbd2cSJim Jagielski # Create FileSequenceList object for the old sequence data. 958*b1cdbd2cSJim Jagielski if (defined $installer::globals::source_msi) 959*b1cdbd2cSJim Jagielski { 960*b1cdbd2cSJim Jagielski my $previous_sequence_data = new installer::patch::FileSequenceList(); 961*b1cdbd2cSJim Jagielski $previous_sequence_data->SetFromMsi($installer::globals::source_msi); 962*b1cdbd2cSJim Jagielski my @added_files = retrieve_sequence_and_uniquename($file_list, $previous_sequence_data); 963*b1cdbd2cSJim Jagielski 964*b1cdbd2cSJim Jagielski # Extract just the unique names. 965*b1cdbd2cSJim Jagielski my %target_unique_names = map {$_->{'uniquename'} => 1} @$file_list; 966*b1cdbd2cSJim Jagielski my @removed_items = $previous_sequence_data->get_removed_files(\%target_unique_names); 967*b1cdbd2cSJim Jagielski 968*b1cdbd2cSJim Jagielski $installer::logger::Lang->printf( 969*b1cdbd2cSJim Jagielski "there are %d files that have been removed from source and %d files added\n", 970*b1cdbd2cSJim Jagielski scalar @removed_items, 971*b1cdbd2cSJim Jagielski scalar @added_files); 972*b1cdbd2cSJim Jagielski 973*b1cdbd2cSJim Jagielski my $file_map = $installer::globals::source_msi->GetFileMap(); 974*b1cdbd2cSJim Jagielski my $index = 0; 975*b1cdbd2cSJim Jagielski foreach my $removed_row (@removed_items) 976*b1cdbd2cSJim Jagielski { 977*b1cdbd2cSJim Jagielski $installer::logger::Lang->printf(" removed file %d: %s\n", 978*b1cdbd2cSJim Jagielski ++$index, 979*b1cdbd2cSJim Jagielski $removed_row->GetValue('File')); 980*b1cdbd2cSJim Jagielski my $directory = $file_map->{$removed_row->GetValue('File')}->{'directory'}; 981*b1cdbd2cSJim Jagielski while (my ($key,$value) = each %$directory) 982*b1cdbd2cSJim Jagielski { 983*b1cdbd2cSJim Jagielski $installer::logger::Lang->printf(" %16s -> %s\n", $key, $value); 984*b1cdbd2cSJim Jagielski } 985*b1cdbd2cSJim Jagielski } 986*b1cdbd2cSJim Jagielski $index = 0; 987*b1cdbd2cSJim Jagielski foreach my $added_file (@added_files) 988*b1cdbd2cSJim Jagielski { 989*b1cdbd2cSJim Jagielski $installer::logger::Lang->printf(" added file %d: %s\n", 990*b1cdbd2cSJim Jagielski ++$index, 991*b1cdbd2cSJim Jagielski $added_file->{'uniquename'}); 992*b1cdbd2cSJim Jagielski installer::scriptitems::print_script_item($added_file); 993*b1cdbd2cSJim Jagielski } 994*b1cdbd2cSJim Jagielski my @new_files = create_items_for_missing_files( 995*b1cdbd2cSJim Jagielski \@removed_items, 996*b1cdbd2cSJim Jagielski $installer::globals::source_msi, 997*b1cdbd2cSJim Jagielski $directory_list); 998*b1cdbd2cSJim Jagielski push @$file_list, @new_files; 999*b1cdbd2cSJim Jagielski } 1000*b1cdbd2cSJim Jagielski assign_missing_sequence_numbers($file_list); 1001*b1cdbd2cSJim Jagielski 1002*b1cdbd2cSJim Jagielski foreach my $file (@$file_list) 1003*b1cdbd2cSJim Jagielski { 1004*b1cdbd2cSJim Jagielski if ( ! defined $file->{'componentname'}) 1005*b1cdbd2cSJim Jagielski { 1006*b1cdbd2cSJim Jagielski $file->{'componentname'} = get_file_component_name($file, $file_list); 1007*b1cdbd2cSJim Jagielski } 1008*b1cdbd2cSJim Jagielski if ( ! defined $file->{'uniquename'}) 1009*b1cdbd2cSJim Jagielski { 1010*b1cdbd2cSJim Jagielski $file->{'uniquename'} = generate_unique_filename_for_filetable($file->{'Name'}); 1011*b1cdbd2cSJim Jagielski } 1012*b1cdbd2cSJim Jagielski 1013*b1cdbd2cSJim Jagielski # Collecting all component conditions 1014*b1cdbd2cSJim Jagielski if ( $file->{'ComponentCondition'} ) 1015*b1cdbd2cSJim Jagielski { 1016*b1cdbd2cSJim Jagielski if ( ! exists($installer::globals::componentcondition{$file->{'componentname'}})) 1017*b1cdbd2cSJim Jagielski { 1018*b1cdbd2cSJim Jagielski $installer::globals::componentcondition{$file->{'componentname'}} 1019*b1cdbd2cSJim Jagielski = $file->{'ComponentCondition'}; 1020*b1cdbd2cSJim Jagielski } 1021*b1cdbd2cSJim Jagielski } 1022*b1cdbd2cSJim Jagielski # Collecting also all tree conditions for multilayer products 1023*b1cdbd2cSJim Jagielski get_tree_condition_for_component($file, $file->{'componentname'}); 1024*b1cdbd2cSJim Jagielski 1025*b1cdbd2cSJim Jagielski # Collecting all component names, that have flag VERSION_INDEPENDENT_COMP_ID 1026*b1cdbd2cSJim Jagielski # This should be all components with constant API, for example URE 1027*b1cdbd2cSJim Jagielski if (has_style($file->{'Styles'}, "VERSION_INDEPENDENT_COMP_ID")) 1028*b1cdbd2cSJim Jagielski { 1029*b1cdbd2cSJim Jagielski $installer::globals::base_independent_components{$file->{'componentname'}} = 1; 1030*b1cdbd2cSJim Jagielski } 1031*b1cdbd2cSJim Jagielski 1032*b1cdbd2cSJim Jagielski # Special handling for files in PREDEFINED_OSSHELLNEWDIR. These components 1033*b1cdbd2cSJim Jagielski # need as KeyPath a RegistryItem in HKCU 1034*b1cdbd2cSJim Jagielski if ($file->{'needs_user_registry_key'} 1035*b1cdbd2cSJim Jagielski || (defined $file->{'Dir'} && $file->{'Dir'} =~ /\bPREDEFINED_OSSHELLNEWDIR\b/)) 1036*b1cdbd2cSJim Jagielski { 1037*b1cdbd2cSJim Jagielski my $keypath = generate_registry_keypath($file); 1038*b1cdbd2cSJim Jagielski $file->{'userregkeypath'} = $keypath; 1039*b1cdbd2cSJim Jagielski push(@installer::globals::userregistrycollector, $file); 1040*b1cdbd2cSJim Jagielski $installer::globals::addeduserregitrykeys = 1; 1041*b1cdbd2cSJim Jagielski } 1042*b1cdbd2cSJim Jagielski 1043*b1cdbd2cSJim Jagielski $file->{'windows_language'} = get_language_for_file($file); 1044*b1cdbd2cSJim Jagielski 1045*b1cdbd2cSJim Jagielski process_language_conditions($file); 1046*b1cdbd2cSJim Jagielski } 1047*b1cdbd2cSJim Jagielski 1048*b1cdbd2cSJim Jagielski # The filenames must be collected because of uniqueness 1049*b1cdbd2cSJim Jagielski # 01-44-~1.DAT, 01-44-~2.DAT, ... 1050*b1cdbd2cSJim Jagielski my %shortnames = (); 1051*b1cdbd2cSJim Jagielski foreach my $file (@$file_list) 1052*b1cdbd2cSJim Jagielski { 1053*b1cdbd2cSJim Jagielski $file->{'short_name'} = generate_filename_for_filetable($file, \%shortnames); 1054*b1cdbd2cSJim Jagielski } 1055*b1cdbd2cSJim Jagielski} 1056*b1cdbd2cSJim Jagielski 1057*b1cdbd2cSJim Jagielski 1058*b1cdbd2cSJim Jagielski 1059*b1cdbd2cSJim Jagielski 1060*b1cdbd2cSJim Jagielskisub create_file_table_data ($$) 1061*b1cdbd2cSJim Jagielski{ 1062*b1cdbd2cSJim Jagielski my ($file_list, $allvariables) = @_; 1063*b1cdbd2cSJim Jagielski 1064*b1cdbd2cSJim Jagielski my @file_table_data = (); 1065*b1cdbd2cSJim Jagielski foreach my $file (@$file_list) 1066*b1cdbd2cSJim Jagielski { 1067*b1cdbd2cSJim Jagielski my $attributes; 1068*b1cdbd2cSJim Jagielski if (has_style($file->{'Styles'}, "DONT_PACK")) 1069*b1cdbd2cSJim Jagielski { 1070*b1cdbd2cSJim Jagielski # Sourcefile is unpacked (msidbFileAttributesNoncompressed). 1071*b1cdbd2cSJim Jagielski $attributes = "8192"; 1072*b1cdbd2cSJim Jagielski } 1073*b1cdbd2cSJim Jagielski else 1074*b1cdbd2cSJim Jagielski { 1075*b1cdbd2cSJim Jagielski # Sourcefile is packed (msidbFileAttributesCompressed). 1076*b1cdbd2cSJim Jagielski $attributes = "16384"; 1077*b1cdbd2cSJim Jagielski } 1078*b1cdbd2cSJim Jagielski 1079*b1cdbd2cSJim Jagielski my $row_data = { 1080*b1cdbd2cSJim Jagielski 'File' => $file->{'uniquename'}, 1081*b1cdbd2cSJim Jagielski 'Component_' => $file->{'componentname'}, 1082*b1cdbd2cSJim Jagielski 'FileName' => $file->{'short_name'}, 1083*b1cdbd2cSJim Jagielski 'FileSize' => get_filesize($file), 1084*b1cdbd2cSJim Jagielski 'Version' => get_fileversion($file, $allvariables), 1085*b1cdbd2cSJim Jagielski 'Language' => $file->{'windows_language'}, 1086*b1cdbd2cSJim Jagielski 'Attributes' => $attributes, 1087*b1cdbd2cSJim Jagielski 'Sequence' => $file->{'sequencenumber'} 1088*b1cdbd2cSJim Jagielski }; 1089*b1cdbd2cSJim Jagielski push @file_table_data, $row_data; 1090*b1cdbd2cSJim Jagielski } 1091*b1cdbd2cSJim Jagielski 1092*b1cdbd2cSJim Jagielski return \@file_table_data; 1093*b1cdbd2cSJim Jagielski} 1094*b1cdbd2cSJim Jagielski 1095*b1cdbd2cSJim Jagielski 1096*b1cdbd2cSJim Jagielski 1097*b1cdbd2cSJim Jagielski 1098*b1cdbd2cSJim Jagielskisub collect_components ($) 1099*b1cdbd2cSJim Jagielski{ 1100*b1cdbd2cSJim Jagielski my ($file_list) = @_; 1101*b1cdbd2cSJim Jagielski 1102*b1cdbd2cSJim Jagielski my %components = (); 1103*b1cdbd2cSJim Jagielski foreach my $file (@$file_list) 1104*b1cdbd2cSJim Jagielski { 1105*b1cdbd2cSJim Jagielski $components{$file->{'componentname'}} = 1; 1106*b1cdbd2cSJim Jagielski } 1107*b1cdbd2cSJim Jagielski return keys %components; 1108*b1cdbd2cSJim Jagielski} 1109*b1cdbd2cSJim Jagielski 1110*b1cdbd2cSJim Jagielski 1111*b1cdbd2cSJim Jagielski 1112*b1cdbd2cSJim Jagielski 1113*b1cdbd2cSJim Jagielski=head filter_files($file_list, $allvariables) 1114*b1cdbd2cSJim Jagielski 1115*b1cdbd2cSJim Jagielski Filter out Java files when not building a Java product. 1116*b1cdbd2cSJim Jagielski 1117*b1cdbd2cSJim Jagielski Is this still triggered? 1118*b1cdbd2cSJim Jagielski 1119*b1cdbd2cSJim Jagielski=cut 1120*b1cdbd2cSJim Jagielskisub filter_files ($$) 1121*b1cdbd2cSJim Jagielski{ 1122*b1cdbd2cSJim Jagielski my ($file_list, $allvariables) = @_; 1123*b1cdbd2cSJim Jagielski 1124*b1cdbd2cSJim Jagielski if ($allvariables->{'JAVAPRODUCT'}) 1125*b1cdbd2cSJim Jagielski { 1126*b1cdbd2cSJim Jagielski return $file_list; 1127*b1cdbd2cSJim Jagielski } 1128*b1cdbd2cSJim Jagielski else 1129*b1cdbd2cSJim Jagielski { 1130*b1cdbd2cSJim Jagielski my @filtered_files = (); 1131*b1cdbd2cSJim Jagielski foreach my $file (@$file_list) 1132*b1cdbd2cSJim Jagielski { 1133*b1cdbd2cSJim Jagielski if ( ! has_style($file->{'Styles'}, "JAVAFILE")) 1134*b1cdbd2cSJim Jagielski { 1135*b1cdbd2cSJim Jagielski push @filtered_files, $file; 1136*b1cdbd2cSJim Jagielski } 1137*b1cdbd2cSJim Jagielski } 1138*b1cdbd2cSJim Jagielski return \@filtered_files; 1139*b1cdbd2cSJim Jagielski } 1140*b1cdbd2cSJim Jagielski} 1141*b1cdbd2cSJim Jagielski 1142*b1cdbd2cSJim Jagielski 1143*b1cdbd2cSJim Jagielski 1144*b1cdbd2cSJim Jagielski 1145*b1cdbd2cSJim Jagielski# Structure of the files table: 1146*b1cdbd2cSJim Jagielski# File Component_ FileName FileSize Version Language Attributes Sequence 1147*b1cdbd2cSJim Jagielskisub create_file_table ($$) 1148*b1cdbd2cSJim Jagielski{ 1149*b1cdbd2cSJim Jagielski my ($file_table_data, $basedir) = @_; 1150*b1cdbd2cSJim Jagielski 1151*b1cdbd2cSJim Jagielski # Set up the 'File' table. 1152*b1cdbd2cSJim Jagielski my @filetable = (); 1153*b1cdbd2cSJim Jagielski installer::windows::idtglobal::write_idt_header(\@filetable, "file"); 1154*b1cdbd2cSJim Jagielski my @keys = ('File', 'Component_', 'FileName', 'FileSize', 'Version', 'Language', 'Attributes', 'Sequence'); 1155*b1cdbd2cSJim Jagielski my $index = 0; 1156*b1cdbd2cSJim Jagielski foreach my $row_data (@$file_table_data) 1157*b1cdbd2cSJim Jagielski { 1158*b1cdbd2cSJim Jagielski ++$index; 1159*b1cdbd2cSJim Jagielski my @values = map {$row_data->{$_}} @keys; 1160*b1cdbd2cSJim Jagielski my $line = join("\t", @values) . "\n"; 1161*b1cdbd2cSJim Jagielski push(@filetable, $line); 1162*b1cdbd2cSJim Jagielski } 1163*b1cdbd2cSJim Jagielski 1164*b1cdbd2cSJim Jagielski my $filetablename = $basedir . $installer::globals::separator . "File.idt"; 1165*b1cdbd2cSJim Jagielski installer::files::save_file($filetablename ,\@filetable); 1166*b1cdbd2cSJim Jagielski $installer::logger::Lang->print("\n"); 1167*b1cdbd2cSJim Jagielski $installer::logger::Lang->printf("Created idt file: %s\n", $filetablename); 1168*b1cdbd2cSJim Jagielski} 1169*b1cdbd2cSJim Jagielski 1170*b1cdbd2cSJim Jagielski 1171*b1cdbd2cSJim Jagielski 1172*b1cdbd2cSJim Jagielski 1173*b1cdbd2cSJim Jagielskisub create_filehash_table ($$) 1174*b1cdbd2cSJim Jagielski{ 1175*b1cdbd2cSJim Jagielski my ($file_list, $basedir) = @_; 1176*b1cdbd2cSJim Jagielski 1177*b1cdbd2cSJim Jagielski my @filehashtable = (); 1178*b1cdbd2cSJim Jagielski 1179*b1cdbd2cSJim Jagielski if ( $installer::globals::prepare_winpatch ) 1180*b1cdbd2cSJim Jagielski { 1181*b1cdbd2cSJim Jagielski 1182*b1cdbd2cSJim Jagielski installer::windows::idtglobal::write_idt_header(\@filehashtable, "filehash"); 1183*b1cdbd2cSJim Jagielski 1184*b1cdbd2cSJim Jagielski foreach my $file (@$file_list) 1185*b1cdbd2cSJim Jagielski { 1186*b1cdbd2cSJim Jagielski my $path = $file->{'sourcepath'}; 1187*b1cdbd2cSJim Jagielski if ($^O =~ /cygwin/i) 1188*b1cdbd2cSJim Jagielski { 1189*b1cdbd2cSJim Jagielski $path = $file->{'cyg_sourcepath'}; 1190*b1cdbd2cSJim Jagielski } 1191*b1cdbd2cSJim Jagielski 1192*b1cdbd2cSJim Jagielski open(FILE, $path) or die "ERROR: Can't open $path for creating file hash"; 1193*b1cdbd2cSJim Jagielski binmode(FILE); 1194*b1cdbd2cSJim Jagielski my $hashinfo = pack("l", 20); 1195*b1cdbd2cSJim Jagielski $hashinfo .= Digest::MD5->new->addfile(*FILE)->digest; 1196*b1cdbd2cSJim Jagielski 1197*b1cdbd2cSJim Jagielski my @i = unpack ('x[l]l4', $hashinfo); 1198*b1cdbd2cSJim Jagielski my $oneline = join("\t", 1199*b1cdbd2cSJim Jagielski ( 1200*b1cdbd2cSJim Jagielski $file->{'uniquename'}, 1201*b1cdbd2cSJim Jagielski "0", 1202*b1cdbd2cSJim Jagielski @i 1203*b1cdbd2cSJim Jagielski )); 1204*b1cdbd2cSJim Jagielski push (@filehashtable, $oneline . "\n"); 1205*b1cdbd2cSJim Jagielski } 1206*b1cdbd2cSJim Jagielski 1207*b1cdbd2cSJim Jagielski my $filehashtablename = $basedir . $installer::globals::separator . "MsiFileHash.idt"; 1208*b1cdbd2cSJim Jagielski installer::files::save_file($filehashtablename ,\@filehashtable); 1209*b1cdbd2cSJim Jagielski $installer::logger::Lang->print("\n"); 1210*b1cdbd2cSJim Jagielski $installer::logger::Lang->printf("Created idt file: %s\n", $filehashtablename); 1211*b1cdbd2cSJim Jagielski } 1212*b1cdbd2cSJim Jagielski} 1213*b1cdbd2cSJim Jagielski 1214*b1cdbd2cSJim Jagielski 1215*b1cdbd2cSJim Jagielski1; 1216