Update to m13
[ooovba.git] / solenv / bin / modules / installer / windows / sign.pm
blob250986daed39cd947cd34b55f7a12c7498752d3e
1 #*************************************************************************
3 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 #
5 # Copyright 2008 by Sun Microsystems, Inc.
7 # OpenOffice.org - a multi-platform office productivity suite
9 # $RCSfile: binary.pm,v $
11 # $Revision: 1.5 $
13 # This file is part of OpenOffice.org.
15 # OpenOffice.org is free software: you can redistribute it and/or modify
16 # it under the terms of the GNU Lesser General Public License version 3
17 # only, as published by the Free Software Foundation.
19 # OpenOffice.org is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU Lesser General Public License version 3 for more details
23 # (a copy is included in the LICENSE file that accompanied this code).
25 # You should have received a copy of the GNU Lesser General Public License
26 # version 3 along with OpenOffice.org. If not, see
27 # <http://www.openoffice.org/license.html>
28 # for a copy of the LGPLv3 License.
30 #*************************************************************************
32 package installer::windows::sign;
34 use Cwd;
35 use installer::converter;
36 use installer::existence;
37 use installer::files;
38 use installer::globals;
39 use installer::scriptitems;
40 use installer::worker;
41 use installer::windows::admin;
43 ########################################################
44 # Copying an existing Windows installation set.
45 ########################################################
47 sub copy_install_set
49 my ( $installsetpath ) = @_;
51 installer::logger::include_header_into_logfile("Start: Copying installation set $installsetpath");
53 my $infoline = "";
55 my $dirname = $installsetpath;
56 installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$dirname);
58 my $path = $installsetpath;
59 installer::pathanalyzer::get_path_from_fullqualifiedname(\$path);
61 $path =~ s/\Q$installer::globals::separator\E\s*$//;
63 if ( $dirname =~ /\./ ) { $dirname =~ s/\./_signed_inprogress./; }
64 else { $dirname = $dirname . "_signed_inprogress"; }
66 my $newpath = $path . $installer::globals::separator . $dirname;
67 my $removepath = $newpath;
68 $removepath =~ s/_inprogress/_witherror/;
70 if ( -d $newpath ) { installer::systemactions::remove_complete_directory($newpath, 1); }
71 if ( -d $removepath ) { installer::systemactions::remove_complete_directory($removepath, 1); }
73 $infoline = "Copy installation set from $installsetpath to $newpath\n";
74 push( @installer::globals::logfileinfo, $infoline);
76 $installsetpath = installer::systemactions::copy_complete_directory($installsetpath, $newpath);
78 installer::logger::include_header_into_logfile("End: Copying installation set $installsetpath");
80 return $newpath;
83 ########################################################
84 # Renaming an existing Windows installation set.
85 ########################################################
87 sub rename_install_set
89 my ( $installsetpath ) = @_;
91 my $infoline = "";
93 my $dirname = $installsetpath;
94 installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$dirname);
96 my $path = $installsetpath;
97 installer::pathanalyzer::get_path_from_fullqualifiedname(\$path);
99 $path =~ s/\Q$installer::globals::separator\E\s*$//;
101 if ( $dirname =~ /\./ ) { $dirname =~ s/\./_inprogress./; }
102 else { $dirname = $dirname . "_inprogress"; }
104 my $newpath = $path . $installer::globals::separator . $dirname;
105 my $removepath = $newpath;
106 $removepath =~ s/_inprogress/_witherror/;
108 if ( -d $newpath ) { installer::systemactions::remove_complete_directory($newpath, 1); }
109 if ( -d $removepath ) { installer::systemactions::remove_complete_directory($removepath, 1); }
111 $installsetpath = installer::systemactions::rename_directory($installsetpath, $newpath);
113 return $newpath;
116 #########################################################
117 # Checking the local system
118 # Checking existence of needed files in include path
119 #########################################################
121 sub check_system_path
123 # The following files have to be found in the environment variable PATH
124 # Only, if \"-sign\" is used.
125 # Windows : "msicert.exe", "msidb.exe", "signtool.exe"
127 my @needed_files_in_path = ("msicert.exe", "msidb.exe", "signtool.exe");
129 my $onefile;
130 my $error = 0;
131 my $pathvariable = $ENV{'PATH'};
132 my $local_pathseparator = $installer::globals::pathseparator;
134 if( $^O =~ /cygwin/i )
135 { # When using cygwin's perl the PATH variable is POSIX style and ...
136 $pathvariable = qx{cygpath -mp "$pathvariable"} ;
137 # has to be converted to DOS style for further use.
138 $local_pathseparator = ';';
141 my $patharrayref = installer::converter::convert_stringlist_into_array(\$pathvariable, $local_pathseparator);
143 $installer::globals::patharray = $patharrayref;
145 foreach my $onefile ( @needed_files_in_path )
147 installer::logger::print_message( "...... searching $onefile ..." );
149 my $fileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath_classic(\$onefile, $patharrayref , 0);
151 if ( $$fileref eq "" )
153 $error = 1;
154 installer::logger::print_error( "$onefile not found\n" );
156 else
158 installer::logger::print_message( "\tFound: $$fileref\n" );
162 $installer::globals::signfiles_checked = 1;
164 if ( $error ) { installer::exiter::exit_program("ERROR: Could not find all needed files in path!", "check_system_path"); }
167 ######################################################
168 # Making systemcall
169 ######################################################
171 sub make_systemcall
173 my ($systemcall, $displaysystemcall) = @_;
175 installer::logger::print_message( "... $displaysystemcall ...\n" );
177 my $success = 1;
178 my $returnvalue = system($systemcall);
180 my $infoline = "Systemcall: $displaysystemcall\n";
181 push( @installer::globals::logfileinfo, $infoline);
183 if ($returnvalue)
185 $infoline = "ERROR: Could not execute \"$displaysystemcall\"!\n";
186 push( @installer::globals::logfileinfo, $infoline);
187 $success = 0;
189 else
191 $infoline = "Success: Executed \"$displaysystemcall\" successfully!\n";
192 push( @installer::globals::logfileinfo, $infoline);
195 return $success;
198 ########################################################
199 # Reading first line of pw file.
200 ########################################################
202 sub get_pw
204 my ( $file ) = @_;
206 my $filecontent = installer::files::read_file($file);
208 my $pw = ${$filecontent}[0];
209 $pw =~ s/^\s*//;
210 $pw =~ s/\s*$//;
212 return $pw;
215 ########################################################
216 # Counting the keys of a hash.
217 ########################################################
219 sub get_hash_count
221 my ($hashref) = @_;
223 my $counter = 0;
225 foreach my $key ( keys %{$hashref} ) { $counter++; }
227 return $counter;
230 ############################################################
231 # Collect all DiskIds to the corresponding cabinet files.
232 ############################################################
234 sub analyze_media_file
236 my ($filecontent) = @_;
238 my %diskidhash = ();
240 for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
242 if ( $i < 3 ) { next; }
244 if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ )
246 my $diskid = $1;
247 my $cabfile = $4;
249 $diskidhash{$cabfile} = $diskid;
253 return \%diskidhash;
256 ########################################################
257 # Collect all DiskIds from database table "Media".
258 ########################################################
260 sub collect_diskid
262 my ($msidatabase, $languagestring) = @_;
264 # creating working directory
265 my $workdir = installer::systemactions::create_directories("media", \$languagestring);
266 installer::windows::admin::extract_tables_from_pcpfile($msidatabase, $workdir, "Media");
268 # Reading tables
269 my $filename = $workdir . $installer::globals::separator . "Media.idt";
270 if ( ! -f $filename ) { installer::exiter::exit_program("ERROR: Could not find required file: $filename !", "collect_diskid"); }
271 my $filecontent = installer::files::read_file($filename);
272 my $diskidhash = analyze_media_file($filecontent);
274 return $diskidhash;
277 ########################################################
278 # Collecting all files in an installation set.
279 ########################################################
281 sub analyze_installset_content
283 my ( $installsetpath ) = @_;
285 my @sourcefiles = ();
286 my $pathstring = "";
287 installer::systemactions::read_complete_directory($installsetpath, $pathstring, \@sourcefiles);
289 if ( ! ( $#sourcefiles > -1 )) { installer::exiter::exit_program("ERROR: No file in installation set. Path: $installsetpath !", "analyze_installset_content"); }
291 my %allcabfileshash = ();
292 my %allmsidatabaseshash = ();
293 my %allfileshash = ();
294 my $contains_cab_file = 0;
295 my $msidatabase = "";
297 for ( my $j = 0; $j <= $#sourcefiles; $j++ )
299 if ( $sourcefiles[$j] =~ /\.cab\s*$/ ) { $allcabfileshash{$sourcefiles[$j]} = 1; }
300 else
302 if ( $sourcefiles[$j] =~ /instmsi\w+.exe\s*$/ ) { next; } # no signing of instmsia.exe and instmsiw.exe
303 if ( $sourcefiles[$j] =~ /vcredist_x86\.exe\s*$/ ) { next; } # no signing of vcredist_x86.exe
304 if ( $sourcefiles[$j] =~ /jre[-\w]+.exe\s*$/ ) { next; } # no signing of java executable
305 if ( $sourcefiles[$j] =~ /\.txt\s*$/ ) { next; }
306 if ( $sourcefiles[$j] =~ /\.html\s*$/ ) { next; }
307 if ( $sourcefiles[$j] =~ /\.ini\s*$/ ) { next; }
308 if ( $sourcefiles[$j] =~ /\.msi\s*$/ )
310 if ( $msidatabase eq "" ) { $msidatabase = $sourcefiles[$j]; }
311 else { installer::exiter::exit_program("ERROR: There is more than one msi database in installation set. Path: $installsetpath !", "analyze_installset_content"); }
313 $allfileshash{$sourcefiles[$j]} = 1;
317 # Is there at least one cab file in the installation set?
318 my $cabcounter = get_hash_count(\%allcabfileshash);
319 if ( $cabcounter > 0 ) { $contains_cab_file = 1; }
321 # How about a cab file without a msi database?
322 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"); }
324 return (\%allcabfileshash, \%allfileshash, $msidatabase, $contains_cab_file);
327 ########################################################
328 # Adding content of external cabinet files into the
329 # msi database
330 ########################################################
332 sub msicert_database
334 my ($msidatabase, $allcabfiles, $languagestring) = @_;
336 # exclude media table from msi database and get all diskids.
337 my $cabfilehash = collect_diskid($msidatabase, $languagestring);
339 my $fullsuccess = 1;
341 foreach my $cabfile ( keys %{$allcabfiles} )
343 if ( ! exists($cabfilehash->{$cabfile}) ) { installer::exiter::exit_program("ERROR: Could not determine DiskId from media table for cabinet file \"$cabfile\" !", "msicert_database"); }
344 my $diskid = $cabfilehash->{$cabfile};
345 my $systemcall = "msicert.exe -d $msidatabase -m $diskid -c $cabfile -h";
346 $success = make_systemcall($systemcall, $systemcall);
347 if ( ! $success ) { $fullsuccess = 0; }
350 return $fullsuccess;
353 ########################################################
354 # Signing a list of files
355 ########################################################
357 sub sign_files
359 my ( $followmeinfohash, $allfiles, $pw ) = @_;
361 my $infoline = "";
362 my $fullsuccess = 1;
364 my $productname = "";
365 if ( $followmeinfohash->{'allvariableshash'}->{'PRODUCTNAME'} ) { $productname = "/d " . "\"$followmeinfohash->{'allvariableshash'}->{'PRODUCTNAME'}\""; }
366 my $url = "";
367 if ( $followmeinfohash->{'allvariableshash'}->{'OPENSOURCE'} == 0 ) { $url = "/du " . "\"http://www.sun.com\""; }
368 else { $url = "/du " . "\"http://www.openoffice.org\""; }
369 my $timestampurl = "http://timestamp.verisign.com/scripts/timestamp.dll";
371 foreach my $onefile ( keys %{$allfiles} )
373 my $systemcall = "signtool.exe sign /f \"$installer::globals::pfxfile\" /p $pw $productname $url /t \"$timestampurl\" \"$onefile\"";
374 my $displaysystemcall = "signtool.exe sign /f \"$installer::globals::pfxfile\" /p ***** $productname $url /t \"$timestampurl\" \"$onefile\"";
375 my $success = make_systemcall($systemcall, $displaysystemcall);
376 if ( ! $success ) { $fullsuccess = 0; }
379 return $fullsuccess;
382 ########################################################
383 # Signing an existing Windows installation set.
384 ########################################################
386 sub sign_install_set
388 my ($followmeinfohash, $make_copy) = @_;
390 my $installsetpath = $followmeinfohash->{'finalinstalldir'};
392 installer::logger::include_header_into_logfile("Start: Signing installation set $installsetpath");
394 my $complete_success = 1;
395 my $success = 1;
397 my $infoline = "Signing installation set in $installsetpath\n";
398 push( @installer::globals::logfileinfo, $infoline);
400 # check required files.
401 if ( ! $installer::globals::signfiles_checked ) { check_system_path(); }
403 # get cerficate information
404 my $pw = get_pw($installer::globals::pwfile);
406 # making a copy of the installation set, if required
407 if ( $make_copy ) { $installsetpath = copy_install_set($installsetpath); }
408 else { $installsetpath = rename_install_set($installsetpath); }
410 # collecting all files in the installation set
411 my ($allcabfiles, $allfiles, $msidatabase, $contains_cab_file) = analyze_installset_content($installsetpath);
413 # changing into installation set
414 my $from = cwd();
415 chdir($installsetpath);
417 # Warning: There might be a problem with very big cabinet files
418 # signing all external cab files first
419 if ( $contains_cab_file )
421 $success = sign_files($followmeinfohash, $allcabfiles, $pw);
422 if ( ! $success ) { $complete_success = 0; }
423 $success = msicert_database($msidatabase, $allcabfiles, $followmeinfohash->{'languagestring'});
424 if ( ! $success ) { $complete_success = 0; }
427 # finally all other files can be signed
428 $success = sign_files($followmeinfohash, $allfiles, $pw);
429 if ( ! $success ) { $complete_success = 0; }
431 # and changing back
432 chdir($from);
434 installer::logger::include_header_into_logfile("End: Signing installation set $installsetpath");
436 return ($installsetpath);