merge the formfield patch from ooo-build
[ooovba.git] / solenv / bin / modules / installer / windows / msiglobal.pm
blob511da180094dfca20e6afe47f9b5034436843bcf
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: msiglobal.pm,v $
11 # This file is part of OpenOffice.org.
13 # OpenOffice.org is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU Lesser General Public License version 3
15 # only, as published by the Free Software Foundation.
17 # OpenOffice.org is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU Lesser General Public License version 3 for more details
21 # (a copy is included in the LICENSE file that accompanied this code).
23 # You should have received a copy of the GNU Lesser General Public License
24 # version 3 along with OpenOffice.org. If not, see
25 # <http://www.openoffice.org/license.html>
26 # for a copy of the LGPLv3 License.
28 #*************************************************************************
30 package installer::windows::msiglobal;
32 use Cwd;
33 use Digest::MD5;
34 use installer::converter;
35 use installer::exiter;
36 use installer::files;
37 use installer::globals;
38 use installer::logger;
39 use installer::pathanalyzer;
40 use installer::remover;
41 use installer::scriptitems;
42 use installer::systemactions;
43 use installer::worker;
44 use installer::windows::idtglobal;
45 use installer::windows::language;
47 ###########################################################################
48 # Generating the header of the ddf file.
49 # The usage of ddf files is needed, because makecab.exe can only include
50 # one sourcefile into a cab file
51 ###########################################################################
53 sub write_ddf_file_header
55 my ($ddffileref, $cabinetfile, $installdir) = @_;
57 my $oneline;
59 $oneline = ".Set CabinetName1=" . $cabinetfile . "\n";
60 push(@{$ddffileref} ,$oneline);
61 $oneline = ".Set ReservePerCabinetSize=128\n"; # This reserves space for a digital signature.
62 push(@{$ddffileref} ,$oneline);
63 $oneline = ".Set MaxDiskSize=CDROM\n"; # This allows the .cab file to be as large as needed.
64 push(@{$ddffileref} ,$oneline);
65 $oneline = ".Set CompressionType=LZX\n";
66 push(@{$ddffileref} ,$oneline);
67 $oneline = ".Set Compress=ON\n";
68 push(@{$ddffileref} ,$oneline);
69 $oneline = ".Set CompressionLevel=$installer::globals::cabfilecompressionlevel\n";
70 push(@{$ddffileref} ,$oneline);
71 $oneline = ".Set Cabinet=ON\n";
72 push(@{$ddffileref} ,$oneline);
73 $oneline = ".Set DiskDirectoryTemplate=" . $installdir . "\n";
74 push(@{$ddffileref} ,$oneline);
77 ##########################################################################
78 # Lines in ddf files must not contain more than 256 characters
79 ##########################################################################
81 sub check_ddf_file
83 my ( $ddffile, $ddffilename ) = @_;
85 my $maxlength = 0;
86 my $maxline = 0;
87 my $linelength = 0;
88 my $linenumber = 0;
90 for ( my $i = 0; $i <= $#{$ddffile}; $i++ )
92 my $oneline = ${$ddffile}[$i];
94 $linelength = length($oneline);
95 $linenumber = $i + 1;
97 if ( $linelength > 256 )
99 installer::exiter::exit_program("ERROR \"$ddffilename\" line $linenumber: Lines in ddf files must not contain more than 256 characters!", "check_ddf_file");
102 if ( $linelength > $maxlength )
104 $maxlength = $linelength;
105 $maxline = $linenumber;
109 my $infoline = "Check of ddf file \"$ddffilename\": Maximum length \"$maxlength\" in line \"$maxline\" (allowed line length: 256 characters)\n";
110 push(@installer::globals::logfileinfo, $infoline);
113 ##########################################################################
114 # Lines in ddf files must not be longer than 256 characters.
115 # Therefore it can be useful to use relative pathes. Then it is
116 # necessary to change into temp directory before calling
117 # makecab.exe.
118 ##########################################################################
120 sub make_relative_ddf_path
122 my ( $sourcepath ) = @_;
124 my $windowstemppath = $installer::globals::temppath;
126 if ( $^O =~ /cygwin/i )
128 $windowstemppath = $installer::globals::cyg_temppath;
131 $sourcepath =~ s/\Q$windowstemppath\E//;
132 $sourcepath =~ s/^\\//;
134 return $sourcepath;
137 ##########################################################################
138 # Returning the order of the sequences in the files array.
139 ##########################################################################
141 sub get_sequenceorder
143 my ($filesref) = @_;
145 my %order = ();
147 for ( my $i = 0; $i <= $#{$filesref}; $i++ )
149 my $onefile = ${$filesref}[$i];
150 if ( ! $onefile->{'assignedsequencenumber'} ) { installer::exiter::exit_program("ERROR: No sequence number assigned to $onefile->{'gid'} ($onefile->{'uniquename'})!", "get_sequenceorder"); }
151 $order{$onefile->{'assignedsequencenumber'}} = $i;
154 return \%order;
157 ##########################################################################
158 # Generation the list, in which the source of the files is connected
159 # with the cabinet destination file. Because more than one file needs
160 # to be included into a cab file, this has to be done via ddf files.
161 ##########################################################################
163 sub generate_cab_file_list
165 my ($filesref, $installdir, $ddfdir, $allvariables) = @_;
167 my @cabfilelist = ();
169 installer::logger::include_header_into_logfile("Generating ddf files");
171 installer::logger::include_timestamp_into_logfile("Performance Info: ddf file generation start");
173 if ( $^O =~ /cygwin/i ) { installer::worker::generate_cygwin_pathes($filesref); }
175 if ( $installer::globals::use_packages_for_cabs )
177 my $sequenceorder = get_sequenceorder($filesref);
179 my $counter = 1;
180 my $currentcabfile = "";
182 while ( ( exists($sequenceorder->{$counter}) ) || ( exists($installer::globals::allmergemodulefilesequences{$counter}) ) ) # Taking care of files from merge modules
184 if ( exists($installer::globals::allmergemodulefilesequences{$counter}) )
186 # Skipping this sequence, it is not included in $filesref, because it is assigned to a file from a merge module.\n";
187 $counter++;
188 next;
191 # Files with increasing sequencerorder are included in one cab file
192 my $onefile = ${$filesref}[$sequenceorder->{$counter}];
193 my $cabinetfile = $onefile->{'assignedcabinetfile'};
194 my $sourcepath = $onefile->{'sourcepath'};
195 if ( $^O =~ /cygwin/i ) { $sourcepath = $onefile->{'cyg_sourcepath'}; }
196 my $uniquename = $onefile->{'uniquename'};
198 my $styles = "";
199 my $doinclude = 1;
200 if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; };
201 if ( $styles =~ /\bDONT_PACK\b/ ) { $doinclude = 0; }
203 # to avoid lines with more than 256 characters, it can be useful to use relative pathes
204 if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); }
206 # all files with the same cabinetfile have increasing sequencenumbers
208 my @ddffile = ();
210 write_ddf_file_header(\@ddffile, $cabinetfile, $installdir);
212 my $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n";
213 if ( $doinclude ) { push(@ddffile, $ddfline); }
215 $counter++; # increasing the counter
216 my $nextfile = "";
217 my $nextcabinetfile = "";
218 if ( exists($sequenceorder->{$counter}) ) { $nextfile = ${$filesref}[$sequenceorder->{$counter}]; }
219 if ( $nextfile->{'assignedcabinetfile'} ) { $nextcabinetfile = $nextfile->{'assignedcabinetfile'}; }
221 while ( $nextcabinetfile eq $cabinetfile )
223 $sourcepath = $nextfile->{'sourcepath'};
224 if ( $^O =~ /cygwin/i ) { $sourcepath = $nextfile->{'cyg_sourcepath'}; }
225 # to avoid lines with more than 256 characters, it can be useful to use relative pathes
226 if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); }
227 $uniquename = $nextfile->{'uniquename'};
228 my $localdoinclude = 1;
229 my $nextfilestyles = "";
230 if ( $nextfile->{'Styles'} ) { $nextfilestyles = $nextfile->{'Styles'}; }
231 if ( $nextfilestyles =~ /\bDONT_PACK\b/ ) { $localdoinclude = 0; }
232 $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n";
233 if ( $localdoinclude ) { push(@ddffile, $ddfline); }
235 $counter++; # increasing the counter!
236 $nextcabinetfile = "_lastfile_";
237 if ( exists($sequenceorder->{$counter}) )
239 $nextfile = ${$filesref}[$sequenceorder->{$counter}];
240 $nextcabinetfile = $nextfile->{'assignedcabinetfile'};
244 # creating the DDF file
246 my $ddffilename = $cabinetfile;
247 $ddffilename =~ s/.cab/.ddf/;
248 $ddfdir =~ s/\Q$installer::globals::separator\E\s*$//;
249 $ddffilename = $ddfdir . $installer::globals::separator . $ddffilename;
251 installer::files::save_file($ddffilename ,\@ddffile);
252 my $infoline = "Created ddf file: $ddffilename\n";
253 push(@installer::globals::logfileinfo, $infoline);
255 # lines in ddf files must not be longer than 256 characters
256 check_ddf_file(\@ddffile, $ddffilename);
258 # Writing the makecab system call
260 my $oneline = "makecab.exe /V3 /F " . $ddffilename . " 2\>\&1 |" . "\n";
262 push(@cabfilelist, $oneline);
264 # collecting all ddf files
265 push(@installer::globals::allddffiles, $ddffilename);
268 elsif ((( $installer::globals::cab_file_per_component ) || ( $installer::globals::fix_number_of_cab_files )) && ( $installer::globals::updatedatabase ))
270 my $sequenceorder = get_sequenceorder($filesref);
272 my $counter = 1;
273 my $currentcabfile = "";
275 while ( ( exists($sequenceorder->{$counter}) ) || ( exists($installer::globals::allmergemodulefilesequences{$counter}) ) ) # Taking care of files from merge modules
277 # if ( exists($installer::globals::allmergemodulefilesequences{$counter}) )
279 # # Skipping this sequence, it is not included in $filesref, because it is assigned to a file from a merge module.\n";
280 # $counter++;
281 # next;
284 my $onefile = ${$filesref}[$sequenceorder->{$counter}];
285 $counter++;
287 my $cabinetfile = $onefile->{'cabinet'};
288 my $sourcepath = $onefile->{'sourcepath'};
289 if ( $^O =~ /cygwin/i ) { $sourcepath = $onefile->{'cyg_sourcepath'}; }
290 my $uniquename = $onefile->{'uniquename'};
292 my $styles = "";
293 my $doinclude = 1;
294 if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; };
295 if ( $styles =~ /\bDONT_PACK\b/ ) { $doinclude = 0; }
297 # to avoid lines with more than 256 characters, it can be useful to use relative pathes
298 if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); }
300 my @ddffile = ();
302 write_ddf_file_header(\@ddffile, $cabinetfile, $installdir);
304 my $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n";
305 if ( $doinclude ) { push(@ddffile, $ddfline); }
307 my $nextfile = "";
308 if ( ${$filesref}[$sequenceorder->{$counter}] ) { $nextfile = ${$filesref}[$sequenceorder->{$counter}]; }
310 my $nextcabinetfile = "";
312 if ( $nextfile->{'cabinet'} ) { $nextcabinetfile = $nextfile->{'cabinet'}; }
314 while ( $nextcabinetfile eq $cabinetfile )
316 $sourcepath = $nextfile->{'sourcepath'};
317 if ( $^O =~ /cygwin/i ) { $sourcepath = $nextfile->{'cyg_sourcepath'}; }
318 # to avoid lines with more than 256 characters, it can be useful to use relative pathes
319 if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); }
320 $uniquename = $nextfile->{'uniquename'};
321 my $localdoinclude = 1;
322 my $nextfilestyles = "";
323 if ( $nextfile->{'Styles'} ) { $nextfilestyles = $nextfile->{'Styles'}; }
324 if ( $nextfilestyles =~ /\bDONT_PACK\b/ ) { $localdoinclude = 0; }
325 $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n";
326 if ( $localdoinclude ) { push(@ddffile, $ddfline); }
327 $counter++; # increasing the counter!
328 $nextfile = "";
329 $nextcabinetfile = "_lastfile_";
330 if (( exists($sequenceorder->{$counter}) ) && ( ${$filesref}[$sequenceorder->{$counter}] ))
332 $nextfile = ${$filesref}[$sequenceorder->{$counter}];
333 $nextcabinetfile = $nextfile->{'cabinet'};
337 # creating the DDF file
339 my $ddffilename = $cabinetfile;
340 $ddffilename =~ s/.cab/.ddf/;
341 $ddfdir =~ s/\Q$installer::globals::separator\E\s*$//;
342 $ddffilename = $ddfdir . $installer::globals::separator . $ddffilename;
344 installer::files::save_file($ddffilename ,\@ddffile);
345 my $infoline = "Created ddf file: $ddffilename\n";
346 push(@installer::globals::logfileinfo, $infoline);
348 # lines in ddf files must not be longer than 256 characters
349 check_ddf_file(\@ddffile, $ddffilename);
351 # Writing the makecab system call
353 my $oneline = "makecab.exe /V3 /F " . $ddffilename . " 2\>\&1 |" . "\n";
355 push(@cabfilelist, $oneline);
357 # collecting all ddf files
358 push(@installer::globals::allddffiles, $ddffilename);
361 elsif (( $installer::globals::cab_file_per_component ) || ( $installer::globals::fix_number_of_cab_files ))
363 for ( my $i = 0; $i <= $#{$filesref}; $i++ )
365 my $onefile = ${$filesref}[$i];
366 my $cabinetfile = $onefile->{'cabinet'};
367 my $sourcepath = $onefile->{'sourcepath'};
368 if ( $^O =~ /cygwin/i ) { $sourcepath = $onefile->{'cyg_sourcepath'}; }
369 my $uniquename = $onefile->{'uniquename'};
371 my $styles = "";
372 my $doinclude = 1;
373 if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; };
374 if ( $styles =~ /\bDONT_PACK\b/ ) { $doinclude = 0; }
377 # to avoid lines with more than 256 characters, it can be useful to use relative pathes
378 if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); }
380 # all files with the same cabinetfile are directly behind each other in the files collector
382 my @ddffile = ();
384 write_ddf_file_header(\@ddffile, $cabinetfile, $installdir);
386 my $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n";
387 if ( $doinclude ) { push(@ddffile, $ddfline); }
389 my $nextfile = ${$filesref}[$i+1];
390 my $nextcabinetfile = "";
392 if ( $nextfile->{'cabinet'} ) { $nextcabinetfile = $nextfile->{'cabinet'}; }
394 while ( $nextcabinetfile eq $cabinetfile )
396 $sourcepath = $nextfile->{'sourcepath'};
397 if ( $^O =~ /cygwin/i ) { $sourcepath = $nextfile->{'cyg_sourcepath'}; }
398 # to avoid lines with more than 256 characters, it can be useful to use relative pathes
399 if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); }
400 $uniquename = $nextfile->{'uniquename'};
401 my $localdoinclude = 1;
402 my $nextfilestyles = "";
403 if ( $nextfile->{'Styles'} ) { $nextfilestyles = $nextfile->{'Styles'}; }
404 if ( $nextfilestyles =~ /\bDONT_PACK\b/ ) { $localdoinclude = 0; }
405 $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n";
406 if ( $localdoinclude ) { push(@ddffile, $ddfline); }
407 $i++; # increasing the counter!
408 $nextfile = ${$filesref}[$i+1];
409 if ( $nextfile ) { $nextcabinetfile = $nextfile->{'cabinet'}; }
410 else { $nextcabinetfile = "_lastfile_"; }
413 # creating the DDF file
415 my $ddffilename = $cabinetfile;
416 $ddffilename =~ s/.cab/.ddf/;
417 $ddfdir =~ s/\Q$installer::globals::separator\E\s*$//;
418 $ddffilename = $ddfdir . $installer::globals::separator . $ddffilename;
420 installer::files::save_file($ddffilename ,\@ddffile);
421 my $infoline = "Created ddf file: $ddffilename\n";
422 push(@installer::globals::logfileinfo, $infoline);
424 # lines in ddf files must not be longer than 256 characters
425 check_ddf_file(\@ddffile, $ddffilename);
427 # Writing the makecab system call
429 my $oneline = "makecab.exe /V3 /F " . $ddffilename . " 2\>\&1 |" . "\n";
431 push(@cabfilelist, $oneline);
433 # collecting all ddf files
434 push(@installer::globals::allddffiles, $ddffilename);
437 elsif (( $installer::globals::one_cab_file ) && ( $installer::globals::updatedatabase ))
439 my $sequenceorder = get_sequenceorder($filesref);
441 my $counter = 1;
442 my $currentcabfile = "";
444 while ( ( exists($sequenceorder->{$counter}) ) || ( exists($installer::globals::allmergemodulefilesequences{$counter}) ) ) # Taking care of files from merge modules
446 if ( exists($installer::globals::allmergemodulefilesequences{$counter}) )
448 # Skipping this sequence, it is not included in $filesref, because it is assigned to a file from a merge module.\n";
449 $counter++;
450 next;
453 my $onefile = ${$filesref}[$sequenceorder->{$counter}];
455 $cabinetfile = $onefile->{'cabinet'};
456 my $sourcepath = $onefile->{'sourcepath'};
457 if ( $^O =~ /cygwin/i ) { $sourcepath = $onefile->{'cyg_sourcepath'}; }
458 my $uniquename = $onefile->{'uniquename'};
460 # to avoid lines with more than 256 characters, it can be useful to use relative pathes
461 if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); }
463 if ( $counter == 1 ) { write_ddf_file_header(\@ddffile, $cabinetfile, $installdir); }
465 my $styles = "";
466 my $doinclude = 1;
467 if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; };
468 if ( $styles =~ /\bDONT_PACK\b/ ) { $doinclude = 0; }
470 my $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n";
471 if ( $doinclude ) { push(@ddffile, $ddfline); }
473 $counter++; # increasing the counter
476 # creating the DDF file
478 my $ddffilename = $cabinetfile;
479 $ddffilename =~ s/.cab/.ddf/;
480 $ddfdir =~ s/[\/\\]\s*$//;
481 $ddffilename = $ddfdir . $installer::globals::separator . $ddffilename;
483 installer::files::save_file($ddffilename ,\@ddffile);
484 my $infoline = "Created ddf file: $ddffilename\n";
485 push(@installer::globals::logfileinfo, $infoline);
487 # lines in ddf files must not be longer than 256 characters
488 check_ddf_file(\@ddffile, $ddffilename);
490 # Writing the makecab system call
492 # my $oneline = "makecab.exe /F " . $ddffilename . "\n";
493 my $oneline = "makecab.exe /V3 /F " . $ddffilename . " 2\>\&1 |" . "\n";
495 push(@cabfilelist, $oneline);
497 # collecting all ddf files
498 push(@installer::globals::allddffiles, $ddffilename);
500 elsif ( $installer::globals::one_cab_file )
502 my @ddffile = ();
504 my $cabinetfile = "";
506 for ( my $i = 0; $i <= $#{$filesref}; $i++ )
508 my $onefile = ${$filesref}[$i];
509 $cabinetfile = $onefile->{'cabinet'};
510 my $sourcepath = $onefile->{'sourcepath'};
511 if ( $^O =~ /cygwin/i ) { $sourcepath = $onefile->{'cyg_sourcepath'}; }
512 my $uniquename = $onefile->{'uniquename'};
514 # to avoid lines with more than 256 characters, it can be useful to use relative pathes
515 if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} ) { $sourcepath = make_relative_ddf_path($sourcepath); }
517 if ( $i == 0 ) { write_ddf_file_header(\@ddffile, $cabinetfile, $installdir); }
519 my $styles = "";
520 my $doinclude = 1;
521 if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; };
522 if ( $styles =~ /\bDONT_PACK\b/ ) { $doinclude = 0; }
524 my $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n";
525 if ( $doinclude ) { push(@ddffile, $ddfline); }
528 # creating the DDF file
530 my $ddffilename = $cabinetfile;
531 $ddffilename =~ s/.cab/.ddf/;
532 $ddfdir =~ s/[\/\\]\s*$//;
533 $ddffilename = $ddfdir . $installer::globals::separator . $ddffilename;
535 installer::files::save_file($ddffilename ,\@ddffile);
536 my $infoline = "Created ddf file: $ddffilename\n";
537 push(@installer::globals::logfileinfo, $infoline);
539 # lines in ddf files must not be longer than 256 characters
540 check_ddf_file(\@ddffile, $ddffilename);
542 # Writing the makecab system call
544 my $oneline = "makecab.exe /F " . $ddffilename . "\n";
546 push(@cabfilelist, $oneline);
548 # collecting all ddf files
549 push(@installer::globals::allddffiles, $ddffilename);
551 else
553 installer::exiter::exit_program("ERROR: No cab file specification in globals.pm !", "create_media_table");
556 installer::logger::include_timestamp_into_logfile("Performance Info: ddf file generation end");
558 return \@cabfilelist; # contains all system calls for packaging process
561 ########################################################################
562 # Returning the file sequence of a specified file.
563 ########################################################################
565 sub get_file_sequence
567 my ($filesref, $uniquefilename) = @_;
569 my $sequence = "";
570 my $found_sequence = 0;
572 for ( my $i = 0; $i <= $#{$filesref}; $i++ )
574 my $onefile = ${$filesref}[$i];
575 my $uniquename = $onefile->{'uniquename'};
577 if ( $uniquename eq $uniquefilename )
579 $sequence = $onefile->{'sequencenumber'};
580 $found_sequence = 1;
581 last;
585 if ( ! $found_sequence ) { installer::exiter::exit_program("ERROR: No sequence found for $uniquefilename !", "get_file_sequence"); }
587 return $sequence;
590 ########################################################################
591 # For update and patch reasons the pack order needs to be saved.
592 # The pack order is saved in the ddf files; the names and locations
593 # of the ddf files are saved in @installer::globals::allddffiles.
594 # The outputfile "packorder.txt" can be saved in
595 # $installer::globals::infodirectory .
596 ########################################################################
598 sub save_packorder
600 installer::logger::include_header_into_logfile("Saving pack order");
602 installer::logger::include_timestamp_into_logfile("Performance Info: saving pack order start");
604 my $packorderfilename = "packorder.txt";
605 $packorderfilename = $installer::globals::infodirectory . $installer::globals::separator . $packorderfilename;
607 my @packorder = ();
609 my $headerline = "\# Syntax\: Filetable_Sequence Cabinetfilename Physical_FileName Unique_FileName\n\n";
610 push(@packorder, $headerline);
612 for ( my $i = 0; $i <= $#installer::globals::allddffiles; $i++ )
614 my $ddffilename = $installer::globals::allddffiles[$i];
615 my $ddffile = installer::files::read_file($ddffilename);
616 my $cabinetfile = "";
618 for ( my $j = 0; $j <= $#{$ddffile}; $j++ )
620 my $oneline = ${$ddffile}[$j];
622 # Getting the Cabinet file name
624 if ( $oneline =~ /^\s*\.Set\s+CabinetName.*\=(.*?)\s*$/ ) { $cabinetfile = $1; }
625 if ( $oneline =~ /^\s*\.Set\s+/ ) { next; }
627 if ( $oneline =~ /^\s*\"(.*?)\"\s+(.*?)\s*$/ )
629 my $sourcefile = $1;
630 my $uniquefilename = $2;
632 installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$sourcefile);
634 # Using the hash created in create_files_table for performance reasons to get the sequence number
635 my $filesequence = "";
636 if ( exists($installer::globals::uniquefilenamesequence{$uniquefilename}) ) { $filesequence = $installer::globals::uniquefilenamesequence{$uniquefilename}; }
637 else { installer::exiter::exit_program("ERROR: No sequence number value for $uniquefilename !", "save_packorder"); }
639 my $line = $filesequence . "\t" . $cabinetfile . "\t" . $sourcefile . "\t" . $uniquefilename . "\n";
640 push(@packorder, $line);
645 installer::files::save_file($packorderfilename ,\@packorder);
647 installer::logger::include_timestamp_into_logfile("Performance Info: saving pack order end");
650 #################################################################
651 # Returning the name of the msi database
652 #################################################################
654 sub get_msidatabasename
656 my ($allvariableshashref, $language) = @_;
658 my $databasename = $allvariableshashref->{'PRODUCTNAME'} . $allvariableshashref->{'PRODUCTVERSION'};
659 $databasename = lc($databasename);
660 $databasename =~ s/\.//g;
661 $databasename =~ s/\-//g;
662 $databasename =~ s/\s//g;
664 # possibility to overwrite the name with variable DATABASENAME
665 if ( $allvariableshashref->{'DATABASENAME'} )
667 $databasename = $allvariableshashref->{'DATABASENAME'};
670 if ( $language )
672 if (!($language eq ""))
674 $databasename .= "_$language";
678 $databasename .= ".msi";
680 return $databasename;
683 #################################################################
684 # Creating the msi database
685 # This works only on Windows
686 #################################################################
688 sub create_msi_database
690 my ($idtdirbase ,$msifilename) = @_;
692 # -f : path containing the idt files
693 # -d : msi database, including path
694 # -c : create database
695 # -i : include the following tables ("*" includes all available tables)
697 my $msidb = "msidb.exe"; # Has to be in the path
698 my $extraslash = ""; # Has to be set for non-ActiveState perl
700 installer::logger::include_header_into_logfile("Creating msi database");
702 $idtdirbase = installer::converter::make_path_conform($idtdirbase);
704 $msifilename = installer::converter::make_path_conform($msifilename);
706 if ( $^O =~ /cygwin/i ) {
707 # msidb.exe really wants backslashes. (And double escaping because system() expands the string.)
708 $idtdirbase =~ s/\//\\\\/g;
709 $msifilename =~ s/\//\\\\/g;
710 $extraslash = "\\";
712 my $systemcall = $msidb . " -f " . $idtdirbase . " -d " . $msifilename . " -c " . "-i " . $extraslash . "*";
714 my $returnvalue = system($systemcall);
716 my $infoline = "Systemcall: $systemcall\n";
717 push( @installer::globals::logfileinfo, $infoline);
719 if ($returnvalue)
721 $infoline = "ERROR: Could not execute $msidb!\n";
722 push( @installer::globals::logfileinfo, $infoline);
724 else
726 $infoline = "Success: Executed $msidb successfully!\n";
727 push( @installer::globals::logfileinfo, $infoline);
731 #####################################################################
732 # Returning the value from sis.mlf for Summary Information Stream
733 #####################################################################
735 sub get_value_from_sis_lng
737 my ($language, $languagefile, $searchstring) = @_;
739 my $language_block = installer::windows::idtglobal::get_language_block_from_language_file($searchstring, $languagefile);
740 my $newstring = installer::windows::idtglobal::get_language_string_from_language_block($language_block, $language, $searchstring);
741 $newstring = "\"" . $newstring . "\"";
743 return $newstring;
746 #################################################################
747 # Returning the msi version for the Summary Information Stream
748 #################################################################
750 sub get_msiversion_for_sis
752 my $msiversion = "200";
753 return $msiversion;
756 #################################################################
757 # Returning the word count for the Summary Information Stream
758 #################################################################
760 sub get_wordcount_for_sis
762 my $wordcount = "0";
763 return $wordcount;
766 #################################################################
767 # Returning the codepage for the Summary Information Stream
768 #################################################################
770 sub get_codepage_for_sis
772 my ( $language ) = @_;
774 my $codepage = installer::windows::language::get_windows_encoding($language);
776 # Codepage 65001 does not work in Summary Information Stream
777 if ( $codepage == 65001 ) { $codepage = 0; }
779 # my $codepage = "1252"; # determine dynamically in a function
780 # my $codepage = "65001"; # UTF-8
781 return $codepage;
784 #################################################################
785 # Returning the template for the Summary Information Stream
786 #################################################################
788 sub get_template_for_sis
790 my ( $language ) = @_;
792 my $windowslanguage = installer::windows::language::get_windows_language($language);
794 my $value = "\"Intel;" . $windowslanguage; # adding the Windows language
796 $value = $value . "\""; # adding ending '"'
798 return $value ;
801 #################################################################
802 # Returning the PackageCode for the Summary Information Stream
803 #################################################################
805 sub get_packagecode_for_sis
807 # always generating a new package code for each package
809 my $guidref = get_guid_list(1, 1); # only one GUID shall be generated
811 ${$guidref}[0] =~ s/\s*$//; # removing ending spaces
813 my $guid = "\{" . ${$guidref}[0] . "\}";
815 my $infoline = "PackageCode: $guid\n";
816 push( @installer::globals::logfileinfo, $infoline);
818 return $guid;
821 #################################################################
822 # Returning the title for the Summary Information Stream
823 #################################################################
825 sub get_title_for_sis
827 my ( $language, $languagefile, $searchstring ) = @_;
829 my $title = get_value_from_sis_lng($language, $languagefile, $searchstring );
831 return $title;
834 #################################################################
835 # Returning the author for the Summary Information Stream
836 #################################################################
838 sub get_author_for_sis
840 my $author = $installer::globals::longmanufacturer;
842 $author = "\"" . $author . "\"";
844 return $author;
847 #################################################################
848 # Returning the subject for the Summary Information Stream
849 #################################################################
851 sub get_subject_for_sis
853 my ( $allvariableshashref ) = @_;
855 my $subject = $allvariableshashref->{'PRODUCTNAME'} . " " . $allvariableshashref->{'PRODUCTVERSION'};
857 $subject = "\"" . $subject . "\"";
859 return $subject;
862 #################################################################
863 # Returning the comment for the Summary Information Stream
864 #################################################################
866 sub get_comment_for_sis
868 my ( $language, $languagefile, $searchstring ) = @_;
870 my $comment = get_value_from_sis_lng($language, $languagefile, $searchstring );
872 return $comment;
875 #################################################################
876 # Returning the keywords for the Summary Information Stream
877 #################################################################
879 sub get_keywords_for_sis
881 my ( $language, $languagefile, $searchstring ) = @_;
883 my $keywords = get_value_from_sis_lng($language, $languagefile, $searchstring );
885 return $keywords;
888 ######################################################################
889 # Returning the application name for the Summary Information Stream
890 ######################################################################
892 sub get_appname_for_sis
894 my ( $language, $languagefile, $searchstring ) = @_;
896 my $appname = get_value_from_sis_lng($language, $languagefile, $searchstring );
898 return $appname;
901 ######################################################################
902 # Returning the security for the Summary Information Stream
903 ######################################################################
905 sub get_security_for_sis
907 my $security = "0";
908 return $security;
911 #################################################################
912 # Writing the Summary information stream into the msi database
913 # This works only on Windows
914 #################################################################
916 sub write_summary_into_msi_database
918 my ($msifilename, $language, $languagefile, $allvariableshashref) = @_;
920 # -g : requrired msi version
921 # -c : codepage
922 # -p : template
924 installer::logger::include_header_into_logfile("Writing summary information stream");
926 my $msiinfo = "msiinfo.exe"; # Has to be in the path
928 my $sislanguage = "en-US"; # title, comment, keyword and appname alway in english
930 my $msiversion = get_msiversion_for_sis();
931 my $codepage = get_codepage_for_sis($language);
932 my $template = get_template_for_sis($language);
933 my $guid = get_packagecode_for_sis();
934 my $title = get_title_for_sis($sislanguage,$languagefile, "OOO_SIS_TITLE");
935 my $author = get_author_for_sis();
936 my $subject = get_subject_for_sis($allvariableshashref);
937 my $comment = get_comment_for_sis($sislanguage,$languagefile, "OOO_SIS_COMMENT");
938 my $keywords = get_keywords_for_sis($sislanguage,$languagefile, "OOO_SIS_KEYWORDS");
939 my $appname = get_appname_for_sis($sislanguage,$languagefile, "OOO_SIS_APPNAME");
940 my $security = get_security_for_sis();
941 my $wordcount = get_wordcount_for_sis();
943 $msifilename = installer::converter::make_path_conform($msifilename);
945 my $systemcall = $msiinfo . " " . $msifilename . " -g " . $msiversion . " -c " . $codepage
946 . " -p " . $template . " -v " . $guid . " -t " . $title . " -a " . $author
947 . " -j " . $subject . " -o " . $comment . " -k " . $keywords . " -n " . $appname
948 . " -u " . $security . " -w " . $wordcount;
950 my $returnvalue = system($systemcall);
952 my $infoline = "Systemcall: $systemcall\n";
953 push( @installer::globals::logfileinfo, $infoline);
955 if ($returnvalue)
957 $infoline = "ERROR: Could not execute $msiinfo!\n";
958 push( @installer::globals::logfileinfo, $infoline);
960 else
962 $infoline = "Success: Executed $msiinfo successfully!\n";
963 push( @installer::globals::logfileinfo, $infoline);
967 #########################################################################
968 # For more than one language in the installation set:
969 # Use one database and create Transformations for all other languages
970 #########################################################################
972 sub create_transforms
974 my ($languagesarray, $defaultlanguage, $installdir, $allvariableshashref) = @_;
976 installer::logger::include_header_into_logfile("Creating Transforms");
978 my $msitran = "msitran.exe"; # Has to be in the path
980 $installdir = installer::converter::make_path_conform($installdir);
982 # Syntax for creating a transformation
983 # msitran.exe -g <baseDB> <referenceDB> <transformfile> [<errorhandling>}
985 my $basedbname = get_msidatabasename($allvariableshashref, $defaultlanguage);
986 $basedbname = $installdir . $installer::globals::separator . $basedbname;
988 my $errorhandling = "f"; # Suppress "change codepage" error
990 # Iterating over all files
992 foreach ( @{$languagesarray} )
994 my $onelanguage = $_;
996 if ( $onelanguage eq $defaultlanguage ) { next; }
998 my $referencedbname = get_msidatabasename($allvariableshashref, $onelanguage);
999 $referencedbname = $installdir . $installer::globals::separator . $referencedbname;
1001 my $transformfile = $installdir . $installer::globals::separator . "trans_" . $onelanguage . ".mst";
1003 my $systemcall = $msitran . " " . " -g " . $basedbname . " " . $referencedbname . " " . $transformfile . " " . $errorhandling;
1005 my $returnvalue = system($systemcall);
1007 my $infoline = "Systemcall: $systemcall\n";
1008 push( @installer::globals::logfileinfo, $infoline);
1010 # Problem: msitran.exe in version 4.0 always returns "1", even if no failure occured.
1011 # Therefore it has to be checked, if this is version 4.0. If yes, if the mst file
1012 # exists and if it is larger than 0 bytes. If this is true, then no error occured.
1013 # File Version of msitran.exe: 4.0.6000.16384 has checksum: "b66190a70145a57773ec769e16777b29".
1014 # Same for msitran.exe from wntmsci12: "aa25d3445b94ffde8ef0c1efb77a56b8"
1016 if ($returnvalue)
1018 $infoline = "WARNING: Returnvalue of $msitran is not 0. Checking version of $msitran!\n";
1019 push( @installer::globals::logfileinfo, $infoline);
1021 open(FILE, "<$installer::globals::msitranpath") or die "ERROR: Can't open $installer::globals::msitranpath for creating file hash";
1022 binmode(FILE);
1023 my $digest = Digest::MD5->new->addfile(*FILE)->hexdigest;
1024 close(FILE);
1026 my @problemchecksums = ("b66190a70145a57773ec769e16777b29", "aa25d3445b94ffde8ef0c1efb77a56b8");
1027 my $isproblemchecksum = 0;
1029 foreach my $problemchecksum ( @problemchecksums )
1031 $infoline = "Checksum of problematic MsiTran.exe: $problemchecksum\n";
1032 push( @installer::globals::logfileinfo, $infoline);
1033 $infoline = "Checksum of used MsiTran.exe: $digest\n";
1034 push( @installer::globals::logfileinfo, $infoline);
1035 if ( $digest eq $problemchecksum ) { $isproblemchecksum = 1; }
1038 if ( $isproblemchecksum )
1040 # Check existence of mst
1041 if ( -f $transformfile )
1043 $infoline = "File $transformfile exists.\n";
1044 push( @installer::globals::logfileinfo, $infoline);
1045 my $filesize = ( -s $transformfile );
1046 $infoline = "Size of $transformfile: $filesize\n";
1047 push( @installer::globals::logfileinfo, $infoline);
1049 if ( $filesize > 0 )
1051 $infoline = "Info: Returnvalue $returnvalue of $msitran is no problem :-) .\n";
1052 push( @installer::globals::logfileinfo, $infoline);
1053 $returnvalue = 0; # reset the error
1055 else
1057 $infoline = "Filesize indicates that an error occured.\n";
1058 push( @installer::globals::logfileinfo, $infoline);
1061 else
1063 $infoline = "File $transformfile does not exist -> An error occured.\n";
1064 push( @installer::globals::logfileinfo, $infoline);
1067 else
1069 $infoline = "This is not a problematic version of msitran.exe. Therefore the error is not caused by problematic msitran.exe.\n";
1070 push( @installer::globals::logfileinfo, $infoline);
1074 if ($returnvalue)
1076 $infoline = "ERROR: Could not execute $msitran!\n";
1077 push( @installer::globals::logfileinfo, $infoline);
1079 else
1081 $infoline = "Success: Executed $msitran successfully!\n";
1082 push( @installer::globals::logfileinfo, $infoline);
1085 # The reference database can be deleted
1087 my $result = unlink($referencedbname);
1088 # $result contains the number of deleted files
1090 if ( $result == 0 )
1092 $infoline = "ERROR: Could not remove file $$referencedbname !\n";
1093 push( @installer::globals::logfileinfo, $infoline);
1094 installer::exiter::exit_program($infoline, "create_transforms");
1099 #########################################################################
1100 # The default language msi database does not need to contain
1101 # the language in the database name. Therefore the file
1102 # is renamed. Example: "openofficeorg20_01.msi" to "openofficeorg20.msi"
1103 #########################################################################
1105 sub rename_msi_database_in_installset
1107 my ($defaultlanguage, $installdir, $allvariableshashref) = @_;
1109 installer::logger::include_header_into_logfile("Renaming msi database");
1111 my $olddatabasename = get_msidatabasename($allvariableshashref, $defaultlanguage);
1112 $olddatabasename = $installdir . $installer::globals::separator . $olddatabasename;
1114 my $newdatabasename = get_msidatabasename($allvariableshashref);
1116 $installer::globals::shortmsidatabasename = $newdatabasename;
1118 $newdatabasename = $installdir . $installer::globals::separator . $newdatabasename;
1120 installer::systemactions::rename_one_file($olddatabasename, $newdatabasename);
1122 $installer::globals::msidatabasename = $newdatabasename;
1125 #########################################################################
1126 # Adding the language to the name of the msi databasename,
1127 # if this is required (ADDLANGUAGEINDATABASENAME)
1128 #########################################################################
1130 sub add_language_to_msi_database
1132 my ($defaultlanguage, $installdir, $allvariables) = @_;
1134 my $languagestring = $defaultlanguage;
1135 if ( $allvariables->{'USELANGUAGECODE'} ) { $languagestring = installer::windows::language::get_windows_language($defaultlanguage); }
1136 my $newdatabasename = $installer::globals::shortmsidatabasename;
1137 $newdatabasename =~ s/\.msi\s*$/_$languagestring\.msi/;
1138 $installer::globals::shortmsidatabasename = $newdatabasename;
1139 $newdatabasename = $installdir . $installer::globals::separator . $newdatabasename;
1141 my $olddatabasename = $installer::globals::msidatabasename;
1143 installer::systemactions::rename_one_file($olddatabasename, $newdatabasename);
1145 $installer::globals::msidatabasename = $newdatabasename;
1148 ##########################################################################
1149 # Writing the databasename into the setup.ini.
1150 ##########################################################################
1152 sub put_databasename_into_setupini
1154 my ($setupinifile, $allvariableshashref) = @_;
1156 my $databasename = get_msidatabasename($allvariableshashref);
1157 my $line = "database=" . $databasename . "\n";
1159 push(@{$setupinifile}, $line);
1162 ##########################################################################
1163 # Writing the required msi version into setup.ini
1164 ##########################################################################
1166 sub put_msiversion_into_setupini
1168 my ($setupinifile) = @_;
1170 my $msiversion = "2.0";
1171 my $line = "msiversion=" . $msiversion . "\n";
1173 push(@{$setupinifile}, $line);
1176 ##########################################################################
1177 # Writing the productname into setup.ini
1178 ##########################################################################
1180 sub put_productname_into_setupini
1182 my ($setupinifile, $allvariableshashref) = @_;
1184 my $productname = $allvariableshashref->{'PRODUCTNAME'};
1185 my $line = "productname=" . $productname . "\n";
1187 push(@{$setupinifile}, $line);
1190 ##########################################################################
1191 # Writing the productcode into setup.ini
1192 ##########################################################################
1194 sub put_productcode_into_setupini
1196 my ($setupinifile) = @_;
1198 my $productcode = $installer::globals::productcode;
1199 my $line = "productcode=" . $productcode . "\n";
1201 push(@{$setupinifile}, $line);
1204 ##########################################################################
1205 # Writing the ProductVersion from Property table into setup.ini
1206 ##########################################################################
1208 sub put_productversion_into_setupini
1210 my ($setupinifile) = @_;
1212 my $line = "productversion=" . $installer::globals::msiproductversion . "\n";
1213 push(@{$setupinifile}, $line);
1216 ##########################################################################
1217 # Writing the key for Minor Upgrades into setup.ini
1218 ##########################################################################
1220 sub put_upgradekey_into_setupini
1222 my ($setupinifile) = @_;
1224 if ( $installer::globals::minorupgradekey ne "" )
1226 my $line = "upgradekey=" . $installer::globals::minorupgradekey . "\n";
1227 push(@{$setupinifile}, $line);
1231 ##########################################################################
1232 # Writing the number of languages into setup.ini
1233 ##########################################################################
1235 sub put_languagecount_into_setupini
1237 my ($setupinifile, $languagesarray) = @_;
1239 my $languagecount = $#{$languagesarray} + 1;
1240 my $line = "count=" . $languagecount . "\n";
1242 push(@{$setupinifile}, $line);
1245 ##########################################################################
1246 # Writing the defaultlanguage into setup.ini
1247 ##########################################################################
1249 sub put_defaultlanguage_into_setupini
1251 my ($setupinifile, $defaultlanguage) = @_;
1253 my $windowslanguage = installer::windows::language::get_windows_language($defaultlanguage);
1254 my $line = "default=" . $windowslanguage . "\n";
1255 push(@{$setupinifile}, $line);
1258 ##########################################################################
1259 # Writing the information about transformations into setup.ini
1260 ##########################################################################
1262 sub put_transforms_into_setupini
1264 my ($setupinifile, $onelanguage, $counter) = @_;
1266 my $windowslanguage = installer::windows::language::get_windows_language($onelanguage);
1267 my $transformfilename = "trans_" . $onelanguage . ".mst";
1269 my $line = "lang" . $counter . "=" . $windowslanguage . "," . $transformfilename . "\n";
1271 push(@{$setupinifile}, $line);
1274 ###################################################
1275 # Including Windows line ends in ini files
1276 # Profiles on Windows shall have \r\n line ends
1277 ###################################################
1279 sub include_windows_lineends
1281 my ($onefile) = @_;
1283 for ( my $i = 0; $i <= $#{$onefile}; $i++ )
1285 ${$onefile}[$i] =~ s/\r?\n$/\r\n/;
1289 ##########################################################################
1290 # Generation the file setup.ini, that is used by the loader setup.exe.
1291 ##########################################################################
1293 sub create_setup_ini
1295 my ($languagesarray, $defaultlanguage, $installdir, $allvariableshashref) = @_;
1297 installer::logger::include_header_into_logfile("Creating setup.ini");
1299 my $setupinifilename = $installdir . $installer::globals::separator . "setup.ini";
1301 my @setupinifile = ();
1302 my $setupinifile = \@setupinifile;
1304 my $line = "\[setup\]\n";
1305 push(@setupinifile, $line);
1307 put_databasename_into_setupini($setupinifile, $allvariableshashref);
1308 put_msiversion_into_setupini($setupinifile);
1309 put_productname_into_setupini($setupinifile, $allvariableshashref);
1310 put_productcode_into_setupini($setupinifile);
1311 put_productversion_into_setupini($setupinifile);
1312 put_upgradekey_into_setupini($setupinifile);
1314 $line = "\[languages\]\n";
1315 push(@setupinifile, $line);
1317 put_languagecount_into_setupini($setupinifile, $languagesarray);
1318 put_defaultlanguage_into_setupini($setupinifile, $defaultlanguage);
1320 if ( $#{$languagesarray} > 0 ) # writing the transforms information
1322 my $counter = 1;
1324 for ( my $i = 0; $i <= $#{$languagesarray}; $i++ )
1326 if ( ${$languagesarray}[$i] eq $defaultlanguage ) { next; }
1328 put_transforms_into_setupini($setupinifile, ${$languagesarray}[$i], $counter);
1329 $counter++;
1333 if ( $installer::globals::iswin && $installer::globals::plat =~ /cygwin/i) # Windows line ends only for Cygwin
1335 include_windows_lineends($setupinifile);
1338 installer::files::save_file($setupinifilename, $setupinifile);
1340 $infoline = "Generated file $setupinifilename !\n";
1341 push( @installer::globals::logfileinfo, $infoline);
1344 #################################################################
1345 # Copying the files defined as ScpActions into the
1346 # installation set.
1347 #################################################################
1349 sub copy_scpactions_into_installset
1351 my ($defaultlanguage, $installdir, $allscpactions) = @_;
1353 installer::logger::include_header_into_logfile("Copying ScpAction files into installation set");
1355 for ( my $i = 0; $i <= $#{$allscpactions}; $i++ )
1357 my $onescpaction = ${$allscpactions}[$i];
1359 if ( $onescpaction->{'Name'} eq "loader.exe" ) { next; } # do not copy this ScpAction loader
1361 # only copying language independent files or files with the correct language (the defaultlanguage)
1363 my $filelanguage = $onescpaction->{'specificlanguage'};
1365 if ( ($filelanguage eq $defaultlanguage) || ($filelanguage eq "") )
1367 my $sourcefile = $onescpaction->{'sourcepath'};
1368 my $destfile = $installdir . $installer::globals::separator . $onescpaction->{'DestinationName'};
1370 installer::systemactions::copy_one_file($sourcefile, $destfile);
1375 #################################################################
1376 # Copying the files for the Windows installer into the
1377 # installation set (setup.exe).
1378 #################################################################
1380 sub copy_windows_installer_files_into_installset
1382 my ($installdir, $includepatharrayref, $allvariables) = @_;
1384 installer::logger::include_header_into_logfile("Copying Windows installer files into installation set");
1386 @copyfile = ();
1387 push(@copyfile, "loader2.exe");
1389 if ( $allvariables->{'NOLOADERREQUIRED'} ) { @copyfile = (); }
1391 for ( my $i = 0; $i <= $#copyfile; $i++ )
1393 my $filename = $copyfile[$i];
1394 my $sourcefileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filename, $includepatharrayref, 1);
1396 if ( ! -f $$sourcefileref ) { installer::exiter::exit_program("ERROR: msi file not found: $$sourcefileref !", "copy_windows_installer_files_into_installset"); }
1398 my $destfile;
1399 if ( $copyfile[$i] eq "loader2.exe" ) { $destfile = "setup.exe"; } # renaming the loader
1400 else { $destfile = $copyfile[$i]; }
1402 $destfile = $installdir . $installer::globals::separator . $destfile;
1404 installer::systemactions::copy_one_file($$sourcefileref, $destfile);
1408 #################################################################
1409 # Copying MergeModules for the Windows installer into the
1410 # installation set. The list of MergeModules is located
1411 # in %installer::globals::copy_msm_files
1412 #################################################################
1414 sub copy_merge_modules_into_installset
1416 my ($installdir) = @_;
1418 installer::logger::include_header_into_logfile("Copying Merge files into installation set");
1420 my $cabfile;
1421 foreach $cabfile ( keys %installer::globals::copy_msm_files )
1423 my $sourcefile = $installer::globals::copy_msm_files{$cabfile};
1424 my $destfile = $installdir . $installer::globals::separator . $cabfile;
1426 installer::systemactions::copy_one_file($sourcefile, $destfile);
1430 #################################################################
1431 # Copying the child projects into the
1432 # installation set
1433 #################################################################
1435 sub copy_child_projects_into_installset
1437 my ($installdir, $allvariables) = @_;
1439 my $sourcefile = "";
1440 my $destdir = "";
1442 # adding Java
1444 if ( $allvariables->{'JAVAPRODUCT'} )
1446 $sourcefile = $installer::globals::javafile->{'sourcepath'};
1447 $destdir = $installdir . $installer::globals::separator . $installer::globals::javafile->{'Subdir'};
1448 if ( ! -d $destdir) { installer::systemactions::create_directory($destdir); }
1449 installer::systemactions::copy_one_file($sourcefile, $destdir);
1452 if ( $allvariables->{'UREPRODUCT'} )
1454 $sourcefile = $installer::globals::urefile->{'sourcepath'};
1455 $destdir = $installdir . $installer::globals::separator . $installer::globals::urefile->{'Subdir'};
1456 if ( ! -d $destdir) { installer::systemactions::create_directory($destdir); }
1457 installer::systemactions::copy_one_file($sourcefile, $destdir);
1461 #################################################################
1462 # Getting a list of GUID using uuidgen.exe.
1463 # This works only on Windows
1464 #################################################################
1466 sub get_guid_list
1468 my ($number, $log) = @_;
1470 if ( $log ) { installer::logger::include_header_into_logfile("Generating $number GUID"); }
1472 my $uuidgen = "uuidgen.exe"; # Has to be in the path
1474 # "-c" for uppercase output
1476 # my $systemcall = "$uuidgen -n$number -c |";
1477 my $systemcall = "$uuidgen -n$number |";
1478 open (UUIDGEN, "$systemcall" ) or die("uuidgen is missing.");
1479 my @uuidlist = <UUIDGEN>;
1480 close (UUIDGEN);
1482 my $infoline = "Systemcall: $systemcall\n";
1483 if ( $log ) { push( @installer::globals::logfileinfo, $infoline); }
1485 my $comparenumber = $#uuidlist + 1;
1487 if ( $comparenumber == $number )
1489 $infoline = "Success: Executed $uuidgen successfully!\n";
1490 if ( $log ) { push( @installer::globals::logfileinfo, $infoline); }
1492 else
1494 $infoline = "ERROR: Could not execute $uuidgen successfully!\n";
1495 if ( $log ) { push( @installer::globals::logfileinfo, $infoline); }
1498 # uppercase, no longer "-c", because this is only supported in uuidgen.exe v.1.01
1499 for ( my $i = 0; $i <= $#uuidlist; $i++ ) { $uuidlist[$i] = uc($uuidlist[$i]); }
1501 return \@uuidlist;
1504 #################################################################
1505 # Calculating a GUID with a string using md5.
1506 #################################################################
1508 sub calculate_guid
1510 my ( $string ) = @_;
1512 my $guid = "";
1514 my $md5 = Digest::MD5->new;
1515 $md5->add($string);
1516 my $digest = $md5->hexdigest;
1517 $digest = uc($digest);
1519 # my $id = pack("A32", $digest);
1520 my ($first, $second, $third, $fourth, $fifth) = unpack ('A8 A4 A4 A4 A12', $digest);
1521 $guid = "$first-$second-$third-$fourth-$fifth";
1523 return $guid;
1526 #################################################################
1527 # Filling the component hash with the values of the
1528 # component file.
1529 #################################################################
1531 sub fill_component_hash
1533 my ($componentfile) = @_;
1535 my %components = ();
1537 for ( my $i = 0; $i <= $#{$componentfile}; $i++ )
1539 my $line = ${$componentfile}[$i];
1541 if ( $line =~ /^\s*(.*?)\t(.*?)\s*$/ )
1543 my $key = $1;
1544 my $value = $2;
1546 $components{$key} = $value;
1550 return \%components;
1553 #################################################################
1554 # Creating a new component file, if new guids were generated.
1555 #################################################################
1557 sub create_new_component_file
1559 my ($componenthash) = @_;
1561 my @componentfile = ();
1563 my $key;
1565 foreach $key (keys %{$componenthash})
1567 my $value = $componenthash->{$key};
1568 my $input = "$key\t$value\n";
1569 push(@componentfile ,$input);
1572 return \@componentfile;
1575 #################################################################
1576 # Filling real component GUID into the component table.
1577 # This works only on Windows
1578 #################################################################
1580 sub set_uuid_into_component_table
1582 my ($idtdirbase, $allvariables) = @_;
1584 my $componenttablename = $idtdirbase . $installer::globals::separator . "Componen.idt";
1586 my $componenttable = installer::files::read_file($componenttablename);
1588 # For update and patch reasons (small update) the GUID of an existing component must not change!
1589 # The collection of component GUIDs is saved in the directory $installer::globals::idttemplatepath in the file "components.txt"
1591 my $infoline = "";
1592 my $counter = 0;
1593 # my $componentfile = installer::files::read_file($installer::globals::componentfilename);
1594 # my $componenthash = fill_component_hash($componentfile);
1596 for ( my $i = 3; $i <= $#{$componenttable}; $i++ ) # ignoring the first three lines
1598 my $oneline = ${$componenttable}[$i];
1599 my $componentname = "";
1600 if ( $oneline =~ /^\s*(\S+?)\t/ ) { $componentname = $1; }
1602 my $uuid = "";
1604 # if ( $componenthash->{$componentname} )
1606 # $uuid = $componenthash->{$componentname};
1608 # else
1611 if ( exists($installer::globals::calculated_component_guids{$componentname}))
1613 $uuid = $installer::globals::calculated_component_guids{$componentname};
1615 else
1617 # Calculating new GUID with the help of the component name.
1618 my $useooobaseversion = 1;
1619 if ( exists($installer::globals::base_independent_components{$componentname})) { $useooobaseversion = 0; }
1620 my $sourcestring = $componentname;
1622 if ( $useooobaseversion )
1624 if ( ! exists($allvariables->{'OOOBASEVERSION'}) ) { installer::exiter::exit_program("ERROR: Could not find variable \"OOOBASEVERSION\" (required value for GUID creation)!", "set_uuid_into_component_table"); }
1625 $sourcestring = $sourcestring . "_" . $allvariables->{'OOOBASEVERSION'};
1627 $uuid = calculate_guid($sourcestring);
1628 $counter++;
1630 # checking, if there is a conflict with an already created guid
1631 if ( exists($installer::globals::allcalculated_guids{$uuid}) ) { installer::exiter::exit_program("ERROR: \"$uuid\" was already created before!", "set_uuid_into_component_table"); }
1632 $installer::globals::allcalculated_guids{$uuid} = 1;
1633 $installer::globals::calculated_component_guids{$componentname} = $uuid;
1635 # Setting new uuid
1636 # $componenthash->{$componentname} = $uuid;
1638 # Setting flag
1639 # $installer::globals::created_new_component_guid = 1; # this is very important!
1643 ${$componenttable}[$i] =~ s/COMPONENTGUID/$uuid/;
1646 installer::files::save_file($componenttablename, $componenttable);
1648 # if ( $installer::globals::created_new_component_guid )
1650 # # create new component file!
1651 # $componentfile = create_new_component_file($componenthash);
1652 # installer::worker::sort_array($componentfile);
1654 # # To avoid conflict the components file cannot be saved at the same place
1655 # # All important data have to be saved in the directory: $installer::globals::infodirectory
1656 # my $localcomponentfilename = $installer::globals::componentfilename;
1657 # installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$localcomponentfilename);
1658 # $localcomponentfilename = $installer::globals::infodirectory . $installer::globals::separator . $localcomponentfilename;
1659 # installer::files::save_file($localcomponentfilename, $componentfile);
1661 # # installer::files::save_file($installer::globals::componentfilename, $componentfile); # version using new file in solver
1663 # $infoline = "COMPONENTCODES: Created $counter new GUIDs for components ! \n";
1664 # push( @installer::globals::logfileinfo, $infoline);
1666 # else
1668 # $infoline = "SUCCESS COMPONENTCODES: All component codes exist! \n";
1669 # push( @installer::globals::logfileinfo, $infoline);
1674 #################################################################
1675 # Include all cab files into the msi database.
1676 # This works only on Windows
1677 #################################################################
1679 sub include_cabs_into_msi
1681 my ($installdir) = @_;
1683 installer::logger::include_header_into_logfile("Including cabs into msi database");
1685 my $from = cwd();
1686 my $to = $installdir;
1688 chdir($to);
1690 my $infoline = "Changing into directory: $to";
1691 push( @installer::globals::logfileinfo, $infoline);
1693 my $msidb = "msidb.exe"; # Has to be in the path
1694 my $extraslash = ""; # Has to be set for non-ActiveState perl
1696 my $msifilename = $installer::globals::msidatabasename;
1698 $msifilename = installer::converter::make_path_conform($msifilename);
1700 # msidb.exe really wants backslashes. (And double escaping because system() expands the string.)
1701 $idtdirbase =~ s/\//\\\\/g;
1702 $msifilename =~ s/\//\\\\/g;
1703 $extraslash = "\\";
1705 my $allcabfiles = installer::systemactions::find_file_with_file_extension("cab", $installdir);
1707 for ( my $i = 0; $i <= $#{$allcabfiles}; $i++ )
1709 my $systemcall = $msidb . " -d " . $msifilename . " -a " . ${$allcabfiles}[$i];
1711 my $returnvalue = system($systemcall);
1713 $infoline = "Systemcall: $systemcall\n";
1714 push( @installer::globals::logfileinfo, $infoline);
1716 if ($returnvalue)
1718 $infoline = "ERROR: Could not execute $systemcall !\n";
1719 push( @installer::globals::logfileinfo, $infoline);
1721 else
1723 $infoline = "Success: Executed $systemcall successfully!\n";
1724 push( @installer::globals::logfileinfo, $infoline);
1727 # deleting the cab file
1729 unlink(${$allcabfiles}[$i]);
1731 $infoline = "Deleted cab file: ${$allcabfiles}[$i]\n";
1732 push( @installer::globals::logfileinfo, $infoline);
1735 $infoline = "Changing back into directory: $from";
1736 push( @installer::globals::logfileinfo, $infoline);
1738 chdir($from);
1741 #################################################################
1742 # Executing the created batch file to pack all files.
1743 # This works only on Windows
1744 #################################################################
1746 sub execute_packaging
1748 my ($localpackjobref, $loggingdir, $allvariables) = @_;
1750 installer::logger::include_header_into_logfile("Packaging process");
1752 installer::logger::include_timestamp_into_logfile("Performance Info: Execute packaging start");
1754 my $infoline = "";
1755 my $from = cwd();
1756 my $to = $loggingdir;
1758 chdir($to);
1759 $infoline = "chdir: $to \n";
1760 push( @installer::globals::logfileinfo, $infoline);
1762 # if the ddf file contains relative pathes, it is necessary to change into the temp directory
1763 if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} )
1765 $to = $installer::globals::temppath;
1766 chdir($to);
1767 $infoline = "chdir: $to \n";
1768 push( @installer::globals::logfileinfo, $infoline);
1771 # changing the tmp directory, because makecab.exe generates temporary cab files
1772 my $origtemppath = "";
1773 if ( $ENV{'TMP'} ) { $origtemppath = $ENV{'TMP'}; }
1774 $ENV{'TMP'} = $installer::globals::temppath; # setting TMP to the new unique directory!
1776 my $maxmakecabcalls = 3;
1777 my $allmakecabcalls = $#{$localpackjobref} + 1;
1779 for ( my $i = 0; $i <= $#{$localpackjobref}; $i++ )
1781 my $systemcall = ${$localpackjobref}[$i];
1783 my $callscounter = $i + 1;
1785 installer::logger::print_message( "... makecab.exe ($callscounter/$allmakecabcalls) ... \n" );
1787 # my $returnvalue = system($systemcall);
1789 for ( my $n = 1; $n <= $maxmakecabcalls; $n++ )
1791 my @ddfoutput = ();
1793 $infoline = "Systemcall: $systemcall";
1794 push( @installer::globals::logfileinfo, $infoline);
1796 open (DDF, "$systemcall");
1797 while (<DDF>) {push(@ddfoutput, $_); }
1798 close (DDF);
1800 my $returnvalue = $?; # $? contains the return value of the systemcall
1802 if ($returnvalue)
1804 if ( $n < $maxmakecabcalls )
1806 installer::logger::print_message( "makecab_error (Try $n): Trying again \n" );
1807 $infoline = "makecab_error (Try $n): $systemcall !";
1809 else
1811 installer::logger::print_message( "ERROR (Try $n): Abort packing \n" );
1812 $infoline = "ERROR (Try $n): $systemcall !";
1815 push( @installer::globals::logfileinfo, $infoline);
1816 # for ( my $j = 0; $j <= $#ddfoutput; $j++ ) { push( @installer::globals::logfileinfo, "$ddfoutput[$j]"); }
1818 for ( my $m = 0; $m <= $#ddfoutput; $m++ )
1820 if ( $ddfoutput[$m] =~ /(ERROR\:.*?)\s*$/ )
1822 $infoline = $1 . "\n";
1823 if ( $n < $maxmakecabcalls ) { $infoline =~ s/ERROR\:/makecab_error\:/i; }
1824 installer::logger::print_message( $infoline );
1825 push( @installer::globals::logfileinfo, $infoline);
1829 if ( $n == $maxmakecabcalls ) { installer::exiter::exit_program("ERROR: \"$systemcall\"!", "execute_packaging"); }
1831 else
1833 # installer::logger::print_message( "Success (Try $n): \"$systemcall\"\n" );
1834 $infoline = "Success (Try $n): $systemcall";
1835 push( @installer::globals::logfileinfo, $infoline);
1836 last;
1841 installer::logger::include_timestamp_into_logfile("Performance Info: Execute packaging end");
1843 # setting back to the original tmp directory
1844 $ENV{'TMP'} = $origtemppath;
1846 chdir($from);
1847 $infoline = "chdir: $from \n";
1848 push( @installer::globals::logfileinfo, $infoline);
1851 ###############################################################
1852 # Setting the global variables ProductCode and the UpgradeCode
1853 ###############################################################
1855 sub set_global_code_variables
1857 my ( $languagesref, $languagestringref, $allvariableshashref, $alloldproperties ) = @_;
1859 # In the msi template directory a files "codes.txt" has to exist, in which the ProductCode
1860 # and the UpgradeCode for the product are defined.
1861 # The name "codes.txt" can be overwritten in Product definition with CODEFILENAME .
1862 # Default $installer::globals::codefilename is defined in parameter.pm.
1864 if ( $allvariableshashref->{'CODEFILENAME'} )
1866 $installer::globals::codefilename = $installer::globals::idttemplatepath . $installer::globals::separator . $allvariableshashref->{'CODEFILENAME'};
1867 installer::files::check_file($installer::globals::codefilename);
1870 my $infoline = "Using Codes file: $installer::globals::codefilename \n";
1871 push( @installer::globals::logfileinfo, $infoline);
1873 my $codefile = installer::files::read_file($installer::globals::codefilename);
1875 my $isopensource = 0;
1876 if ( $allvariableshashref->{'OPENSOURCE'} ) { $isopensource = $allvariableshashref->{'OPENSOURCE'}; }
1878 my $onelanguage = "";
1880 if ( $#{$languagesref} > 0 ) # more than one language
1882 if (( ${$languagesref}[1] =~ /jp/ ) ||
1883 ( ${$languagesref}[1] =~ /ko/ ) ||
1884 ( ${$languagesref}[1] =~ /zh/ ))
1886 $onelanguage = "multiasia";
1888 else
1890 $onelanguage = "multiwestern";
1893 else # only one language
1895 $onelanguage = ${$languagesref}[0];
1898 # ProductCode must not change, if Windows patches shall be applied
1899 if ( $installer::globals::updatedatabase )
1901 $installer::globals::productcode = $alloldproperties->{'ProductCode'};
1903 elsif ( $installer::globals::prepare_winpatch )
1905 # ProductCode has to be specified in each language
1906 my $searchstring = "PRODUCTCODE";
1907 my $codeblock = installer::windows::idtglobal::get_language_block_from_language_file($searchstring, $codefile);
1908 $installer::globals::productcode = installer::windows::idtglobal::get_code_from_code_block($codeblock, $onelanguage);
1909 } else {
1910 my $guidref = get_guid_list(1, 1); # only one GUID shall be generated
1911 ${$guidref}[0] =~ s/\s*$//; # removing ending spaces
1912 $installer::globals::productcode = "\{" . ${$guidref}[0] . "\}";
1915 if ( $installer::globals::patch ) # patch upgrade codes are defined in soffice.lst
1917 if ( $allvariableshashref->{'PATCHUPGRADECODE'} ) { $installer::globals::upgradecode = $allvariableshashref->{'PATCHUPGRADECODE'}; }
1918 else { installer::exiter::exit_program("ERROR: PATCHUPGRADECODE not defined in list file!", "set_global_code_variables"); }
1920 else
1922 # UpgradeCode can take english as default, if not defined in specified language
1924 $searchstring = "UPGRADECODE"; # searching in the codes.txt file
1925 $codeblock = installer::windows::idtglobal::get_language_block_from_language_file($searchstring, $codefile);
1926 $installer::globals::upgradecode = installer::windows::idtglobal::get_language_string_from_language_block($codeblock, $onelanguage, "");
1929 # if (( $installer::globals::productcode eq "" ) && ( ! $isopensource )) { installer::exiter::exit_program("ERROR: ProductCode for language $onelanguage not defined in $installer::globals::codefilename !", "set_global_code_variables"); }
1930 if ( $installer::globals::upgradecode eq "" ) { installer::exiter::exit_program("ERROR: UpgradeCode not defined in $installer::globals::codefilename !", "set_global_code_variables"); }
1932 $infoline = "Setting ProductCode to: $installer::globals::productcode \n";
1933 push( @installer::globals::logfileinfo, $infoline);
1934 $infoline = "Setting UpgradeCode to: $installer::globals::upgradecode \n";
1935 push( @installer::globals::logfileinfo, $infoline);
1937 # Adding both variables into the variables array
1939 $allvariableshashref->{'PRODUCTCODE'} = $installer::globals::productcode;
1940 $allvariableshashref->{'UPGRADECODE'} = $installer::globals::upgradecode;
1942 $infoline = "Defined variable PRODUCTCODE: $installer::globals::productcode \n";
1943 push( @installer::globals::logfileinfo, $infoline);
1945 $infoline = "Defined variable UPGRADECODE: $installer::globals::upgradecode \n";
1946 push( @installer::globals::logfileinfo, $infoline);
1950 ###############################################################
1951 # Setting the product version used in property table and
1952 # upgrade table. Saving in global variable $msiproductversion
1953 ###############################################################
1955 sub set_msiproductversion
1957 my ( $allvariables ) = @_;
1959 my $productversion = $allvariables->{'PRODUCTVERSION'};
1961 if (( $productversion =~ /^\s*\d+\s*$/ ) && ( $productversion > 255 )) { $productversion = $productversion%256; }
1963 if ( $productversion =~ /^\s*(\d+)\.(\d+)\.(\d+)\s*$/ )
1965 $productversion = $1 . "\." . $2 . $3 . "\." . $installer::globals::buildid;
1967 elsif ( $productversion =~ /^\s*(\d+)\.(\d+)\s*$/ )
1969 $productversion = $1 . "\." . $2 . "\." . $installer::globals::buildid;
1971 else
1973 my $productminor = "00";
1974 if (( $allvariables->{'PACKAGEVERSION'} ) && ( $allvariables->{'PACKAGEVERSION'} ne "" ))
1976 if ( $allvariables->{'PACKAGEVERSION'} =~ /^\s*(\d+)\.(\d+)\.(\d+)\s*$/ ) { $productminor = $2; }
1979 $productversion = $productversion . "\." . $productminor . "\." . $installer::globals::buildid;
1982 $installer::globals::msiproductversion = $productversion;
1984 # Setting $installer::globals::msimajorproductversion, to differ between old version in upgrade table
1986 if ( $installer::globals::msiproductversion =~ /^\s*(\d+)\./ )
1988 my $major = $1;
1989 $installer::globals::msimajorproductversion = $major . "\.0\.0";
1993 #################################################################################
1994 # Including the msi product version into the bootstrap.ini, Windows only
1995 #################################################################################
1997 sub put_msiproductversion_into_bootstrapfile
1999 my ($filesref) = @_;
2001 for ( my $i = 0; $i <= $#{$filesref}; $i++ )
2003 my $onefile = ${$filesref}[$i];
2005 if ( $onefile->{'gid'} eq "gid_Profile_Version_Ini" )
2007 my $file = installer::files::read_file($onefile->{'sourcepath'});
2009 for ( my $j = 0; $j <= $#{$file}; $j++ )
2011 ${$file}[$j] =~ s/\<msiproductversion\>/$installer::globals::msiproductversion/;
2014 installer::files::save_file($onefile->{'sourcepath'}, $file);
2016 last;
2021 ####################################################################################
2022 # Updating the file Property.idt dynamically
2023 # Content:
2024 # Property Value
2025 ####################################################################################
2027 sub update_reglocat_table
2029 my ($basedir, $allvariables) = @_;
2031 my $reglocatfilename = $basedir . $installer::globals::separator . "RegLocat.idt";
2033 # Only do something, if this file exists
2035 if ( -f $reglocatfilename )
2037 my $reglocatfile = installer::files::read_file($reglocatfilename);
2039 my $layername = "";
2040 if ( $allvariables->{'REGISTRYLAYERNAME'} )
2042 $layername = $allvariables->{'REGISTRYLAYERNAME'};
2044 else
2046 for ( my $i = 0; $i <= $#{$reglocatfile}; $i++ )
2048 if ( ${$reglocatfile}[$i] =~ /\bLAYERNAMETEMPLATE\b/ )
2050 installer::exiter::exit_program("ERROR: Variable \"REGISTRYLAYERNAME\" has to be defined", "update_reglocat_table");
2055 if ( $layername ne "" )
2057 # Updating the layername in
2059 for ( my $i = 0; $i <= $#{$reglocatfile}; $i++ )
2061 ${$reglocatfile}[$i] =~ s/\bLAYERNAMETEMPLATE\b/$layername/;
2064 # Saving the file
2065 installer::files::save_file($reglocatfilename ,$reglocatfile);
2066 my $infoline = "Updated idt file: $reglocatfilename\n";
2067 push(@installer::globals::logfileinfo, $infoline);
2074 ####################################################################################
2075 # Updating the file RemoveRe.idt dynamically (RemoveRegistry.idt)
2076 # The name of the component has to be replaced.
2077 ####################################################################################
2079 sub update_removere_table
2081 my ($basedir) = @_;
2083 my $removeregistryfilename = $basedir . $installer::globals::separator . "RemoveRe.idt";
2085 # Only do something, if this file exists
2087 if ( -f $removeregistryfilename )
2089 my $removeregistryfile = installer::files::read_file($removeregistryfilename);
2091 for ( my $i = 0; $i <= $#{$removeregistryfile}; $i++ )
2093 for ( my $i = 0; $i <= $#{$removeregistryfile}; $i++ )
2095 ${$removeregistryfile}[$i] =~ s/\bREGISTRYROOTCOMPONENT\b/$installer::globals::registryrootcomponent/;
2099 # Saving the file
2100 installer::files::save_file($removeregistryfilename ,$removeregistryfile);
2101 my $infoline = "Updated idt file: $removeregistryfilename \n";
2102 push(@installer::globals::logfileinfo, $infoline);
2106 ##########################################################################
2107 # Reading saved mappings in Files.idt and Director.idt.
2108 # This is required, if installation sets shall be created,
2109 # that can be used for creation of msp files.
2110 ##########################################################################
2112 sub read_saved_mappings
2114 installer::logger::include_header_into_logfile("Reading saved mappings from older installation sets:");
2116 installer::logger::include_timestamp_into_logfile("Performance Info: Reading saved mappings start");
2118 if ( $installer::globals::previous_idt_dir )
2120 my @errorlines = ();
2121 my $errorstring = "";
2122 my $error_occured = 0;
2123 my $file_error_occured = 0;
2124 my $dir_error = 0;
2126 my $idtdir = $installer::globals::previous_idt_dir;
2127 $idtdir =~ s/\Q$installer::globals::separator\E\s*$//;
2129 # Reading File.idt
2131 my $idtfile = $idtdir . $installer::globals::separator . "File.idt";
2132 push( @installer::globals::globallogfileinfo, "\nAnalyzing file: $idtfile\n" );
2133 if ( ! -f $idtfile ) { push( @installer::globals::globallogfileinfo, "Warning: File $idtfile does not exist!\n" ); }
2135 my $n = 0;
2136 open (F, "<$idtfile") || installer::exiter::exit_program("ERROR: Cannot open file $idtfile for reading", "read_saved_mappings");
2137 <F>; <F>; <F>;
2138 while (<F>)
2140 m/^([^\t]+)\t([^\t]+)\t((.*)\|)?([^\t]*)/;
2141 print "OUT1: \$1: $1, \$2: $2, \$3: $3, \$4: $4, \$5: $5\n";
2142 next if ("$1" eq "$5") && (!defined($3));
2143 my $lc1 = lc($1);
2145 if ( exists($installer::globals::savedmapping{"$2/$5"}))
2147 if ( ! $file_error_occured )
2149 $errorstring = "\nErrors in $idtfile: \n";
2150 push(@errorlines, $errorstring);
2152 $errorstring = "Duplicate savedmapping{" . "$2/$5}\n";
2153 push(@errorlines, $errorstring);
2154 $error_occured = 1;
2155 $file_error_occured = 1;
2158 if ( exists($installer::globals::savedrevmapping{$lc1}))
2160 if ( ! $file_error_occured )
2162 $errorstring = "\nErrors in $idtfile: \n";
2163 push(@errorlines, $errorstring);
2165 $errorstring = "Duplicate savedrevmapping{" . "$lc1}\n";
2166 push(@errorlines, $errorstring);
2167 $error_occured = 1;
2168 $file_error_occured = 1;
2171 my $shortname = $4 || '';
2173 # Don't reuse illegal 8.3 mappings that we used to generate in 2.0.4
2174 if (index($shortname, '.') > 8 ||
2175 (index($shortname, '.') == -1 && length($shortname) > 8))
2177 $shortname = '';
2180 if (( $shortname ne '' ) && ( index($shortname, '~') > 0 ) && ( exists($installer::globals::savedrev83mapping{$shortname}) ))
2182 if ( ! $file_error_occured )
2184 $errorstring = "\nErrors in $idtfile: \n";
2185 push(@errorlines, $errorstring);
2187 $errorstring = "Duplicate savedrev83mapping{" . "$shortname}\n";
2188 push(@errorlines, $errorstring);
2189 $error_occured = 1;
2190 $file_error_occured = 1;
2193 $installer::globals::savedmapping{"$2/$5"} = "$1;$shortname";
2194 $installer::globals::savedrevmapping{lc($1)} = "$2/$5";
2195 $installer::globals::savedrev83mapping{$shortname} = "$2/$5" if $shortname ne '';
2196 $n++;
2199 close (F);
2201 push( @installer::globals::globallogfileinfo, "Read $n old file table key or 8.3 name mappings from $idtfile\n" );
2203 # Reading Director.idt
2205 $idtfile = $idtdir . $installer::globals::separator . "Director.idt";
2206 push( @installer::globals::globallogfileinfo, "\nAnalyzing file $idtfile\n" );
2207 if ( ! -f $idtfile ) { push( @installer::globals::globallogfileinfo, "Warning: File $idtfile does not exist!\n" ); }
2209 $n = 0;
2210 open (F, "<$idtfile") || installer::exiter::exit_program("ERROR: Cannot open file $idtfile for reading", "read_saved_mappings");
2211 <F>; <F>; <F>;
2212 while (<F>)
2214 m/^([^\t]+)\t([^\t]+)\t(([^~]+~\d.*)\|)?([^\t]*)/;
2215 next if (!defined($3));
2216 my $lc1 = lc($1);
2218 print "OUT2: \$1: $1, \$2: $2, \$3: $3\n";
2220 if ( exists($installer::globals::saved83dirmapping{$1}) )
2222 if ( ! $dir_error_occured )
2224 $errorstring = "\nErrors in $idtfile: \n";
2225 push(@errorlines, $errorstring);
2227 $errorstring = "Duplicate saved83dirmapping{" . "$1}\n";
2228 push(@errorlines, $errorstring);
2229 $error_occured = 1;
2230 $dir_error_occured = 1;
2233 $installer::globals::saved83dirmapping{$1} = $4;
2234 $n++;
2236 close (F);
2238 push( @installer::globals::globallogfileinfo, "Read $n old directory 8.3 name mappings from $idtfile\n" );
2240 # Analyzing errors
2242 if ( $error_occured )
2244 for ( my $i = 0; $i <= $#errorlines; $i++ )
2246 print "$errorlines[$i]";
2247 push( @installer::globals::globallogfileinfo, "$errorlines[$i]");
2249 installer::exiter::exit_program("ERROR: Duplicate entries in saved mappings!", "read_saved_mappings");
2251 } else {
2252 # push( @installer::globals::globallogfileinfo, "WARNING: Windows patch shall be prepared, but PREVIOUS_IDT_DIR is not set!\n" );
2253 installer::exiter::exit_program("ERROR: Windows patch shall be prepared, but environment variable PREVIOUS_IDT_DIR is not set!", "read_saved_mappings");
2256 installer::logger::include_timestamp_into_logfile("Performance Info: Reading saved mappings end");