1*cdf0e10cSrcweir#************************************************************************* 2*cdf0e10cSrcweir# 3*cdf0e10cSrcweir# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir# 5*cdf0e10cSrcweir# Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir# 7*cdf0e10cSrcweir# OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir# 9*cdf0e10cSrcweir# This file is part of OpenOffice.org. 10*cdf0e10cSrcweir# 11*cdf0e10cSrcweir# OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir# it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir# only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir# 15*cdf0e10cSrcweir# OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir# but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir# GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir# (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir# 21*cdf0e10cSrcweir# You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir# version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir# <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir# for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir# 26*cdf0e10cSrcweir#************************************************************************* 27*cdf0e10cSrcweir 28*cdf0e10cSrcweirpackage installer::windows::sign; 29*cdf0e10cSrcweir 30*cdf0e10cSrcweiruse Cwd; 31*cdf0e10cSrcweiruse installer::converter; 32*cdf0e10cSrcweiruse installer::existence; 33*cdf0e10cSrcweiruse installer::files; 34*cdf0e10cSrcweiruse installer::globals; 35*cdf0e10cSrcweiruse installer::scriptitems; 36*cdf0e10cSrcweiruse installer::worker; 37*cdf0e10cSrcweiruse installer::windows::admin; 38*cdf0e10cSrcweir 39*cdf0e10cSrcweir######################################################## 40*cdf0e10cSrcweir# Copying an existing Windows installation set. 41*cdf0e10cSrcweir######################################################## 42*cdf0e10cSrcweir 43*cdf0e10cSrcweirsub copy_install_set 44*cdf0e10cSrcweir{ 45*cdf0e10cSrcweir my ( $installsetpath ) = @_; 46*cdf0e10cSrcweir 47*cdf0e10cSrcweir installer::logger::include_header_into_logfile("Start: Copying installation set $installsetpath"); 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir my $infoline = ""; 50*cdf0e10cSrcweir 51*cdf0e10cSrcweir my $dirname = $installsetpath; 52*cdf0e10cSrcweir installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$dirname); 53*cdf0e10cSrcweir 54*cdf0e10cSrcweir my $path = $installsetpath; 55*cdf0e10cSrcweir installer::pathanalyzer::get_path_from_fullqualifiedname(\$path); 56*cdf0e10cSrcweir 57*cdf0e10cSrcweir $path =~ s/\Q$installer::globals::separator\E\s*$//; 58*cdf0e10cSrcweir 59*cdf0e10cSrcweir if ( $dirname =~ /\./ ) { $dirname =~ s/\./_signed_inprogress./; } 60*cdf0e10cSrcweir else { $dirname = $dirname . "_signed_inprogress"; } 61*cdf0e10cSrcweir 62*cdf0e10cSrcweir my $newpath = $path . $installer::globals::separator . $dirname; 63*cdf0e10cSrcweir my $removepath = $newpath; 64*cdf0e10cSrcweir $removepath =~ s/_inprogress/_witherror/; 65*cdf0e10cSrcweir 66*cdf0e10cSrcweir if ( -d $newpath ) { installer::systemactions::remove_complete_directory($newpath, 1); } 67*cdf0e10cSrcweir if ( -d $removepath ) { installer::systemactions::remove_complete_directory($removepath, 1); } 68*cdf0e10cSrcweir 69*cdf0e10cSrcweir $infoline = "Copy installation set from $installsetpath to $newpath\n"; 70*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir $installsetpath = installer::systemactions::copy_complete_directory($installsetpath, $newpath); 73*cdf0e10cSrcweir 74*cdf0e10cSrcweir installer::logger::include_header_into_logfile("End: Copying installation set $installsetpath"); 75*cdf0e10cSrcweir 76*cdf0e10cSrcweir return $newpath; 77*cdf0e10cSrcweir} 78*cdf0e10cSrcweir 79*cdf0e10cSrcweir######################################################## 80*cdf0e10cSrcweir# Renaming an existing Windows installation set. 81*cdf0e10cSrcweir######################################################## 82*cdf0e10cSrcweir 83*cdf0e10cSrcweirsub rename_install_set 84*cdf0e10cSrcweir{ 85*cdf0e10cSrcweir my ( $installsetpath ) = @_; 86*cdf0e10cSrcweir 87*cdf0e10cSrcweir my $infoline = ""; 88*cdf0e10cSrcweir 89*cdf0e10cSrcweir my $dirname = $installsetpath; 90*cdf0e10cSrcweir installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$dirname); 91*cdf0e10cSrcweir 92*cdf0e10cSrcweir my $path = $installsetpath; 93*cdf0e10cSrcweir installer::pathanalyzer::get_path_from_fullqualifiedname(\$path); 94*cdf0e10cSrcweir 95*cdf0e10cSrcweir $path =~ s/\Q$installer::globals::separator\E\s*$//; 96*cdf0e10cSrcweir 97*cdf0e10cSrcweir if ( $dirname =~ /\./ ) { $dirname =~ s/\./_inprogress./; } 98*cdf0e10cSrcweir else { $dirname = $dirname . "_inprogress"; } 99*cdf0e10cSrcweir 100*cdf0e10cSrcweir my $newpath = $path . $installer::globals::separator . $dirname; 101*cdf0e10cSrcweir my $removepath = $newpath; 102*cdf0e10cSrcweir $removepath =~ s/_inprogress/_witherror/; 103*cdf0e10cSrcweir 104*cdf0e10cSrcweir if ( -d $newpath ) { installer::systemactions::remove_complete_directory($newpath, 1); } 105*cdf0e10cSrcweir if ( -d $removepath ) { installer::systemactions::remove_complete_directory($removepath, 1); } 106*cdf0e10cSrcweir 107*cdf0e10cSrcweir $installsetpath = installer::systemactions::rename_directory($installsetpath, $newpath); 108*cdf0e10cSrcweir 109*cdf0e10cSrcweir return $newpath; 110*cdf0e10cSrcweir} 111*cdf0e10cSrcweir 112*cdf0e10cSrcweir######################################################### 113*cdf0e10cSrcweir# Checking the local system 114*cdf0e10cSrcweir# Checking existence of needed files in include path 115*cdf0e10cSrcweir######################################################### 116*cdf0e10cSrcweir 117*cdf0e10cSrcweirsub check_system_path 118*cdf0e10cSrcweir{ 119*cdf0e10cSrcweir # The following files have to be found in the environment variable PATH 120*cdf0e10cSrcweir # Only, if \"-sign\" is used. 121*cdf0e10cSrcweir # Windows : "msicert.exe", "diff.exe", "msidb.exe", "signtool.exe" 122*cdf0e10cSrcweir 123*cdf0e10cSrcweir my @needed_files_in_path = ("msicert.exe", "msidb.exe", "signtool.exe", "diff.exe"); 124*cdf0e10cSrcweir if ( $installer::globals::internal_cabinet_signing ) 125*cdf0e10cSrcweir { 126*cdf0e10cSrcweir push(@needed_files_in_path, "cabarc.exe"); 127*cdf0e10cSrcweir push(@needed_files_in_path, "makecab.exe"); 128*cdf0e10cSrcweir } 129*cdf0e10cSrcweir 130*cdf0e10cSrcweir my $onefile; 131*cdf0e10cSrcweir my $error = 0; 132*cdf0e10cSrcweir my $pathvariable = $ENV{'PATH'}; 133*cdf0e10cSrcweir my $local_pathseparator = $installer::globals::pathseparator; 134*cdf0e10cSrcweir 135*cdf0e10cSrcweir if( $^O =~ /cygwin/i ) 136*cdf0e10cSrcweir { # When using cygwin's perl the PATH variable is POSIX style and ... 137*cdf0e10cSrcweir $pathvariable = qx{cygpath -mp "$pathvariable"} ; 138*cdf0e10cSrcweir # has to be converted to DOS style for further use. 139*cdf0e10cSrcweir $local_pathseparator = ';'; 140*cdf0e10cSrcweir } 141*cdf0e10cSrcweir 142*cdf0e10cSrcweir my $patharrayref = installer::converter::convert_stringlist_into_array(\$pathvariable, $local_pathseparator); 143*cdf0e10cSrcweir 144*cdf0e10cSrcweir $installer::globals::patharray = $patharrayref; 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir foreach my $onefile ( @needed_files_in_path ) 147*cdf0e10cSrcweir { 148*cdf0e10cSrcweir installer::logger::print_message( "...... searching $onefile ..." ); 149*cdf0e10cSrcweir 150*cdf0e10cSrcweir my $fileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath_classic(\$onefile, $patharrayref , 0); 151*cdf0e10cSrcweir 152*cdf0e10cSrcweir if ( $$fileref eq "" ) 153*cdf0e10cSrcweir { 154*cdf0e10cSrcweir $error = 1; 155*cdf0e10cSrcweir installer::logger::print_error( "$onefile not found\n" ); 156*cdf0e10cSrcweir } 157*cdf0e10cSrcweir else 158*cdf0e10cSrcweir { 159*cdf0e10cSrcweir installer::logger::print_message( "\tFound: $$fileref\n" ); 160*cdf0e10cSrcweir } 161*cdf0e10cSrcweir } 162*cdf0e10cSrcweir 163*cdf0e10cSrcweir $installer::globals::signfiles_checked = 1; 164*cdf0e10cSrcweir 165*cdf0e10cSrcweir if ( $error ) { installer::exiter::exit_program("ERROR: Could not find all needed files in path!", "check_system_path"); } 166*cdf0e10cSrcweir} 167*cdf0e10cSrcweir 168*cdf0e10cSrcweir###################################################### 169*cdf0e10cSrcweir# Making systemcall 170*cdf0e10cSrcweir###################################################### 171*cdf0e10cSrcweir 172*cdf0e10cSrcweirsub make_systemcall 173*cdf0e10cSrcweir{ 174*cdf0e10cSrcweir my ($systemcall, $displaysystemcall) = @_; 175*cdf0e10cSrcweir 176*cdf0e10cSrcweir installer::logger::print_message( "... $displaysystemcall ...\n" ); 177*cdf0e10cSrcweir 178*cdf0e10cSrcweir my $success = 1; 179*cdf0e10cSrcweir my $returnvalue = system($systemcall); 180*cdf0e10cSrcweir 181*cdf0e10cSrcweir my $infoline = "Systemcall: $displaysystemcall\n"; 182*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 183*cdf0e10cSrcweir 184*cdf0e10cSrcweir if ($returnvalue) 185*cdf0e10cSrcweir { 186*cdf0e10cSrcweir $infoline = "ERROR: Could not execute \"$displaysystemcall\"!\n"; 187*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 188*cdf0e10cSrcweir $success = 0; 189*cdf0e10cSrcweir } 190*cdf0e10cSrcweir else 191*cdf0e10cSrcweir { 192*cdf0e10cSrcweir $infoline = "Success: Executed \"$displaysystemcall\" successfully!\n"; 193*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 194*cdf0e10cSrcweir } 195*cdf0e10cSrcweir 196*cdf0e10cSrcweir return $success; 197*cdf0e10cSrcweir} 198*cdf0e10cSrcweir 199*cdf0e10cSrcweir###################################################### 200*cdf0e10cSrcweir# Making systemcall with warning 201*cdf0e10cSrcweir###################################################### 202*cdf0e10cSrcweir 203*cdf0e10cSrcweirsub make_systemcall_with_warning 204*cdf0e10cSrcweir{ 205*cdf0e10cSrcweir my ($systemcall, $displaysystemcall) = @_; 206*cdf0e10cSrcweir 207*cdf0e10cSrcweir installer::logger::print_message( "... $displaysystemcall ...\n" ); 208*cdf0e10cSrcweir 209*cdf0e10cSrcweir my $success = 1; 210*cdf0e10cSrcweir my $returnvalue = system($systemcall); 211*cdf0e10cSrcweir 212*cdf0e10cSrcweir my $infoline = "Systemcall: $displaysystemcall\n"; 213*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 214*cdf0e10cSrcweir 215*cdf0e10cSrcweir if ($returnvalue) 216*cdf0e10cSrcweir { 217*cdf0e10cSrcweir $infoline = "WARNING: Could not execute \"$displaysystemcall\"!\n"; 218*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 219*cdf0e10cSrcweir $success = 0; 220*cdf0e10cSrcweir } 221*cdf0e10cSrcweir else 222*cdf0e10cSrcweir { 223*cdf0e10cSrcweir $infoline = "Success: Executed \"$displaysystemcall\" successfully!\n"; 224*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 225*cdf0e10cSrcweir } 226*cdf0e10cSrcweir 227*cdf0e10cSrcweir return $success; 228*cdf0e10cSrcweir} 229*cdf0e10cSrcweir 230*cdf0e10cSrcweir###################################################### 231*cdf0e10cSrcweir# Making systemcall with more return data 232*cdf0e10cSrcweir###################################################### 233*cdf0e10cSrcweir 234*cdf0e10cSrcweirsub execute_open_system_call 235*cdf0e10cSrcweir{ 236*cdf0e10cSrcweir my ( $systemcall ) = @_; 237*cdf0e10cSrcweir 238*cdf0e10cSrcweir my @openoutput = (); 239*cdf0e10cSrcweir my $success = 1; 240*cdf0e10cSrcweir 241*cdf0e10cSrcweir my $comspec = $ENV{COMSPEC}; 242*cdf0e10cSrcweir $comspec = $comspec . " -c "; 243*cdf0e10cSrcweir 244*cdf0e10cSrcweir if( $^O =~ /cygwin/i ) 245*cdf0e10cSrcweir { 246*cdf0e10cSrcweir # $comspec =~ s/\\/\\\\/g; 247*cdf0e10cSrcweir # $comspec = qx{cygpath -u "$comspec"}; 248*cdf0e10cSrcweir # $comspec =~ s/\s*$//g; 249*cdf0e10cSrcweir $comspec = ""; 250*cdf0e10cSrcweir } 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir my $localsystemcall = "$comspec $systemcall 2>&1 |"; 253*cdf0e10cSrcweir 254*cdf0e10cSrcweir open( OPN, "$localsystemcall") or warn "Can't execute $localsystemcall\n"; 255*cdf0e10cSrcweir while (<OPN>) { push(@openoutput, $_); } 256*cdf0e10cSrcweir close (OPN); 257*cdf0e10cSrcweir 258*cdf0e10cSrcweir my $returnvalue = $?; # $? contains the return value of the systemcall 259*cdf0e10cSrcweir 260*cdf0e10cSrcweir if ($returnvalue) 261*cdf0e10cSrcweir { 262*cdf0e10cSrcweir $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; 263*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 264*cdf0e10cSrcweir $success = 0; 265*cdf0e10cSrcweir } 266*cdf0e10cSrcweir else 267*cdf0e10cSrcweir { 268*cdf0e10cSrcweir $infoline = "Success: Executed \"$systemcall\" successfully!\n"; 269*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 270*cdf0e10cSrcweir } 271*cdf0e10cSrcweir 272*cdf0e10cSrcweir return ($success, \@openoutput); 273*cdf0e10cSrcweir} 274*cdf0e10cSrcweir 275*cdf0e10cSrcweir######################################################## 276*cdf0e10cSrcweir# Reading first line of pw file. 277*cdf0e10cSrcweir######################################################## 278*cdf0e10cSrcweir 279*cdf0e10cSrcweirsub get_pw 280*cdf0e10cSrcweir{ 281*cdf0e10cSrcweir my ( $file ) = @_; 282*cdf0e10cSrcweir 283*cdf0e10cSrcweir my $filecontent = installer::files::read_file($file); 284*cdf0e10cSrcweir 285*cdf0e10cSrcweir my $pw = ${$filecontent}[0]; 286*cdf0e10cSrcweir $pw =~ s/^\s*//; 287*cdf0e10cSrcweir $pw =~ s/\s*$//; 288*cdf0e10cSrcweir 289*cdf0e10cSrcweir return $pw; 290*cdf0e10cSrcweir} 291*cdf0e10cSrcweir 292*cdf0e10cSrcweir######################################################## 293*cdf0e10cSrcweir# Counting the keys of a hash. 294*cdf0e10cSrcweir######################################################## 295*cdf0e10cSrcweir 296*cdf0e10cSrcweirsub get_hash_count 297*cdf0e10cSrcweir{ 298*cdf0e10cSrcweir my ($hashref) = @_; 299*cdf0e10cSrcweir 300*cdf0e10cSrcweir my $counter = 0; 301*cdf0e10cSrcweir 302*cdf0e10cSrcweir foreach my $key ( keys %{$hashref} ) { $counter++; } 303*cdf0e10cSrcweir 304*cdf0e10cSrcweir return $counter; 305*cdf0e10cSrcweir} 306*cdf0e10cSrcweir 307*cdf0e10cSrcweir############################################################ 308*cdf0e10cSrcweir# Collect all last files in a cabinet file. This is 309*cdf0e10cSrcweir# necessary to control, if the cabinet file was damaged 310*cdf0e10cSrcweir# by calling signtool.exe. 311*cdf0e10cSrcweir############################################################ 312*cdf0e10cSrcweir 313*cdf0e10cSrcweirsub analyze_file_file 314*cdf0e10cSrcweir{ 315*cdf0e10cSrcweir my ($filecontent) = @_; 316*cdf0e10cSrcweir 317*cdf0e10cSrcweir my %filenamehash = (); 318*cdf0e10cSrcweir 319*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) 320*cdf0e10cSrcweir { 321*cdf0e10cSrcweir if ( $i < 3 ) { next; } 322*cdf0e10cSrcweir 323*cdf0e10cSrcweir if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 324*cdf0e10cSrcweir { 325*cdf0e10cSrcweir my $name = $1; 326*cdf0e10cSrcweir my $sequence = $8; 327*cdf0e10cSrcweir 328*cdf0e10cSrcweir $filenamehash{$sequence} = $name; 329*cdf0e10cSrcweir } 330*cdf0e10cSrcweir } 331*cdf0e10cSrcweir 332*cdf0e10cSrcweir return ( \%filenamehash ); 333*cdf0e10cSrcweir} 334*cdf0e10cSrcweir 335*cdf0e10cSrcweir############################################################ 336*cdf0e10cSrcweir# Collect all DiskIds to the corresponding cabinet files. 337*cdf0e10cSrcweir############################################################ 338*cdf0e10cSrcweir 339*cdf0e10cSrcweirsub analyze_media_file 340*cdf0e10cSrcweir{ 341*cdf0e10cSrcweir my ($filecontent) = @_; 342*cdf0e10cSrcweir 343*cdf0e10cSrcweir my %diskidhash = (); 344*cdf0e10cSrcweir my %lastsequencehash = (); 345*cdf0e10cSrcweir 346*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) 347*cdf0e10cSrcweir { 348*cdf0e10cSrcweir if ( $i < 3 ) { next; } 349*cdf0e10cSrcweir 350*cdf0e10cSrcweir if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 351*cdf0e10cSrcweir { 352*cdf0e10cSrcweir my $diskid = $1; 353*cdf0e10cSrcweir my $lastsequence = $2; 354*cdf0e10cSrcweir my $cabfile = $4; 355*cdf0e10cSrcweir 356*cdf0e10cSrcweir $diskidhash{$cabfile} = $diskid; 357*cdf0e10cSrcweir $lastsequencehash{$cabfile} = $lastsequence; 358*cdf0e10cSrcweir } 359*cdf0e10cSrcweir } 360*cdf0e10cSrcweir 361*cdf0e10cSrcweir return ( \%diskidhash, \%lastsequencehash ); 362*cdf0e10cSrcweir} 363*cdf0e10cSrcweir 364*cdf0e10cSrcweir######################################################## 365*cdf0e10cSrcweir# Collect all DiskIds from database table "Media". 366*cdf0e10cSrcweir######################################################## 367*cdf0e10cSrcweir 368*cdf0e10cSrcweirsub collect_diskid_from_media_table 369*cdf0e10cSrcweir{ 370*cdf0e10cSrcweir my ($msidatabase, $languagestring) = @_; 371*cdf0e10cSrcweir 372*cdf0e10cSrcweir # creating working directory 373*cdf0e10cSrcweir my $workdir = installer::systemactions::create_directories("media", \$languagestring); 374*cdf0e10cSrcweir installer::windows::admin::extract_tables_from_pcpfile($msidatabase, $workdir, "Media File"); 375*cdf0e10cSrcweir 376*cdf0e10cSrcweir # Reading tables 377*cdf0e10cSrcweir my $filename = $workdir . $installer::globals::separator . "Media.idt"; 378*cdf0e10cSrcweir if ( ! -f $filename ) { installer::exiter::exit_program("ERROR: Could not find required file: $filename !", "collect_diskid_from_media_table"); } 379*cdf0e10cSrcweir my $filecontent = installer::files::read_file($filename); 380*cdf0e10cSrcweir my ( $diskidhash, $lastsequencehash ) = analyze_media_file($filecontent); 381*cdf0e10cSrcweir 382*cdf0e10cSrcweir $filename = $workdir . $installer::globals::separator . "File.idt"; 383*cdf0e10cSrcweir if ( ! -f $filename ) { installer::exiter::exit_program("ERROR: Could not find required file: $filename !", "collect_diskid_from_media_table"); } 384*cdf0e10cSrcweir $filecontent = installer::files::read_file($filename); 385*cdf0e10cSrcweir my $filenamehash = analyze_file_file($filecontent); 386*cdf0e10cSrcweir 387*cdf0e10cSrcweir return ( $diskidhash, $filenamehash, $lastsequencehash ); 388*cdf0e10cSrcweir} 389*cdf0e10cSrcweir 390*cdf0e10cSrcweir######################################################## 391*cdf0e10cSrcweir# Check, if this installation set contains 392*cdf0e10cSrcweir# internal cabinet files included into the msi 393*cdf0e10cSrcweir# database. 394*cdf0e10cSrcweir######################################################## 395*cdf0e10cSrcweir 396*cdf0e10cSrcweirsub check_for_internal_cabfiles 397*cdf0e10cSrcweir{ 398*cdf0e10cSrcweir my ($cabfilehash) = @_; 399*cdf0e10cSrcweir 400*cdf0e10cSrcweir my $contains_internal_cabfiles = 0; 401*cdf0e10cSrcweir my %allcabfileshash = (); 402*cdf0e10cSrcweir 403*cdf0e10cSrcweir foreach my $filename ( keys %{$cabfilehash} ) 404*cdf0e10cSrcweir { 405*cdf0e10cSrcweir if ( $filename =~ /^\s*\#/ ) # starting with a hash 406*cdf0e10cSrcweir { 407*cdf0e10cSrcweir $contains_internal_cabfiles = 1; 408*cdf0e10cSrcweir # setting real filename without hash as key and name with hash as value 409*cdf0e10cSrcweir my $realfilename = $filename; 410*cdf0e10cSrcweir $realfilename =~ s/^\s*\#//; 411*cdf0e10cSrcweir $allcabfileshash{$realfilename} = $filename; 412*cdf0e10cSrcweir } 413*cdf0e10cSrcweir } 414*cdf0e10cSrcweir 415*cdf0e10cSrcweir return ( $contains_internal_cabfiles, \%allcabfileshash ); 416*cdf0e10cSrcweir} 417*cdf0e10cSrcweir 418*cdf0e10cSrcweir######################################################## 419*cdf0e10cSrcweir# Collecting all files in an installation set. 420*cdf0e10cSrcweir######################################################## 421*cdf0e10cSrcweir 422*cdf0e10cSrcweirsub analyze_installset_content 423*cdf0e10cSrcweir{ 424*cdf0e10cSrcweir my ( $installsetpath ) = @_; 425*cdf0e10cSrcweir 426*cdf0e10cSrcweir my @sourcefiles = (); 427*cdf0e10cSrcweir my $pathstring = ""; 428*cdf0e10cSrcweir installer::systemactions::read_complete_directory($installsetpath, $pathstring, \@sourcefiles); 429*cdf0e10cSrcweir 430*cdf0e10cSrcweir if ( ! ( $#sourcefiles > -1 )) { installer::exiter::exit_program("ERROR: No file in installation set. Path: $installsetpath !", "analyze_installset_content"); } 431*cdf0e10cSrcweir 432*cdf0e10cSrcweir my %allcabfileshash = (); 433*cdf0e10cSrcweir my %allmsidatabaseshash = (); 434*cdf0e10cSrcweir my %allfileshash = (); 435*cdf0e10cSrcweir my $contains_external_cabfiles = 0; 436*cdf0e10cSrcweir my $msidatabase = ""; 437*cdf0e10cSrcweir my $contains_msidatabase = 0; 438*cdf0e10cSrcweir 439*cdf0e10cSrcweir for ( my $j = 0; $j <= $#sourcefiles; $j++ ) 440*cdf0e10cSrcweir { 441*cdf0e10cSrcweir if ( $sourcefiles[$j] =~ /\.cab\s*$/ ) { $allcabfileshash{$sourcefiles[$j]} = 1; } 442*cdf0e10cSrcweir else 443*cdf0e10cSrcweir { 444*cdf0e10cSrcweir if ( $sourcefiles[$j] =~ /\.txt\s*$/ ) { next; } 445*cdf0e10cSrcweir if ( $sourcefiles[$j] =~ /\.html\s*$/ ) { next; } 446*cdf0e10cSrcweir if ( $sourcefiles[$j] =~ /\.ini\s*$/ ) { next; } 447*cdf0e10cSrcweir if ( $sourcefiles[$j] =~ /\.bmp\s*$/ ) { next; } 448*cdf0e10cSrcweir if ( $sourcefiles[$j] =~ /\.msi\s*$/ ) 449*cdf0e10cSrcweir { 450*cdf0e10cSrcweir if ( $msidatabase eq "" ) { $msidatabase = $sourcefiles[$j]; } 451*cdf0e10cSrcweir else { installer::exiter::exit_program("ERROR: There is more than one msi database in installation set. Path: $installsetpath !", "analyze_installset_content"); } 452*cdf0e10cSrcweir } 453*cdf0e10cSrcweir $allfileshash{$sourcefiles[$j]} = 1; 454*cdf0e10cSrcweir } 455*cdf0e10cSrcweir } 456*cdf0e10cSrcweir 457*cdf0e10cSrcweir # Is there at least one cab file in the installation set? 458*cdf0e10cSrcweir my $cabcounter = get_hash_count(\%allcabfileshash); 459*cdf0e10cSrcweir if ( $cabcounter > 0 ) { $contains_external_cabfiles = 1; } 460*cdf0e10cSrcweir 461*cdf0e10cSrcweir # How about a cab file without a msi database? 462*cdf0e10cSrcweir if (( $cabcounter > 0 ) && ( $msidatabase eq "" )) { installer::exiter::exit_program("ERROR: There is no msi database in the installation set, but an external cabinet file. Path: $installsetpath !", "collect_installset_content"); } 463*cdf0e10cSrcweir 464*cdf0e10cSrcweir if ( $msidatabase ne "" ) { $contains_msidatabase = 1; } 465*cdf0e10cSrcweir 466*cdf0e10cSrcweir return (\%allcabfileshash, \%allfileshash, $msidatabase, $contains_external_cabfiles, $contains_msidatabase, \@sourcefiles); 467*cdf0e10cSrcweir} 468*cdf0e10cSrcweir 469*cdf0e10cSrcweir######################################################## 470*cdf0e10cSrcweir# Adding content of external cabinet files into the 471*cdf0e10cSrcweir# msi database 472*cdf0e10cSrcweir######################################################## 473*cdf0e10cSrcweir 474*cdf0e10cSrcweirsub msicert_database 475*cdf0e10cSrcweir{ 476*cdf0e10cSrcweir my ($msidatabase, $allcabfiles, $cabfilehash, $internalcabfile) = @_; 477*cdf0e10cSrcweir 478*cdf0e10cSrcweir my $fullsuccess = 1; 479*cdf0e10cSrcweir 480*cdf0e10cSrcweir foreach my $cabfile ( keys %{$allcabfiles} ) 481*cdf0e10cSrcweir { 482*cdf0e10cSrcweir my $origfilesize = -s $cabfile; 483*cdf0e10cSrcweir 484*cdf0e10cSrcweir my $mediacabfilename = $cabfile; 485*cdf0e10cSrcweir if ( $internalcabfile ) { $mediacabfilename = "\#" . $mediacabfilename; } 486*cdf0e10cSrcweir if ( ! exists($cabfilehash->{$mediacabfilename}) ) { installer::exiter::exit_program("ERROR: Could not determine DiskId from media table for cabinet file \"$cabfile\" !", "msicert_database"); } 487*cdf0e10cSrcweir my $diskid = $cabfilehash->{$mediacabfilename}; 488*cdf0e10cSrcweir 489*cdf0e10cSrcweir my $systemcall = "msicert.exe -d $msidatabase -m $diskid -c $cabfile -h"; 490*cdf0e10cSrcweir $success = make_systemcall($systemcall, $systemcall); 491*cdf0e10cSrcweir if ( ! $success ) { $fullsuccess = 0; } 492*cdf0e10cSrcweir 493*cdf0e10cSrcweir # size of cabinet file must not change 494*cdf0e10cSrcweir my $finalfilesize = -s $cabfile; 495*cdf0e10cSrcweir 496*cdf0e10cSrcweir if ( $origfilesize != $finalfilesize ) { installer::exiter::exit_program("ERROR: msicert.exe changed size of cabinet file !", "msicert_database"); } 497*cdf0e10cSrcweir } 498*cdf0e10cSrcweir 499*cdf0e10cSrcweir return $fullsuccess; 500*cdf0e10cSrcweir} 501*cdf0e10cSrcweir 502*cdf0e10cSrcweir######################################################## 503*cdf0e10cSrcweir# Checking if cabinet file was broken by signtool. 504*cdf0e10cSrcweir######################################################## 505*cdf0e10cSrcweir 506*cdf0e10cSrcweirsub cabinet_cosistency_check 507*cdf0e10cSrcweir{ 508*cdf0e10cSrcweir my ( $onefile, $followmeinfohash, $filenamehash, $lastsequencehash, $temppath ) = @_; 509*cdf0e10cSrcweir 510*cdf0e10cSrcweir my $infoline = "Making consistency check of $onefile\n"; 511*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 512*cdf0e10cSrcweir my $expandfile = "expand.exe"; # Has to be in the path 513*cdf0e10cSrcweir 514*cdf0e10cSrcweir if ( $^O =~ /cygwin/i ) 515*cdf0e10cSrcweir { 516*cdf0e10cSrcweir $expandfile = qx(cygpath -u "$ENV{WINDIR}"/System32/expand.exe); 517*cdf0e10cSrcweir chomp $expandfile; 518*cdf0e10cSrcweir } 519*cdf0e10cSrcweir 520*cdf0e10cSrcweir if ( $filenamehash == 0 ) 521*cdf0e10cSrcweir { 522*cdf0e10cSrcweir $infoline = "Warning: Stopping consistency check: Important hash of filenames is empty!\n"; 523*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 524*cdf0e10cSrcweir } 525*cdf0e10cSrcweir elsif ( $lastsequencehash == 0 ) 526*cdf0e10cSrcweir { 527*cdf0e10cSrcweir $infoline = "Warning: Stopping consistency check; Important hash of last sequences is empty!\n"; 528*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 529*cdf0e10cSrcweir } 530*cdf0e10cSrcweir else # both hashes are available 531*cdf0e10cSrcweir { 532*cdf0e10cSrcweir # $onefile contains only the name of the cabinet file without path 533*cdf0e10cSrcweir my $sequence = $lastsequencehash->{$onefile}; 534*cdf0e10cSrcweir my $lastfile = $filenamehash->{$sequence}; 535*cdf0e10cSrcweir $infoline = "Check of $onefile: Sequence: $sequence is file: $lastfile\n"; 536*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 537*cdf0e10cSrcweir 538*cdf0e10cSrcweir # Therefore the file $lastfile need to be binary compared. 539*cdf0e10cSrcweir # It has to be expanded from the cabinet file 540*cdf0e10cSrcweir # of the original installation set and from the 541*cdf0e10cSrcweir # newly signed cabinet file. 542*cdf0e10cSrcweir 543*cdf0e10cSrcweir # How about cabinet files extracted from msi database? 544*cdf0e10cSrcweir my $finalinstalldir = $followmeinfohash->{'finalinstalldir'}; 545*cdf0e10cSrcweir 546*cdf0e10cSrcweir $finalinstalldir =~ s/\\\s*$//; 547*cdf0e10cSrcweir $finalinstalldir =~ s/\/\s*$//; 548*cdf0e10cSrcweir my $sourcecabfile = $finalinstalldir . $installer::globals::separator . $onefile; 549*cdf0e10cSrcweir my $currentpath = cwd(); 550*cdf0e10cSrcweir my $destcabfile = $currentpath . $installer::globals::separator . $onefile; 551*cdf0e10cSrcweir # my $destcabfile = $onefile; 552*cdf0e10cSrcweir 553*cdf0e10cSrcweir if ( $^O =~ /cygwin/i ) 554*cdf0e10cSrcweir { 555*cdf0e10cSrcweir chomp( $destcabfile = qx{cygpath -w "$destcabfile"} ); 556*cdf0e10cSrcweir $destcabfile =~ s/\\/\//g; 557*cdf0e10cSrcweir } 558*cdf0e10cSrcweir 559*cdf0e10cSrcweir if ( ! -f $sourcecabfile ) 560*cdf0e10cSrcweir { 561*cdf0e10cSrcweir $infoline = "WARNING: Check of cab file cannot happen, because source cabinet file was not found: $sourcecabfile\n"; 562*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 563*cdf0e10cSrcweir } 564*cdf0e10cSrcweir elsif ( ! -f $destcabfile ) 565*cdf0e10cSrcweir { 566*cdf0e10cSrcweir $infoline = "WARNING: Check of cab file cannot happen, because destination cabinet file was not found: $sourcecabfile\n"; 567*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 568*cdf0e10cSrcweir } 569*cdf0e10cSrcweir else # everything is okay for the check 570*cdf0e10cSrcweir { 571*cdf0e10cSrcweir my $diffpath = get_diff_path($temppath); 572*cdf0e10cSrcweir 573*cdf0e10cSrcweir my $origdiffpath = $diffpath . $installer::globals::separator . "orig"; 574*cdf0e10cSrcweir my $newdiffpath = $diffpath . $installer::globals::separator . "new"; 575*cdf0e10cSrcweir 576*cdf0e10cSrcweir if ( ! -d $origdiffpath ) { mkdir($origdiffpath); } 577*cdf0e10cSrcweir if ( ! -d $newdiffpath ) { mkdir($newdiffpath); } 578*cdf0e10cSrcweir 579*cdf0e10cSrcweir my $systemcall = "$expandfile $sourcecabfile $origdiffpath -f:$lastfile "; 580*cdf0e10cSrcweir $infoline = $systemcall . "\n"; 581*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 582*cdf0e10cSrcweir 583*cdf0e10cSrcweir my $success = make_systemcall($systemcall, $systemcall); 584*cdf0e10cSrcweir if ( ! $success ) { installer::exiter::exit_program("ERROR: Could not successfully execute: $systemcall !", "cabinet_cosistency_check"); } 585*cdf0e10cSrcweir 586*cdf0e10cSrcweir $systemcall = "$expandfile $destcabfile $newdiffpath -f:$lastfile "; 587*cdf0e10cSrcweir $infoline = $systemcall . "\n"; 588*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 589*cdf0e10cSrcweir 590*cdf0e10cSrcweir $success = make_systemcall($systemcall, $systemcall); 591*cdf0e10cSrcweir if ( ! $success ) { installer::exiter::exit_program("ERROR: Could not successfully execute: $systemcall !", "cabinet_cosistency_check"); } 592*cdf0e10cSrcweir 593*cdf0e10cSrcweir # and finally the two files can be diffed. 594*cdf0e10cSrcweir my $origfile = $origdiffpath . $installer::globals::separator . $lastfile; 595*cdf0e10cSrcweir my $newfile = $newdiffpath . $installer::globals::separator . $lastfile; 596*cdf0e10cSrcweir 597*cdf0e10cSrcweir if ( ! -f $origfile ) { installer::exiter::exit_program("ERROR: Unpacked original file not found: $origfile !", "cabinet_cosistency_check"); } 598*cdf0e10cSrcweir if ( ! -f $newfile ) { installer::exiter::exit_program("ERROR: Unpacked new file not found: $newfile !", "cabinet_cosistency_check"); } 599*cdf0e10cSrcweir 600*cdf0e10cSrcweir my $origsize = -s $origfile; 601*cdf0e10cSrcweir my $newsize = -s $newfile; 602*cdf0e10cSrcweir 603*cdf0e10cSrcweir if ( $origsize != $newsize ) # This shows an error! 604*cdf0e10cSrcweir { 605*cdf0e10cSrcweir $infoline = "ERROR: Different filesize after signtool.exe was used. Original: $origsize Bytes, new: $newsize. File: $lastfile\n"; 606*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 607*cdf0e10cSrcweir installer::exiter::exit_program("ERROR: The cabinet file $destcabfile is broken after signtool.exe signed this file !", "cabinet_cosistency_check"); 608*cdf0e10cSrcweir } 609*cdf0e10cSrcweir else 610*cdf0e10cSrcweir { 611*cdf0e10cSrcweir $infoline = "Same size of last file in cabinet file after usage of signtool.exe: $newsize (File: $lastfile)\n"; 612*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 613*cdf0e10cSrcweir 614*cdf0e10cSrcweir # Also making a binary diff? 615*cdf0e10cSrcweir 616*cdf0e10cSrcweir my $difffile = "diff.exe"; # has to be in the path 617*cdf0e10cSrcweir # $systemcall = "$difffile $sourcecabfile $destcabfile"; # Test for differences 618*cdf0e10cSrcweir $systemcall = "$difffile $origfile $newfile"; 619*cdf0e10cSrcweir $infoline = $systemcall . "\n"; 620*cdf0e10cSrcweir $returnvalue = make_systemcall($systemcall, $systemcall); 621*cdf0e10cSrcweir 622*cdf0e10cSrcweir my $success = $?; 623*cdf0e10cSrcweir 624*cdf0e10cSrcweir if ( $success == 0 ) 625*cdf0e10cSrcweir { 626*cdf0e10cSrcweir $infoline = "Last files are identical after signing cabinet file (File: $lastfile)\n"; 627*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 628*cdf0e10cSrcweir } 629*cdf0e10cSrcweir elsif ( $success == 1 ) 630*cdf0e10cSrcweir { 631*cdf0e10cSrcweir $infoline = "ERROR: Last files are different after signing cabinet file (File: $lastfile)\n"; 632*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 633*cdf0e10cSrcweir installer::exiter::exit_program("ERROR: Last files are different after signing cabinet file (File: $lastfile)!", "cabinet_cosistency_check"); 634*cdf0e10cSrcweir } 635*cdf0e10cSrcweir else 636*cdf0e10cSrcweir { 637*cdf0e10cSrcweir $infoline = "ERROR: Problem occured calling diff.exe (File: $lastfile)\n"; 638*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 639*cdf0e10cSrcweir installer::exiter::exit_program("ERROR: Problem occured calling diff.exe (File: $lastfile) !", "cabinet_cosistency_check"); 640*cdf0e10cSrcweir } 641*cdf0e10cSrcweir } 642*cdf0e10cSrcweir } 643*cdf0e10cSrcweir } 644*cdf0e10cSrcweir 645*cdf0e10cSrcweir} 646*cdf0e10cSrcweir 647*cdf0e10cSrcweir######################################################## 648*cdf0e10cSrcweir# Signing a list of files 649*cdf0e10cSrcweir######################################################## 650*cdf0e10cSrcweir 651*cdf0e10cSrcweirsub sign_files 652*cdf0e10cSrcweir{ 653*cdf0e10cSrcweir my ( $followmeinfohash, $allfiles, $pw, $cabinternal, $filenamehash, $lastsequencehash, $temppath ) = @_; 654*cdf0e10cSrcweir 655*cdf0e10cSrcweir my $infoline = ""; 656*cdf0e10cSrcweir my $fullsuccess = 1; 657*cdf0e10cSrcweir my $maxcounter = 3; 658*cdf0e10cSrcweir 659*cdf0e10cSrcweir my $productname = ""; 660*cdf0e10cSrcweir if ( $followmeinfohash->{'allvariableshash'}->{'PRODUCTNAME'} ) { $productname = "/d " . "\"$followmeinfohash->{'allvariableshash'}->{'PRODUCTNAME'}\""; } 661*cdf0e10cSrcweir my $url = ""; 662*cdf0e10cSrcweir if (( ! exists($followmeinfohash->{'allvariableshash'}->{'OPENSOURCE'}) ) || ( $followmeinfohash->{'allvariableshash'}->{'OPENSOURCE'} == 0 )) { $url = "/du " . "\"http://www.sun.com\""; } 663*cdf0e10cSrcweir else { $url = "/du " . "\"http://www.openoffice.org\""; } 664*cdf0e10cSrcweir my $timestampurl = "http://timestamp.verisign.com/scripts/timestamp.dll"; 665*cdf0e10cSrcweir 666*cdf0e10cSrcweir my $pfxfilepath = $installer::globals::pfxfile; 667*cdf0e10cSrcweir 668*cdf0e10cSrcweir if( $^O =~ /cygwin/i ) 669*cdf0e10cSrcweir { 670*cdf0e10cSrcweir $pfxfilepath = qx{cygpath -w "$pfxfilepath"}; 671*cdf0e10cSrcweir $pfxfilepath =~ s/\\/\\\\/g; 672*cdf0e10cSrcweir $pfxfilepath =~ s/\s*$//g; 673*cdf0e10cSrcweir } 674*cdf0e10cSrcweir 675*cdf0e10cSrcweir foreach my $onefile ( reverse sort keys %{$allfiles} ) 676*cdf0e10cSrcweir { 677*cdf0e10cSrcweir if ( already_certified($onefile) ) 678*cdf0e10cSrcweir { 679*cdf0e10cSrcweir $infoline = "Already certified: Skipping file $onefile\n"; 680*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 681*cdf0e10cSrcweir next; 682*cdf0e10cSrcweir } 683*cdf0e10cSrcweir 684*cdf0e10cSrcweir my $counter = 1; 685*cdf0e10cSrcweir my $success = 0; 686*cdf0e10cSrcweir 687*cdf0e10cSrcweir while (( $counter <= $maxcounter ) && ( ! $success )) 688*cdf0e10cSrcweir { 689*cdf0e10cSrcweir if ( $counter > 1 ) { installer::logger::print_message( "\n\n... repeating file $onefile ...\n" ); } 690*cdf0e10cSrcweir if ( $cabinternal ) { installer::logger::print_message(" Signing: $onefile\n"); } 691*cdf0e10cSrcweir my $systemcall = "signtool.exe sign /f \"$pfxfilepath\" /p $pw $productname $url /t \"$timestampurl\" \"$onefile\""; 692*cdf0e10cSrcweir my $displaysystemcall = "signtool.exe sign /f \"$pfxfilepath\" /p ***** $productname $url /t \"$timestampurl\" \"$onefile\""; 693*cdf0e10cSrcweir $success = make_systemcall_with_warning($systemcall, $displaysystemcall); 694*cdf0e10cSrcweir $counter++; 695*cdf0e10cSrcweir } 696*cdf0e10cSrcweir 697*cdf0e10cSrcweir # Special check for cabinet files, that sometimes get damaged by signtool.exe 698*cdf0e10cSrcweir if (( $success ) && ( $onefile =~ /\.cab\s*$/ ) && ( ! $cabinternal )) 699*cdf0e10cSrcweir { 700*cdf0e10cSrcweir cabinet_cosistency_check($onefile, $followmeinfohash, $filenamehash, $lastsequencehash, $temppath); 701*cdf0e10cSrcweir } 702*cdf0e10cSrcweir 703*cdf0e10cSrcweir if ( ! $success ) 704*cdf0e10cSrcweir { 705*cdf0e10cSrcweir $fullsuccess = 0; 706*cdf0e10cSrcweir installer::exiter::exit_program("ERROR: Could not sign file: $onefile!", "sign_files"); 707*cdf0e10cSrcweir } 708*cdf0e10cSrcweir } 709*cdf0e10cSrcweir 710*cdf0e10cSrcweir return $fullsuccess; 711*cdf0e10cSrcweir} 712*cdf0e10cSrcweir 713*cdf0e10cSrcweir########################################################################## 714*cdf0e10cSrcweir# Lines in ddf files must not contain more than 256 characters 715*cdf0e10cSrcweir########################################################################## 716*cdf0e10cSrcweir 717*cdf0e10cSrcweirsub check_ddf_file 718*cdf0e10cSrcweir{ 719*cdf0e10cSrcweir my ( $ddffile, $ddffilename ) = @_; 720*cdf0e10cSrcweir 721*cdf0e10cSrcweir my $maxlength = 0; 722*cdf0e10cSrcweir my $maxline = 0; 723*cdf0e10cSrcweir my $linelength = 0; 724*cdf0e10cSrcweir my $linenumber = 0; 725*cdf0e10cSrcweir 726*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$ddffile}; $i++ ) 727*cdf0e10cSrcweir { 728*cdf0e10cSrcweir my $oneline = ${$ddffile}[$i]; 729*cdf0e10cSrcweir 730*cdf0e10cSrcweir $linelength = length($oneline); 731*cdf0e10cSrcweir $linenumber = $i + 1; 732*cdf0e10cSrcweir 733*cdf0e10cSrcweir if ( $linelength > 256 ) 734*cdf0e10cSrcweir { 735*cdf0e10cSrcweir installer::exiter::exit_program("ERROR \"$ddffilename\" line $linenumber: Lines in ddf files must not contain more than 256 characters!", "check_ddf_file"); 736*cdf0e10cSrcweir } 737*cdf0e10cSrcweir 738*cdf0e10cSrcweir if ( $linelength > $maxlength ) 739*cdf0e10cSrcweir { 740*cdf0e10cSrcweir $maxlength = $linelength; 741*cdf0e10cSrcweir $maxline = $linenumber; 742*cdf0e10cSrcweir } 743*cdf0e10cSrcweir } 744*cdf0e10cSrcweir 745*cdf0e10cSrcweir my $infoline = "Check of ddf file \"$ddffilename\": Maximum length \"$maxlength\" in line \"$maxline\" (allowed line length: 256 characters)\n"; 746*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 747*cdf0e10cSrcweir} 748*cdf0e10cSrcweir 749*cdf0e10cSrcweir################################################################# 750*cdf0e10cSrcweir# Setting the path, where the cab files are unpacked. 751*cdf0e10cSrcweir################################################################# 752*cdf0e10cSrcweir 753*cdf0e10cSrcweirsub get_cab_path 754*cdf0e10cSrcweir{ 755*cdf0e10cSrcweir my ($temppath) = @_; 756*cdf0e10cSrcweir 757*cdf0e10cSrcweir my $cabpath = "cabs_" . $$; 758*cdf0e10cSrcweir $cabpath = $temppath . $installer::globals::separator . $cabpath; 759*cdf0e10cSrcweir if ( ! -d $cabpath ) { installer::systemactions::create_directory($cabpath); } 760*cdf0e10cSrcweir 761*cdf0e10cSrcweir return $cabpath; 762*cdf0e10cSrcweir} 763*cdf0e10cSrcweir 764*cdf0e10cSrcweir################################################################# 765*cdf0e10cSrcweir# Setting the path, where the diff can happen. 766*cdf0e10cSrcweir################################################################# 767*cdf0e10cSrcweir 768*cdf0e10cSrcweirsub get_diff_path 769*cdf0e10cSrcweir{ 770*cdf0e10cSrcweir my ($temppath) = @_; 771*cdf0e10cSrcweir 772*cdf0e10cSrcweir my $diffpath = "diff_" . $$; 773*cdf0e10cSrcweir $diffpath = $temppath . $installer::globals::separator . $diffpath; 774*cdf0e10cSrcweir if ( ! -d $diffpath ) { installer::systemactions::create_directory($diffpath); } 775*cdf0e10cSrcweir 776*cdf0e10cSrcweir return $diffpath; 777*cdf0e10cSrcweir} 778*cdf0e10cSrcweir 779*cdf0e10cSrcweir################################################################# 780*cdf0e10cSrcweir# Exclude all cab files from the msi database. 781*cdf0e10cSrcweir################################################################# 782*cdf0e10cSrcweir 783*cdf0e10cSrcweirsub extract_cabs_from_database 784*cdf0e10cSrcweir{ 785*cdf0e10cSrcweir my ($msidatabase, $allcabfiles) = @_; 786*cdf0e10cSrcweir 787*cdf0e10cSrcweir installer::logger::include_header_into_logfile("Extracting cabs from msi database"); 788*cdf0e10cSrcweir 789*cdf0e10cSrcweir my $infoline = ""; 790*cdf0e10cSrcweir my $fullsuccess = 1; 791*cdf0e10cSrcweir my $msidb = "msidb.exe"; # Has to be in the path 792*cdf0e10cSrcweir 793*cdf0e10cSrcweir # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) 794*cdf0e10cSrcweir $msidatabase =~ s/\//\\\\/g; 795*cdf0e10cSrcweir 796*cdf0e10cSrcweir foreach my $onefile ( keys %{$allcabfiles} ) 797*cdf0e10cSrcweir { 798*cdf0e10cSrcweir my $systemcall = $msidb . " -d " . $msidatabase . " -x " . $onefile; 799*cdf0e10cSrcweir my $success = make_systemcall($systemcall, $systemcall); 800*cdf0e10cSrcweir if ( ! $success ) { $fullsuccess = 0; } 801*cdf0e10cSrcweir 802*cdf0e10cSrcweir # and removing the stream from the database 803*cdf0e10cSrcweir $systemcall = $msidb . " -d " . $msidatabase . " -k " . $onefile; 804*cdf0e10cSrcweir $success = make_systemcall($systemcall, $systemcall); 805*cdf0e10cSrcweir if ( ! $success ) { $fullsuccess = 0; } 806*cdf0e10cSrcweir } 807*cdf0e10cSrcweir 808*cdf0e10cSrcweir return $fullsuccess; 809*cdf0e10cSrcweir} 810*cdf0e10cSrcweir 811*cdf0e10cSrcweir################################################################# 812*cdf0e10cSrcweir# Include cab files into the msi database. 813*cdf0e10cSrcweir################################################################# 814*cdf0e10cSrcweir 815*cdf0e10cSrcweirsub include_cabs_into_database 816*cdf0e10cSrcweir{ 817*cdf0e10cSrcweir my ($msidatabase, $allcabfiles) = @_; 818*cdf0e10cSrcweir 819*cdf0e10cSrcweir installer::logger::include_header_into_logfile("Including cabs into msi database"); 820*cdf0e10cSrcweir 821*cdf0e10cSrcweir my $infoline = ""; 822*cdf0e10cSrcweir my $fullsuccess = 1; 823*cdf0e10cSrcweir my $msidb = "msidb.exe"; # Has to be in the path 824*cdf0e10cSrcweir 825*cdf0e10cSrcweir # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) 826*cdf0e10cSrcweir $msidatabase =~ s/\//\\\\/g; 827*cdf0e10cSrcweir 828*cdf0e10cSrcweir foreach my $onefile ( keys %{$allcabfiles} ) 829*cdf0e10cSrcweir { 830*cdf0e10cSrcweir my $systemcall = $msidb . " -d " . $msidatabase . " -a " . $onefile; 831*cdf0e10cSrcweir my $success = make_systemcall($systemcall, $systemcall); 832*cdf0e10cSrcweir if ( ! $success ) { $fullsuccess = 0; } 833*cdf0e10cSrcweir } 834*cdf0e10cSrcweir 835*cdf0e10cSrcweir return $fullsuccess; 836*cdf0e10cSrcweir} 837*cdf0e10cSrcweir 838*cdf0e10cSrcweir######################################################## 839*cdf0e10cSrcweir# Reading the order of the files inside the 840*cdf0e10cSrcweir# cabinet files. 841*cdf0e10cSrcweir######################################################## 842*cdf0e10cSrcweir 843*cdf0e10cSrcweirsub read_cab_file 844*cdf0e10cSrcweir{ 845*cdf0e10cSrcweir my ($cabfilename) = @_; 846*cdf0e10cSrcweir 847*cdf0e10cSrcweir installer::logger::print_message( "\n... reading cabinet file $cabfilename ...\n" ); 848*cdf0e10cSrcweir my $infoline = "Reading cabinet file $cabfilename\n"; 849*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 850*cdf0e10cSrcweir 851*cdf0e10cSrcweir my $systemcall = "cabarc.exe" . " L " . $cabfilename; 852*cdf0e10cSrcweir push(@logfile, "$systemcall\n"); 853*cdf0e10cSrcweir 854*cdf0e10cSrcweir my ($success, $fileorder) = execute_open_system_call($systemcall); 855*cdf0e10cSrcweir 856*cdf0e10cSrcweir my @allfiles = (); 857*cdf0e10cSrcweir 858*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$fileorder}; $i++ ) 859*cdf0e10cSrcweir { 860*cdf0e10cSrcweir my $line = ${$fileorder}[$i]; 861*cdf0e10cSrcweir if ( $line =~ /^\s*(.*?)\s+\d+\s+\d+\/\d+\/\d+\s+\d+\:\d+\:\d+\s+[\w-]+\s*$/ ) 862*cdf0e10cSrcweir { 863*cdf0e10cSrcweir my $filename = $1; 864*cdf0e10cSrcweir push(@allfiles, $filename); 865*cdf0e10cSrcweir } 866*cdf0e10cSrcweir } 867*cdf0e10cSrcweir 868*cdf0e10cSrcweir return \@allfiles; 869*cdf0e10cSrcweir} 870*cdf0e10cSrcweir 871*cdf0e10cSrcweir######################################################## 872*cdf0e10cSrcweir# Unpacking a cabinet file. 873*cdf0e10cSrcweir######################################################## 874*cdf0e10cSrcweir 875*cdf0e10cSrcweirsub unpack_cab_file 876*cdf0e10cSrcweir{ 877*cdf0e10cSrcweir my ($cabfilename, $temppath) = @_; 878*cdf0e10cSrcweir 879*cdf0e10cSrcweir installer::logger::print_message( "\n... unpacking cabinet file $cabfilename ...\n" ); 880*cdf0e10cSrcweir my $infoline = "Unpacking cabinet file $cabfilename\n"; 881*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 882*cdf0e10cSrcweir 883*cdf0e10cSrcweir my $dirname = $cabfilename; 884*cdf0e10cSrcweir $dirname =~ s/\.cab\s*$//; 885*cdf0e10cSrcweir my $workingpath = $temppath . $installer::globals::separator . "unpack_". $dirname . "_" . $$; 886*cdf0e10cSrcweir if ( ! -d $workingpath ) { installer::systemactions::create_directory($workingpath); } 887*cdf0e10cSrcweir 888*cdf0e10cSrcweir # changing into unpack directory 889*cdf0e10cSrcweir my $from = cwd(); 890*cdf0e10cSrcweir chdir($workingpath); 891*cdf0e10cSrcweir 892*cdf0e10cSrcweir my $fullcabfilename = $from . $installer::globals::separator . $cabfilename; 893*cdf0e10cSrcweir 894*cdf0e10cSrcweir if( $^O =~ /cygwin/i ) 895*cdf0e10cSrcweir { 896*cdf0e10cSrcweir $fullcabfilename = qx{cygpath -w "$fullcabfilename"}; 897*cdf0e10cSrcweir $fullcabfilename =~ s/\\/\\\\/g; 898*cdf0e10cSrcweir $fullcabfilename =~ s/\s*$//g; 899*cdf0e10cSrcweir } 900*cdf0e10cSrcweir 901*cdf0e10cSrcweir my $systemcall = "cabarc.exe" . " -p X " . $fullcabfilename; 902*cdf0e10cSrcweir $success = make_systemcall($systemcall, $systemcall); 903*cdf0e10cSrcweir if ( ! $success ) { installer::exiter::exit_program("ERROR: Could not unpack cabinet file: $fullcabfilename!", "unpack_cab_file"); } 904*cdf0e10cSrcweir 905*cdf0e10cSrcweir # returning to directory 906*cdf0e10cSrcweir chdir($from); 907*cdf0e10cSrcweir 908*cdf0e10cSrcweir return $workingpath; 909*cdf0e10cSrcweir} 910*cdf0e10cSrcweir 911*cdf0e10cSrcweir######################################################## 912*cdf0e10cSrcweir# Returning the header of a ddf file. 913*cdf0e10cSrcweir######################################################## 914*cdf0e10cSrcweir 915*cdf0e10cSrcweirsub get_ddf_file_header 916*cdf0e10cSrcweir{ 917*cdf0e10cSrcweir my ($ddffileref, $cabinetfile, $installdir) = @_; 918*cdf0e10cSrcweir 919*cdf0e10cSrcweir my $oneline; 920*cdf0e10cSrcweir my $compressionlevel = 2; 921*cdf0e10cSrcweir 922*cdf0e10cSrcweir if( $^O =~ /cygwin/i ) 923*cdf0e10cSrcweir { 924*cdf0e10cSrcweir $installdir = qx{cygpath -w "$installdir"}; 925*cdf0e10cSrcweir $installdir =~ s/\s*$//g; 926*cdf0e10cSrcweir } 927*cdf0e10cSrcweir 928*cdf0e10cSrcweir $oneline = ".Set CabinetName1=" . $cabinetfile . "\n"; 929*cdf0e10cSrcweir push(@{$ddffileref} ,$oneline); 930*cdf0e10cSrcweir $oneline = ".Set ReservePerCabinetSize=128\n"; # This reserves space for a digital signature. 931*cdf0e10cSrcweir push(@{$ddffileref} ,$oneline); 932*cdf0e10cSrcweir $oneline = ".Set MaxDiskSize=2147483648\n"; # This allows the .cab file to get a size of 2 GB. 933*cdf0e10cSrcweir push(@{$ddffileref} ,$oneline); 934*cdf0e10cSrcweir $oneline = ".Set CompressionType=LZX\n"; 935*cdf0e10cSrcweir push(@{$ddffileref} ,$oneline); 936*cdf0e10cSrcweir $oneline = ".Set Compress=ON\n"; 937*cdf0e10cSrcweir push(@{$ddffileref} ,$oneline); 938*cdf0e10cSrcweir $oneline = ".Set CompressionLevel=$compressionlevel\n"; 939*cdf0e10cSrcweir push(@{$ddffileref} ,$oneline); 940*cdf0e10cSrcweir $oneline = ".Set Cabinet=ON\n"; 941*cdf0e10cSrcweir push(@{$ddffileref} ,$oneline); 942*cdf0e10cSrcweir $oneline = ".Set DiskDirectoryTemplate=" . $installdir . "\n"; 943*cdf0e10cSrcweir push(@{$ddffileref} ,$oneline); 944*cdf0e10cSrcweir} 945*cdf0e10cSrcweir 946*cdf0e10cSrcweir######################################################## 947*cdf0e10cSrcweir# Writing content into ddf file. 948*cdf0e10cSrcweir######################################################## 949*cdf0e10cSrcweir 950*cdf0e10cSrcweirsub put_all_files_into_ddffile 951*cdf0e10cSrcweir{ 952*cdf0e10cSrcweir my ($ddffile, $allfiles, $workingpath) = @_; 953*cdf0e10cSrcweir 954*cdf0e10cSrcweir $workingpath =~ s/\//\\/g; 955*cdf0e10cSrcweir 956*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$allfiles}; $i++ ) 957*cdf0e10cSrcweir { 958*cdf0e10cSrcweir my $filename = ${$allfiles}[$i]; 959*cdf0e10cSrcweir if( $^O =~ /cygwin/i ) { $filename =~ s/\//\\/g; } # Backslash for Cygwin! 960*cdf0e10cSrcweir if ( ! -f $filename ) { installer::exiter::exit_program("ERROR: Could not find file: $filename!", "put_all_files_into_ddffile"); } 961*cdf0e10cSrcweir my $infoline = "\"" . $filename . "\"" . " " . ${$allfiles}[$i] . "\n"; 962*cdf0e10cSrcweir push( @{$ddffile}, $infoline); 963*cdf0e10cSrcweir } 964*cdf0e10cSrcweir} 965*cdf0e10cSrcweir 966*cdf0e10cSrcweir######################################################## 967*cdf0e10cSrcweir# Packing a cabinet file. 968*cdf0e10cSrcweir######################################################## 969*cdf0e10cSrcweir 970*cdf0e10cSrcweirsub do_pack_cab_file 971*cdf0e10cSrcweir{ 972*cdf0e10cSrcweir my ($cabfilename, $allfiles, $workingpath, $temppath) = @_; 973*cdf0e10cSrcweir 974*cdf0e10cSrcweir installer::logger::print_message( "\n... packing cabinet file $cabfilename ...\n" ); 975*cdf0e10cSrcweir my $infoline = "Packing cabinet file $cabfilename\n"; 976*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 977*cdf0e10cSrcweir 978*cdf0e10cSrcweir if ( -f $cabfilename ) { unlink($cabfilename); } # removing cab file 979*cdf0e10cSrcweir if ( -f $cabfilename ) { installer::exiter::exit_program("ERROR: Failed to remove file: $cabfilename!", "do_pack_cab_file"); } 980*cdf0e10cSrcweir 981*cdf0e10cSrcweir # generate ddf file for makecab.exe 982*cdf0e10cSrcweir my @ddffile = (); 983*cdf0e10cSrcweir 984*cdf0e10cSrcweir my $dirname = $cabfilename; 985*cdf0e10cSrcweir $dirname =~ s/\.cab\s*$//; 986*cdf0e10cSrcweir my $ddfpath = $temppath . $installer::globals::separator . "ddf_". $dirname . "_" . $$; 987*cdf0e10cSrcweir 988*cdf0e10cSrcweir my $ddffilename = $cabfilename; 989*cdf0e10cSrcweir $ddffilename =~ s/.cab/.ddf/; 990*cdf0e10cSrcweir $ddffilename = $ddfpath . $installer::globals::separator . $ddffilename; 991*cdf0e10cSrcweir 992*cdf0e10cSrcweir if ( ! -d $ddfpath ) { installer::systemactions::create_directory($ddfpath); } 993*cdf0e10cSrcweir 994*cdf0e10cSrcweir my $from = cwd(); 995*cdf0e10cSrcweir 996*cdf0e10cSrcweir chdir($workingpath); # changing into the directory with the unpacked files 997*cdf0e10cSrcweir 998*cdf0e10cSrcweir get_ddf_file_header(\@ddffile, $cabfilename, $from); 999*cdf0e10cSrcweir put_all_files_into_ddffile(\@ddffile, $allfiles, $workingpath); 1000*cdf0e10cSrcweir # lines in ddf files must not be longer than 256 characters 1001*cdf0e10cSrcweir check_ddf_file(\@ddffile, $ddffilename); 1002*cdf0e10cSrcweir 1003*cdf0e10cSrcweir installer::files::save_file($ddffilename, \@ddffile); 1004*cdf0e10cSrcweir 1005*cdf0e10cSrcweir if( $^O =~ /cygwin/i ) 1006*cdf0e10cSrcweir { 1007*cdf0e10cSrcweir $ddffilename = qx{cygpath -w "$ddffilename"}; 1008*cdf0e10cSrcweir $ddffilename =~ s/\\/\\\\/g; 1009*cdf0e10cSrcweir $ddffilename =~ s/\s*$//g; 1010*cdf0e10cSrcweir } 1011*cdf0e10cSrcweir 1012*cdf0e10cSrcweir my $systemcall = "makecab.exe /V1 /F " . $ddffilename; 1013*cdf0e10cSrcweir my $success = make_systemcall($systemcall, $systemcall); 1014*cdf0e10cSrcweir if ( ! $success ) { installer::exiter::exit_program("ERROR: Could not pack cabinet file!", "do_pack_cab_file"); } 1015*cdf0e10cSrcweir 1016*cdf0e10cSrcweir chdir($from); 1017*cdf0e10cSrcweir 1018*cdf0e10cSrcweir return ($success); 1019*cdf0e10cSrcweir} 1020*cdf0e10cSrcweir 1021*cdf0e10cSrcweir######################################################## 1022*cdf0e10cSrcweir# Extraction the file extension from a file 1023*cdf0e10cSrcweir######################################################## 1024*cdf0e10cSrcweir 1025*cdf0e10cSrcweirsub get_extension 1026*cdf0e10cSrcweir{ 1027*cdf0e10cSrcweir my ( $file ) = @_; 1028*cdf0e10cSrcweir 1029*cdf0e10cSrcweir my $extension = ""; 1030*cdf0e10cSrcweir 1031*cdf0e10cSrcweir if ( $file =~ /^\s*(.*)\.(\w+?)\s*$/ ) { $extension = $2; } 1032*cdf0e10cSrcweir 1033*cdf0e10cSrcweir return $extension; 1034*cdf0e10cSrcweir} 1035*cdf0e10cSrcweir 1036*cdf0e10cSrcweir######################################################## 1037*cdf0e10cSrcweir# Checking, if a file already contains a certificate. 1038*cdf0e10cSrcweir# This must not be overwritten. 1039*cdf0e10cSrcweir######################################################## 1040*cdf0e10cSrcweir 1041*cdf0e10cSrcweirsub already_certified 1042*cdf0e10cSrcweir{ 1043*cdf0e10cSrcweir my ( $filename ) = @_; 1044*cdf0e10cSrcweir 1045*cdf0e10cSrcweir my $success = 1; 1046*cdf0e10cSrcweir my $is_certified = 0; 1047*cdf0e10cSrcweir 1048*cdf0e10cSrcweir my $systemcall = "signtool.exe verify /q /pa \"$filename\""; 1049*cdf0e10cSrcweir my $returnvalue = system($systemcall); 1050*cdf0e10cSrcweir 1051*cdf0e10cSrcweir if ( $returnvalue ) { $success = 0; } 1052*cdf0e10cSrcweir 1053*cdf0e10cSrcweir # my $success = make_systemcall($systemcall, $systemcall); 1054*cdf0e10cSrcweir 1055*cdf0e10cSrcweir if ( $success ) 1056*cdf0e10cSrcweir { 1057*cdf0e10cSrcweir $is_certified = 1; 1058*cdf0e10cSrcweir installer::logger::print_message( "... already certified -> skipping $filename ...\n" ); 1059*cdf0e10cSrcweir } 1060*cdf0e10cSrcweir 1061*cdf0e10cSrcweir return $is_certified; 1062*cdf0e10cSrcweir} 1063*cdf0e10cSrcweir 1064*cdf0e10cSrcweir######################################################## 1065*cdf0e10cSrcweir# Signing the files, that are included into 1066*cdf0e10cSrcweir# cabinet files. 1067*cdf0e10cSrcweir######################################################## 1068*cdf0e10cSrcweir 1069*cdf0e10cSrcweirsub sign_files_in_cabinet_files 1070*cdf0e10cSrcweir{ 1071*cdf0e10cSrcweir my ( $followmeinfohash, $allcabfiles, $pw, $temppath ) = @_; 1072*cdf0e10cSrcweir 1073*cdf0e10cSrcweir my $complete_success = 1; 1074*cdf0e10cSrcweir my $from = cwd(); 1075*cdf0e10cSrcweir 1076*cdf0e10cSrcweir foreach my $cabfilename ( keys %{$allcabfiles} ) 1077*cdf0e10cSrcweir { 1078*cdf0e10cSrcweir my $success = 1; 1079*cdf0e10cSrcweir 1080*cdf0e10cSrcweir # saving order of files in cab file 1081*cdf0e10cSrcweir my $fileorder = read_cab_file($cabfilename); 1082*cdf0e10cSrcweir 1083*cdf0e10cSrcweir # unpack into $working path 1084*cdf0e10cSrcweir my $workingpath = unpack_cab_file($cabfilename, $temppath); 1085*cdf0e10cSrcweir 1086*cdf0e10cSrcweir chdir($workingpath); 1087*cdf0e10cSrcweir 1088*cdf0e10cSrcweir # sign files 1089*cdf0e10cSrcweir my %allfileshash = (); 1090*cdf0e10cSrcweir foreach my $onefile ( @{$fileorder} ) 1091*cdf0e10cSrcweir { 1092*cdf0e10cSrcweir my $extension = get_extension($onefile); 1093*cdf0e10cSrcweir if ( exists( $installer::globals::sign_extensions{$extension} ) ) 1094*cdf0e10cSrcweir { 1095*cdf0e10cSrcweir $allfileshash{$onefile} = 1; 1096*cdf0e10cSrcweir } 1097*cdf0e10cSrcweir } 1098*cdf0e10cSrcweir $success = sign_files($followmeinfohash, \%allfileshash, $pw, 1, 0, 0, $temppath); 1099*cdf0e10cSrcweir if ( ! $success ) { $complete_success = 0; } 1100*cdf0e10cSrcweir 1101*cdf0e10cSrcweir chdir($from); 1102*cdf0e10cSrcweir 1103*cdf0e10cSrcweir # pack into new directory 1104*cdf0e10cSrcweir do_pack_cab_file($cabfilename, $fileorder, $workingpath, $temppath); 1105*cdf0e10cSrcweir } 1106*cdf0e10cSrcweir 1107*cdf0e10cSrcweir return $complete_success; 1108*cdf0e10cSrcweir} 1109*cdf0e10cSrcweir 1110*cdf0e10cSrcweir######################################################## 1111*cdf0e10cSrcweir# Comparing the content of two directories. 1112*cdf0e10cSrcweir# Only filesize is compared. 1113*cdf0e10cSrcweir######################################################## 1114*cdf0e10cSrcweir 1115*cdf0e10cSrcweirsub compare_directories 1116*cdf0e10cSrcweir{ 1117*cdf0e10cSrcweir my ( $dir1, $dir2, $files ) = @_; 1118*cdf0e10cSrcweir 1119*cdf0e10cSrcweir $dir1 =~ s/\\\s*//; 1120*cdf0e10cSrcweir $dir2 =~ s/\\\s*//; 1121*cdf0e10cSrcweir $dir1 =~ s/\/\s*//; 1122*cdf0e10cSrcweir $dir2 =~ s/\/\s*//; 1123*cdf0e10cSrcweir 1124*cdf0e10cSrcweir my $infoline = "Comparing directories: $dir1 and $dir2\n"; 1125*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 1126*cdf0e10cSrcweir 1127*cdf0e10cSrcweir foreach my $onefile ( @{$files} ) 1128*cdf0e10cSrcweir { 1129*cdf0e10cSrcweir my $file1 = $dir1 . $installer::globals::separator . $onefile; 1130*cdf0e10cSrcweir my $file2 = $dir2 . $installer::globals::separator . $onefile; 1131*cdf0e10cSrcweir 1132*cdf0e10cSrcweir if ( ! -f $file1 ) { installer::exiter::exit_program("ERROR: Missing file : $file1!", "compare_directories"); } 1133*cdf0e10cSrcweir if ( ! -f $file2 ) { installer::exiter::exit_program("ERROR: Missing file : $file2!", "compare_directories"); } 1134*cdf0e10cSrcweir 1135*cdf0e10cSrcweir my $size1 = -s $file1; 1136*cdf0e10cSrcweir my $size2 = -s $file2; 1137*cdf0e10cSrcweir 1138*cdf0e10cSrcweir $infoline = "Comparing files: $file1 ($size1) and $file2 ($size2)\n"; 1139*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 1140*cdf0e10cSrcweir 1141*cdf0e10cSrcweir if ( $size1 != $size2 ) 1142*cdf0e10cSrcweir { 1143*cdf0e10cSrcweir installer::exiter::exit_program("ERROR: File defect after copy (different size) $file1 ($size1 bytes) and $file2 ($size2 bytes)!", "compare_directories"); 1144*cdf0e10cSrcweir } 1145*cdf0e10cSrcweir } 1146*cdf0e10cSrcweir} 1147*cdf0e10cSrcweir 1148*cdf0e10cSrcweir######################################################## 1149*cdf0e10cSrcweir# Signing an existing Windows installation set. 1150*cdf0e10cSrcweir######################################################## 1151*cdf0e10cSrcweir 1152*cdf0e10cSrcweirsub sign_install_set 1153*cdf0e10cSrcweir{ 1154*cdf0e10cSrcweir my ($followmeinfohash, $make_copy, $temppath) = @_; 1155*cdf0e10cSrcweir 1156*cdf0e10cSrcweir my $installsetpath = $followmeinfohash->{'finalinstalldir'}; 1157*cdf0e10cSrcweir 1158*cdf0e10cSrcweir installer::logger::include_header_into_logfile("Start: Signing installation set $installsetpath"); 1159*cdf0e10cSrcweir 1160*cdf0e10cSrcweir my $complete_success = 1; 1161*cdf0e10cSrcweir my $success = 1; 1162*cdf0e10cSrcweir 1163*cdf0e10cSrcweir my $infoline = "Signing installation set in $installsetpath\n"; 1164*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 1165*cdf0e10cSrcweir 1166*cdf0e10cSrcweir # check required files. 1167*cdf0e10cSrcweir if ( ! $installer::globals::signfiles_checked ) { check_system_path(); } 1168*cdf0e10cSrcweir 1169*cdf0e10cSrcweir # get cerficate information 1170*cdf0e10cSrcweir my $pw = get_pw($installer::globals::pwfile); 1171*cdf0e10cSrcweir 1172*cdf0e10cSrcweir # making a copy of the installation set, if required 1173*cdf0e10cSrcweir if ( $make_copy ) { $installsetpath = copy_install_set($installsetpath); } 1174*cdf0e10cSrcweir else { $installsetpath = rename_install_set($installsetpath); } 1175*cdf0e10cSrcweir 1176*cdf0e10cSrcweir # collecting all files in the installation set 1177*cdf0e10cSrcweir my ($allcabfiles, $allfiles, $msidatabase, $contains_external_cabfiles, $contains_msidatabase, $sourcefiles) = analyze_installset_content($installsetpath); 1178*cdf0e10cSrcweir 1179*cdf0e10cSrcweir if ( $make_copy ) { compare_directories($installsetpath, $followmeinfohash->{'finalinstalldir'}, $sourcefiles); } 1180*cdf0e10cSrcweir 1181*cdf0e10cSrcweir # changing into installation set 1182*cdf0e10cSrcweir my $from = cwd(); 1183*cdf0e10cSrcweir my $fullmsidatabase = $installsetpath . $installer::globals::separator . $msidatabase; 1184*cdf0e10cSrcweir 1185*cdf0e10cSrcweir if( $^O =~ /cygwin/i ) 1186*cdf0e10cSrcweir { 1187*cdf0e10cSrcweir $fullmsidatabase = qx{cygpath -w "$fullmsidatabase"}; 1188*cdf0e10cSrcweir $fullmsidatabase =~ s/\\/\\\\/g; 1189*cdf0e10cSrcweir $fullmsidatabase =~ s/\s*$//g; 1190*cdf0e10cSrcweir } 1191*cdf0e10cSrcweir 1192*cdf0e10cSrcweir chdir($installsetpath); 1193*cdf0e10cSrcweir 1194*cdf0e10cSrcweir if ( $contains_msidatabase ) 1195*cdf0e10cSrcweir { 1196*cdf0e10cSrcweir # exclude media table from msi database and get all diskids. 1197*cdf0e10cSrcweir my ( $cabfilehash, $filenamehash, $lastsequencehash ) = collect_diskid_from_media_table($msidatabase, $followmeinfohash->{'languagestring'}); 1198*cdf0e10cSrcweir 1199*cdf0e10cSrcweir # Check, if there are internal cab files 1200*cdf0e10cSrcweir my ( $contains_internal_cabfiles, $all_internal_cab_files) = check_for_internal_cabfiles($cabfilehash); 1201*cdf0e10cSrcweir 1202*cdf0e10cSrcweir if ( $contains_internal_cabfiles ) 1203*cdf0e10cSrcweir { 1204*cdf0e10cSrcweir my $cabpath = get_cab_path($temppath); 1205*cdf0e10cSrcweir chdir($cabpath); 1206*cdf0e10cSrcweir 1207*cdf0e10cSrcweir # Exclude all cabinet files from database 1208*cdf0e10cSrcweir $success = extract_cabs_from_database($fullmsidatabase, $all_internal_cab_files); 1209*cdf0e10cSrcweir if ( ! $success ) { $complete_success = 0; } 1210*cdf0e10cSrcweir 1211*cdf0e10cSrcweir if ( $installer::globals::internal_cabinet_signing ) { sign_files_in_cabinet_files($followmeinfohash, $all_internal_cab_files, $pw, $temppath); } 1212*cdf0e10cSrcweir 1213*cdf0e10cSrcweir $success = sign_files($followmeinfohash, $all_internal_cab_files, $pw, 0, $filenamehash, $lastsequencehash, $temppath); 1214*cdf0e10cSrcweir if ( ! $success ) { $complete_success = 0; } 1215*cdf0e10cSrcweir $success = msicert_database($fullmsidatabase, $all_internal_cab_files, $cabfilehash, 1); 1216*cdf0e10cSrcweir if ( ! $success ) { $complete_success = 0; } 1217*cdf0e10cSrcweir 1218*cdf0e10cSrcweir # Include all cabinet files into database 1219*cdf0e10cSrcweir $success = include_cabs_into_database($fullmsidatabase, $all_internal_cab_files); 1220*cdf0e10cSrcweir if ( ! $success ) { $complete_success = 0; } 1221*cdf0e10cSrcweir chdir($installsetpath); 1222*cdf0e10cSrcweir } 1223*cdf0e10cSrcweir 1224*cdf0e10cSrcweir # Warning: There might be a problem with very big cabinet files 1225*cdf0e10cSrcweir # signing all external cab files first 1226*cdf0e10cSrcweir if ( $contains_external_cabfiles ) 1227*cdf0e10cSrcweir { 1228*cdf0e10cSrcweir if ( $installer::globals::internal_cabinet_signing ) { sign_files_in_cabinet_files($followmeinfohash, $allcabfiles, $pw, $temppath); } 1229*cdf0e10cSrcweir 1230*cdf0e10cSrcweir $success = sign_files($followmeinfohash, $allcabfiles, $pw, 0, $filenamehash, $lastsequencehash, $temppath); 1231*cdf0e10cSrcweir if ( ! $success ) { $complete_success = 0; } 1232*cdf0e10cSrcweir $success = msicert_database($msidatabase, $allcabfiles, $cabfilehash, 0); 1233*cdf0e10cSrcweir if ( ! $success ) { $complete_success = 0; } 1234*cdf0e10cSrcweir } 1235*cdf0e10cSrcweir } 1236*cdf0e10cSrcweir 1237*cdf0e10cSrcweir # finally all other files can be signed 1238*cdf0e10cSrcweir $success = sign_files($followmeinfohash, $allfiles, $pw, 0, 0, 0, $temppath); 1239*cdf0e10cSrcweir if ( ! $success ) { $complete_success = 0; } 1240*cdf0e10cSrcweir 1241*cdf0e10cSrcweir # and changing back 1242*cdf0e10cSrcweir chdir($from); 1243*cdf0e10cSrcweir 1244*cdf0e10cSrcweir installer::logger::include_header_into_logfile("End: Signing installation set $installsetpath"); 1245*cdf0e10cSrcweir 1246*cdf0e10cSrcweir return ($installsetpath); 1247*cdf0e10cSrcweir} 1248*cdf0e10cSrcweir 1249*cdf0e10cSrcweir1; 1250