1*b1cdbd2cSJim Jagielski#**************************************************************
2*b1cdbd2cSJim Jagielski#
3*b1cdbd2cSJim Jagielski#  Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski#  or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski#  distributed with this work for additional information
6*b1cdbd2cSJim Jagielski#  regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski#  to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski#  "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski#  with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski#
11*b1cdbd2cSJim Jagielski#    http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski#
13*b1cdbd2cSJim Jagielski#  Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski#  software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski#  KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski#  specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski#  under the License.
19*b1cdbd2cSJim Jagielski#
20*b1cdbd2cSJim Jagielski#**************************************************************
21*b1cdbd2cSJim Jagielski
22*b1cdbd2cSJim Jagielski
23*b1cdbd2cSJim Jagielski
24*b1cdbd2cSJim Jagielskipackage installer::windows::msiglobal;
25*b1cdbd2cSJim Jagielski
26*b1cdbd2cSJim Jagielskiuse Cwd;
27*b1cdbd2cSJim Jagielskiuse Digest::MD5;
28*b1cdbd2cSJim Jagielskiuse installer::converter;
29*b1cdbd2cSJim Jagielskiuse installer::exiter;
30*b1cdbd2cSJim Jagielskiuse installer::files;
31*b1cdbd2cSJim Jagielskiuse installer::globals;
32*b1cdbd2cSJim Jagielskiuse installer::logger;
33*b1cdbd2cSJim Jagielskiuse installer::pathanalyzer;
34*b1cdbd2cSJim Jagielskiuse installer::remover;
35*b1cdbd2cSJim Jagielskiuse installer::scriptitems;
36*b1cdbd2cSJim Jagielskiuse installer::systemactions;
37*b1cdbd2cSJim Jagielskiuse installer::worker;
38*b1cdbd2cSJim Jagielskiuse installer::windows::idtglobal;
39*b1cdbd2cSJim Jagielskiuse installer::windows::language;
40*b1cdbd2cSJim Jagielskiuse installer::patch::ReleasesList;
41*b1cdbd2cSJim Jagielski
42*b1cdbd2cSJim Jagielskiuse strict;
43*b1cdbd2cSJim Jagielski
44*b1cdbd2cSJim Jagielski###########################################################################
45*b1cdbd2cSJim Jagielski# Generating the header of the ddf file.
46*b1cdbd2cSJim Jagielski# The usage of ddf files is needed, because makecab.exe can only include
47*b1cdbd2cSJim Jagielski# one sourcefile into a cab file
48*b1cdbd2cSJim Jagielski###########################################################################
49*b1cdbd2cSJim Jagielski
50*b1cdbd2cSJim Jagielskisub write_ddf_file_header
51*b1cdbd2cSJim Jagielski{
52*b1cdbd2cSJim Jagielski	my ($ddffileref, $cabinetfile, $installdir) = @_;
53*b1cdbd2cSJim Jagielski
54*b1cdbd2cSJim Jagielski	my $oneline;
55*b1cdbd2cSJim Jagielski
56*b1cdbd2cSJim Jagielski	$oneline = ".Set CabinetName1=" . $cabinetfile . "\n";
57*b1cdbd2cSJim Jagielski	push(@{$ddffileref} ,$oneline);
58*b1cdbd2cSJim Jagielski	$oneline = ".Set ReservePerCabinetSize=128\n";	# This reserves space for a digital signature.
59*b1cdbd2cSJim Jagielski	push(@{$ddffileref} ,$oneline);
60*b1cdbd2cSJim Jagielski	$oneline = ".Set MaxDiskSize=2147483648\n";		# This allows the .cab file to get a size of 2 GB.
61*b1cdbd2cSJim Jagielski	push(@{$ddffileref} ,$oneline);
62*b1cdbd2cSJim Jagielski	$oneline = ".Set CompressionType=LZX\n";
63*b1cdbd2cSJim Jagielski	push(@{$ddffileref} ,$oneline);
64*b1cdbd2cSJim Jagielski	$oneline = ".Set Compress=ON\n";
65*b1cdbd2cSJim Jagielski	push(@{$ddffileref} ,$oneline);
66*b1cdbd2cSJim Jagielski	$oneline = ".Set CompressionLevel=$installer::globals::cabfilecompressionlevel\n";
67*b1cdbd2cSJim Jagielski	push(@{$ddffileref} ,$oneline);
68*b1cdbd2cSJim Jagielski	$oneline = ".Set Cabinet=ON\n";
69*b1cdbd2cSJim Jagielski	push(@{$ddffileref} ,$oneline);
70*b1cdbd2cSJim Jagielski	$oneline = ".Set DiskDirectoryTemplate=" . $installdir . "\n";
71*b1cdbd2cSJim Jagielski	push(@{$ddffileref} ,$oneline);
72*b1cdbd2cSJim Jagielski}
73*b1cdbd2cSJim Jagielski
74*b1cdbd2cSJim Jagielski##########################################################################
75*b1cdbd2cSJim Jagielski# Lines in ddf files must not contain more than 256 characters
76*b1cdbd2cSJim Jagielski##########################################################################
77*b1cdbd2cSJim Jagielski
78*b1cdbd2cSJim Jagielskisub check_ddf_file
79*b1cdbd2cSJim Jagielski{
80*b1cdbd2cSJim Jagielski	my ( $ddffile, $ddffilename ) = @_;
81*b1cdbd2cSJim Jagielski
82*b1cdbd2cSJim Jagielski	my $maxlength = 0;
83*b1cdbd2cSJim Jagielski	my $maxline = 0;
84*b1cdbd2cSJim Jagielski	my $linelength = 0;
85*b1cdbd2cSJim Jagielski	my $linenumber = 0;
86*b1cdbd2cSJim Jagielski
87*b1cdbd2cSJim Jagielski	for ( my $i = 0; $i <= $#{$ddffile}; $i++ )
88*b1cdbd2cSJim Jagielski	{
89*b1cdbd2cSJim Jagielski		my $oneline = ${$ddffile}[$i];
90*b1cdbd2cSJim Jagielski
91*b1cdbd2cSJim Jagielski		$linelength = length($oneline);
92*b1cdbd2cSJim Jagielski		$linenumber = $i + 1;
93*b1cdbd2cSJim Jagielski
94*b1cdbd2cSJim Jagielski		if ( $linelength > 256 )
95*b1cdbd2cSJim Jagielski		{
96*b1cdbd2cSJim Jagielski			installer::exiter::exit_program("ERROR \"$ddffilename\" line $linenumber: Lines in ddf files must not contain more than 256 characters!", "check_ddf_file");
97*b1cdbd2cSJim Jagielski		}
98*b1cdbd2cSJim Jagielski
99*b1cdbd2cSJim Jagielski		if ( $linelength > $maxlength )
100*b1cdbd2cSJim Jagielski		{
101*b1cdbd2cSJim Jagielski			$maxlength = $linelength;
102*b1cdbd2cSJim Jagielski			$maxline = $linenumber;
103*b1cdbd2cSJim Jagielski		}
104*b1cdbd2cSJim Jagielski	}
105*b1cdbd2cSJim Jagielski
106*b1cdbd2cSJim Jagielski	my $infoline = "Check of ddf file \"$ddffilename\": Maximum length \"$maxlength\" in line \"$maxline\" (allowed line length: 256 characters)\n";
107*b1cdbd2cSJim Jagielski	$installer::logger::Lang->print($infoline);
108*b1cdbd2cSJim Jagielski}
109*b1cdbd2cSJim Jagielski
110*b1cdbd2cSJim Jagielski##########################################################################
111*b1cdbd2cSJim Jagielski# Lines in ddf files must not be longer than 256 characters.
112*b1cdbd2cSJim Jagielski# Therefore it can be useful to use relative pathes. Then it is
113*b1cdbd2cSJim Jagielski# necessary to change into temp directory before calling
114*b1cdbd2cSJim Jagielski# makecab.exe.
115*b1cdbd2cSJim Jagielski##########################################################################
116*b1cdbd2cSJim Jagielski
117*b1cdbd2cSJim Jagielskisub make_relative_ddf_path
118*b1cdbd2cSJim Jagielski{
119*b1cdbd2cSJim Jagielski	my ( $sourcepath ) = @_;
120*b1cdbd2cSJim Jagielski
121*b1cdbd2cSJim Jagielski	my $windowstemppath = $installer::globals::temppath;
122*b1cdbd2cSJim Jagielski
123*b1cdbd2cSJim Jagielski	if ( $^O =~ /cygwin/i )
124*b1cdbd2cSJim Jagielski	{
125*b1cdbd2cSJim Jagielski		$windowstemppath = $installer::globals::cyg_temppath;
126*b1cdbd2cSJim Jagielski	}
127*b1cdbd2cSJim Jagielski
128*b1cdbd2cSJim Jagielski	$sourcepath =~ s/\Q$windowstemppath\E//;
129*b1cdbd2cSJim Jagielski	$sourcepath =~ s/^\\//;
130*b1cdbd2cSJim Jagielski
131*b1cdbd2cSJim Jagielski	return $sourcepath;
132*b1cdbd2cSJim Jagielski}
133*b1cdbd2cSJim Jagielski
134*b1cdbd2cSJim Jagielski
135*b1cdbd2cSJim Jagielski##########################################################################
136*b1cdbd2cSJim Jagielski# Generation the list, in which the source of the files is connected
137*b1cdbd2cSJim Jagielski# with the cabinet destination file. Because more than one file needs
138*b1cdbd2cSJim Jagielski# to be included into a cab file, this has to be done via ddf files.
139*b1cdbd2cSJim Jagielski##########################################################################
140*b1cdbd2cSJim Jagielski
141*b1cdbd2cSJim Jagielskisub generate_cab_file_list ($$$$)
142*b1cdbd2cSJim Jagielski{
143*b1cdbd2cSJim Jagielski	my ($filesref, $installdir, $ddfdir, $allvariables) = @_;
144*b1cdbd2cSJim Jagielski
145*b1cdbd2cSJim Jagielski	installer::logger::include_header_into_logfile("Generating ddf files");
146*b1cdbd2cSJim Jagielski
147*b1cdbd2cSJim Jagielski	if ( $^O =~ /cygwin/i )
148*b1cdbd2cSJim Jagielski    {
149*b1cdbd2cSJim Jagielski        installer::worker::generate_cygwin_pathes($filesref);
150*b1cdbd2cSJim Jagielski    }
151*b1cdbd2cSJim Jagielski
152*b1cdbd2cSJim Jagielski    # Make sure that all files point to the same cabinet file.
153*b1cdbd2cSJim Jagielski    # Multiple cabinet files are not supported anymore.
154*b1cdbd2cSJim Jagielski    my $cabinetfile = $filesref->[0]->{'cabinet'};
155*b1cdbd2cSJim Jagielski    foreach my $onefile (@$filesref)
156*b1cdbd2cSJim Jagielski    {
157*b1cdbd2cSJim Jagielski        if ($onefile->{'cabinet'} ne $cabinetfile)
158*b1cdbd2cSJim Jagielski        {
159*b1cdbd2cSJim Jagielski            installer::exiter::exit_program(
160*b1cdbd2cSJim Jagielski                "ERROR: multiple cabinet files are not supported",
161*b1cdbd2cSJim Jagielski                "generate_cab_file_list");
162*b1cdbd2cSJim Jagielski        }
163*b1cdbd2cSJim Jagielski    }
164*b1cdbd2cSJim Jagielski
165*b1cdbd2cSJim Jagielski    # Sort files on the sequence number.
166*b1cdbd2cSJim Jagielski    my @sorted_files = sort {$a->{'sequencenumber'} <=> $b->{'sequencenumber'}} @$filesref;
167*b1cdbd2cSJim Jagielski
168*b1cdbd2cSJim Jagielski    my @ddffile = ();
169*b1cdbd2cSJim Jagielski    write_ddf_file_header(\@ddffile, $cabinetfile, $installdir);
170*b1cdbd2cSJim Jagielski    foreach my $onefile (@sorted_files)
171*b1cdbd2cSJim Jagielski    {
172*b1cdbd2cSJim Jagielski        my $styles = $onefile->{'Styles'};
173*b1cdbd2cSJim Jagielski        $styles = "" unless defined $styles;
174*b1cdbd2cSJim Jagielski        if ($styles =~ /\bDONT_PACK\b/)
175*b1cdbd2cSJim Jagielski        {
176*b1cdbd2cSJim Jagielski            $installer::logger::Lang->printf("    excluding '%s' from ddf\n", $onefile->{'uniquename'});
177*b1cdbd2cSJim Jagielski        }
178*b1cdbd2cSJim Jagielski
179*b1cdbd2cSJim Jagielski        my $uniquename = $onefile->{'uniquename'};
180*b1cdbd2cSJim Jagielski        my $sourcepath = $onefile->{'sourcepath'};
181*b1cdbd2cSJim Jagielski        if ( $^O =~ /cygwin/i )
182*b1cdbd2cSJim Jagielski        {
183*b1cdbd2cSJim Jagielski            $sourcepath = $onefile->{'cyg_sourcepath'};
184*b1cdbd2cSJim Jagielski        }
185*b1cdbd2cSJim Jagielski
186*b1cdbd2cSJim Jagielski        # to avoid lines with more than 256 characters, it can be useful to use relative pathes
187*b1cdbd2cSJim Jagielski        if ($allvariables->{'RELATIVE_PATHES_IN_DDF'})
188*b1cdbd2cSJim Jagielski        {
189*b1cdbd2cSJim Jagielski            $sourcepath = make_relative_ddf_path($sourcepath);
190*b1cdbd2cSJim Jagielski        }
191*b1cdbd2cSJim Jagielski
192*b1cdbd2cSJim Jagielski        my $ddfline = "\"" . $sourcepath . "\"" . " " . $uniquename . "\n";
193*b1cdbd2cSJim Jagielski        push(@ddffile, $ddfline);
194*b1cdbd2cSJim Jagielski
195*b1cdbd2cSJim Jagielski        $installer::logger::Lang->printf("    adding '%s' with sequence %d to ddf\n",
196*b1cdbd2cSJim Jagielski            $onefile->{'uniquename'},
197*b1cdbd2cSJim Jagielski            $onefile->{'sequencenumber'});
198*b1cdbd2cSJim Jagielski    }
199*b1cdbd2cSJim Jagielski    # creating the DDF file
200*b1cdbd2cSJim Jagielski
201*b1cdbd2cSJim Jagielski    my $ddffilename = $cabinetfile;
202*b1cdbd2cSJim Jagielski    $ddffilename =~ s/.cab/.ddf/;
203*b1cdbd2cSJim Jagielski    $ddfdir =~ s/\Q$installer::globals::separator\E\s*$//;
204*b1cdbd2cSJim Jagielski    $ddffilename = $ddfdir . $installer::globals::separator . $ddffilename;
205*b1cdbd2cSJim Jagielski
206*b1cdbd2cSJim Jagielski    installer::files::save_file($ddffilename ,\@ddffile);
207*b1cdbd2cSJim Jagielski    $installer::logger::Lang->print("Created ddf file: %s\n", $ddffilename);
208*b1cdbd2cSJim Jagielski
209*b1cdbd2cSJim Jagielski    # lines in ddf files must not be longer than 256 characters
210*b1cdbd2cSJim Jagielski    check_ddf_file(\@ddffile, $ddffilename);
211*b1cdbd2cSJim Jagielski
212*b1cdbd2cSJim Jagielski    # collecting all ddf files
213*b1cdbd2cSJim Jagielski    push(@installer::globals::allddffiles, $ddffilename);
214*b1cdbd2cSJim Jagielski
215*b1cdbd2cSJim Jagielski    # Writing the makecab system call
216*b1cdbd2cSJim Jagielski    # Return a list with all system calls for packaging process.
217*b1cdbd2cSJim Jagielski	my @cabfilelist = ("makecab.exe /V3 /F " . $ddffilename . " 2\>\&1 |" . "\n");
218*b1cdbd2cSJim Jagielski	return \@cabfilelist;
219*b1cdbd2cSJim Jagielski}
220*b1cdbd2cSJim Jagielski
221*b1cdbd2cSJim Jagielski
222*b1cdbd2cSJim Jagielski
223*b1cdbd2cSJim Jagielski#################################################################
224*b1cdbd2cSJim Jagielski# Returning the name of the msi database
225*b1cdbd2cSJim Jagielski#################################################################
226*b1cdbd2cSJim Jagielski
227*b1cdbd2cSJim Jagielskisub get_msidatabasename
228*b1cdbd2cSJim Jagielski{
229*b1cdbd2cSJim Jagielski	my ($allvariableshashref, $language) = @_;
230*b1cdbd2cSJim Jagielski
231*b1cdbd2cSJim Jagielski	my $databasename = $allvariableshashref->{'PRODUCTNAME'} . $allvariableshashref->{'PRODUCTVERSION'};
232*b1cdbd2cSJim Jagielski	$databasename = lc($databasename);
233*b1cdbd2cSJim Jagielski	$databasename =~ s/\.//g;
234*b1cdbd2cSJim Jagielski	$databasename =~ s/\-//g;
235*b1cdbd2cSJim Jagielski	$databasename =~ s/\s//g;
236*b1cdbd2cSJim Jagielski
237*b1cdbd2cSJim Jagielski	# possibility to overwrite the name with variable DATABASENAME
238*b1cdbd2cSJim Jagielski	if ( $allvariableshashref->{'DATABASENAME'} )
239*b1cdbd2cSJim Jagielski	{
240*b1cdbd2cSJim Jagielski		$databasename = $allvariableshashref->{'DATABASENAME'};
241*b1cdbd2cSJim Jagielski	}
242*b1cdbd2cSJim Jagielski
243*b1cdbd2cSJim Jagielski	if ( $language )
244*b1cdbd2cSJim Jagielski	{
245*b1cdbd2cSJim Jagielski		if (!($language eq ""))
246*b1cdbd2cSJim Jagielski		{
247*b1cdbd2cSJim Jagielski			$databasename .= "_$language";
248*b1cdbd2cSJim Jagielski		}
249*b1cdbd2cSJim Jagielski	}
250*b1cdbd2cSJim Jagielski
251*b1cdbd2cSJim Jagielski	$databasename .= ".msi";
252*b1cdbd2cSJim Jagielski
253*b1cdbd2cSJim Jagielski	return $databasename;
254*b1cdbd2cSJim Jagielski}
255*b1cdbd2cSJim Jagielski
256*b1cdbd2cSJim Jagielski#################################################################
257*b1cdbd2cSJim Jagielski# Creating the msi database
258*b1cdbd2cSJim Jagielski# This works only on Windows
259*b1cdbd2cSJim Jagielski#################################################################
260*b1cdbd2cSJim Jagielski
261*b1cdbd2cSJim Jagielskisub create_msi_database
262*b1cdbd2cSJim Jagielski{
263*b1cdbd2cSJim Jagielski	my ($idtdirbase ,$msifilename) = @_;
264*b1cdbd2cSJim Jagielski
265*b1cdbd2cSJim Jagielski	# -f : path containing the idt files
266*b1cdbd2cSJim Jagielski	# -d : msi database, including path
267*b1cdbd2cSJim Jagielski	# -c : create database
268*b1cdbd2cSJim Jagielski	# -i : include the following tables ("*" includes all available tables)
269*b1cdbd2cSJim Jagielski
270*b1cdbd2cSJim Jagielski	my $msidb = "msidb.exe";	# Has to be in the path
271*b1cdbd2cSJim Jagielski	my $extraslash = "";		# Has to be set for non-ActiveState perl
272*b1cdbd2cSJim Jagielski
273*b1cdbd2cSJim Jagielski	installer::logger::include_header_into_logfile("Creating msi database");
274*b1cdbd2cSJim Jagielski
275*b1cdbd2cSJim Jagielski	$idtdirbase = installer::converter::make_path_conform($idtdirbase);
276*b1cdbd2cSJim Jagielski
277*b1cdbd2cSJim Jagielski	$msifilename = installer::converter::make_path_conform($msifilename);
278*b1cdbd2cSJim Jagielski
279*b1cdbd2cSJim Jagielski	if ( $^O =~ /cygwin/i ) {
280*b1cdbd2cSJim Jagielski		# msidb.exe really wants backslashes. (And double escaping because system() expands the string.)
281*b1cdbd2cSJim Jagielski		$idtdirbase =~ s/\//\\\\/g;
282*b1cdbd2cSJim Jagielski		$msifilename =~ s/\//\\\\/g;
283*b1cdbd2cSJim Jagielski		$extraslash = "\\";
284*b1cdbd2cSJim Jagielski	}
285*b1cdbd2cSJim Jagielski	my $systemcall = $msidb . " -f " . $idtdirbase . " -d " . $msifilename . " -c " . "-i " . $extraslash . "*";
286*b1cdbd2cSJim Jagielski
287*b1cdbd2cSJim Jagielski	my $returnvalue = system($systemcall);
288*b1cdbd2cSJim Jagielski
289*b1cdbd2cSJim Jagielski	my $infoline = "Systemcall: $systemcall\n";
290*b1cdbd2cSJim Jagielski	$installer::logger::Lang->print($infoline);
291*b1cdbd2cSJim Jagielski
292*b1cdbd2cSJim Jagielski	if ($returnvalue)
293*b1cdbd2cSJim Jagielski	{
294*b1cdbd2cSJim Jagielski		$infoline = "ERROR: Could not execute $msidb!\n";
295*b1cdbd2cSJim Jagielski		$installer::logger::Lang->print($infoline);
296*b1cdbd2cSJim Jagielski	}
297*b1cdbd2cSJim Jagielski	else
298*b1cdbd2cSJim Jagielski	{
299*b1cdbd2cSJim Jagielski		$infoline = "Success: Executed $msidb successfully!\n";
300*b1cdbd2cSJim Jagielski		$installer::logger::Lang->print($infoline);
301*b1cdbd2cSJim Jagielski	}
302*b1cdbd2cSJim Jagielski}
303*b1cdbd2cSJim Jagielski
304*b1cdbd2cSJim Jagielski#####################################################################
305*b1cdbd2cSJim Jagielski# Returning the value from sis.mlf for Summary Information Stream
306*b1cdbd2cSJim Jagielski#####################################################################
307*b1cdbd2cSJim Jagielski
308*b1cdbd2cSJim Jagielskisub get_value_from_sis_lng
309*b1cdbd2cSJim Jagielski{
310*b1cdbd2cSJim Jagielski	my ($language, $languagefile, $searchstring) = @_;
311*b1cdbd2cSJim Jagielski
312*b1cdbd2cSJim Jagielski	my $language_block = installer::windows::idtglobal::get_language_block_from_language_file($searchstring, $languagefile);
313*b1cdbd2cSJim Jagielski	my $newstring = installer::windows::idtglobal::get_language_string_from_language_block($language_block, $language, $searchstring);
314*b1cdbd2cSJim Jagielski	$newstring = "\"" . $newstring . "\"";
315*b1cdbd2cSJim Jagielski
316*b1cdbd2cSJim Jagielski	return $newstring;
317*b1cdbd2cSJim Jagielski}
318*b1cdbd2cSJim Jagielski
319*b1cdbd2cSJim Jagielski#################################################################
320*b1cdbd2cSJim Jagielski# Returning the msi version for the Summary Information Stream
321*b1cdbd2cSJim Jagielski#################################################################
322*b1cdbd2cSJim Jagielski
323*b1cdbd2cSJim Jagielskisub get_msiversion_for_sis
324*b1cdbd2cSJim Jagielski{
325*b1cdbd2cSJim Jagielski	my $msiversion = "200";
326*b1cdbd2cSJim Jagielski	return $msiversion;
327*b1cdbd2cSJim Jagielski}
328*b1cdbd2cSJim Jagielski
329*b1cdbd2cSJim Jagielski#################################################################
330*b1cdbd2cSJim Jagielski# Returning the word count for the Summary Information Stream
331*b1cdbd2cSJim Jagielski#################################################################
332*b1cdbd2cSJim Jagielski
333*b1cdbd2cSJim Jagielskisub get_wordcount_for_sis
334*b1cdbd2cSJim Jagielski{
335*b1cdbd2cSJim Jagielski	my $wordcount = "0";
336*b1cdbd2cSJim Jagielski	return $wordcount;
337*b1cdbd2cSJim Jagielski}
338*b1cdbd2cSJim Jagielski
339*b1cdbd2cSJim Jagielski#################################################################
340*b1cdbd2cSJim Jagielski# Returning the codepage for the Summary Information Stream
341*b1cdbd2cSJim Jagielski#################################################################
342*b1cdbd2cSJim Jagielski
343*b1cdbd2cSJim Jagielskisub get_codepage_for_sis
344*b1cdbd2cSJim Jagielski{
345*b1cdbd2cSJim Jagielski	my ( $language ) = @_;
346*b1cdbd2cSJim Jagielski
347*b1cdbd2cSJim Jagielski	my $codepage = installer::windows::language::get_windows_encoding($language);
348*b1cdbd2cSJim Jagielski
349*b1cdbd2cSJim Jagielski	# Codepage 65001 does not work in Summary Information Stream
350*b1cdbd2cSJim Jagielski	if ( $codepage == 65001 ) { $codepage = 0; }
351*b1cdbd2cSJim Jagielski
352*b1cdbd2cSJim Jagielski	# my $codepage = "1252";	# determine dynamically in a function
353*b1cdbd2cSJim Jagielski	# my $codepage = "65001";		# UTF-8
354*b1cdbd2cSJim Jagielski	return $codepage;
355*b1cdbd2cSJim Jagielski}
356*b1cdbd2cSJim Jagielski
357*b1cdbd2cSJim Jagielski#################################################################
358*b1cdbd2cSJim Jagielski# Returning the template for the Summary Information Stream
359*b1cdbd2cSJim Jagielski#################################################################
360*b1cdbd2cSJim Jagielski
361*b1cdbd2cSJim Jagielskisub get_template_for_sis
362*b1cdbd2cSJim Jagielski{
363*b1cdbd2cSJim Jagielski	my ( $language, $allvariables ) = @_;
364*b1cdbd2cSJim Jagielski
365*b1cdbd2cSJim Jagielski	my $windowslanguage = installer::windows::language::get_windows_language($language);
366*b1cdbd2cSJim Jagielski
367*b1cdbd2cSJim Jagielski	my $architecture = "Intel";
368*b1cdbd2cSJim Jagielski
369*b1cdbd2cSJim Jagielski	# Adding 256, if this is a 64 bit installation set.
370*b1cdbd2cSJim Jagielski	if (( $allvariables->{'64BITPRODUCT'} ) && ( $allvariables->{'64BITPRODUCT'} == 1 )) { $architecture = "x64"; }
371*b1cdbd2cSJim Jagielski
372*b1cdbd2cSJim Jagielski	my $value = "\"" . $architecture . ";" . $windowslanguage;	# adding the Windows language
373*b1cdbd2cSJim Jagielski
374*b1cdbd2cSJim Jagielski	$value = $value . "\"";						# adding ending '"'
375*b1cdbd2cSJim Jagielski
376*b1cdbd2cSJim Jagielski	return $value ;
377*b1cdbd2cSJim Jagielski}
378*b1cdbd2cSJim Jagielski
379*b1cdbd2cSJim Jagielski#################################################################
380*b1cdbd2cSJim Jagielski# Returning the PackageCode for the Summary Information Stream
381*b1cdbd2cSJim Jagielski#################################################################
382*b1cdbd2cSJim Jagielski
383*b1cdbd2cSJim Jagielskisub get_packagecode_for_sis
384*b1cdbd2cSJim Jagielski{
385*b1cdbd2cSJim Jagielski	# always generating a new package code for each package
386*b1cdbd2cSJim Jagielski
387*b1cdbd2cSJim Jagielski	my $guid = "\{" . create_guid() . "\}";
388*b1cdbd2cSJim Jagielski
389*b1cdbd2cSJim Jagielski	my $infoline = "PackageCode: $guid\n";
390*b1cdbd2cSJim Jagielski	$installer::logger::Lang->print($infoline);
391*b1cdbd2cSJim Jagielski
392*b1cdbd2cSJim Jagielski	return $guid;
393*b1cdbd2cSJim Jagielski}
394*b1cdbd2cSJim Jagielski
395*b1cdbd2cSJim Jagielski#################################################################
396*b1cdbd2cSJim Jagielski# Returning the title for the Summary Information Stream
397*b1cdbd2cSJim Jagielski#################################################################
398*b1cdbd2cSJim Jagielski
399*b1cdbd2cSJim Jagielskisub get_title_for_sis
400*b1cdbd2cSJim Jagielski{
401*b1cdbd2cSJim Jagielski	my ( $language, $languagefile, $searchstring ) = @_;
402*b1cdbd2cSJim Jagielski
403*b1cdbd2cSJim Jagielski	my $title = get_value_from_sis_lng($language, $languagefile, $searchstring );
404*b1cdbd2cSJim Jagielski
405*b1cdbd2cSJim Jagielski	return $title;
406*b1cdbd2cSJim Jagielski}
407*b1cdbd2cSJim Jagielski
408*b1cdbd2cSJim Jagielski#################################################################
409*b1cdbd2cSJim Jagielski# Returning the author for the Summary Information Stream
410*b1cdbd2cSJim Jagielski#################################################################
411*b1cdbd2cSJim Jagielski
412*b1cdbd2cSJim Jagielskisub get_author_for_sis
413*b1cdbd2cSJim Jagielski{
414*b1cdbd2cSJim Jagielski	my $author = $installer::globals::longmanufacturer;
415*b1cdbd2cSJim Jagielski
416*b1cdbd2cSJim Jagielski	$author = "\"" . $author . "\"";
417*b1cdbd2cSJim Jagielski
418*b1cdbd2cSJim Jagielski	return $author;
419*b1cdbd2cSJim Jagielski}
420*b1cdbd2cSJim Jagielski
421*b1cdbd2cSJim Jagielski#################################################################
422*b1cdbd2cSJim Jagielski# Returning the subject for the Summary Information Stream
423*b1cdbd2cSJim Jagielski#################################################################
424*b1cdbd2cSJim Jagielski
425*b1cdbd2cSJim Jagielskisub get_subject_for_sis
426*b1cdbd2cSJim Jagielski{
427*b1cdbd2cSJim Jagielski	my ( $allvariableshashref ) = @_;
428*b1cdbd2cSJim Jagielski
429*b1cdbd2cSJim Jagielski	my $subject = $allvariableshashref->{'PRODUCTNAME'} . " " . $allvariableshashref->{'PRODUCTVERSION'};
430*b1cdbd2cSJim Jagielski
431*b1cdbd2cSJim Jagielski	$subject = "\"" . $subject . "\"";
432*b1cdbd2cSJim Jagielski
433*b1cdbd2cSJim Jagielski	return $subject;
434*b1cdbd2cSJim Jagielski}
435*b1cdbd2cSJim Jagielski
436*b1cdbd2cSJim Jagielski#################################################################
437*b1cdbd2cSJim Jagielski# Returning the comment for the Summary Information Stream
438*b1cdbd2cSJim Jagielski#################################################################
439*b1cdbd2cSJim Jagielski
440*b1cdbd2cSJim Jagielskisub get_comment_for_sis
441*b1cdbd2cSJim Jagielski{
442*b1cdbd2cSJim Jagielski	my ( $language, $languagefile, $searchstring ) = @_;
443*b1cdbd2cSJim Jagielski
444*b1cdbd2cSJim Jagielski	my $comment = get_value_from_sis_lng($language, $languagefile, $searchstring );
445*b1cdbd2cSJim Jagielski
446*b1cdbd2cSJim Jagielski	return $comment;
447*b1cdbd2cSJim Jagielski}
448*b1cdbd2cSJim Jagielski
449*b1cdbd2cSJim Jagielski#################################################################
450*b1cdbd2cSJim Jagielski# Returning the keywords for the Summary Information Stream
451*b1cdbd2cSJim Jagielski#################################################################
452*b1cdbd2cSJim Jagielski
453*b1cdbd2cSJim Jagielskisub get_keywords_for_sis
454*b1cdbd2cSJim Jagielski{
455*b1cdbd2cSJim Jagielski	my ( $language, $languagefile, $searchstring ) = @_;
456*b1cdbd2cSJim Jagielski
457*b1cdbd2cSJim Jagielski	my $keywords = get_value_from_sis_lng($language, $languagefile, $searchstring );
458*b1cdbd2cSJim Jagielski
459*b1cdbd2cSJim Jagielski	return $keywords;
460*b1cdbd2cSJim Jagielski}
461*b1cdbd2cSJim Jagielski
462*b1cdbd2cSJim Jagielski######################################################################
463*b1cdbd2cSJim Jagielski# Returning the application name for the Summary Information Stream
464*b1cdbd2cSJim Jagielski######################################################################
465*b1cdbd2cSJim Jagielski
466*b1cdbd2cSJim Jagielskisub get_appname_for_sis
467*b1cdbd2cSJim Jagielski{
468*b1cdbd2cSJim Jagielski	my ( $language, $languagefile, $searchstring ) = @_;
469*b1cdbd2cSJim Jagielski
470*b1cdbd2cSJim Jagielski	my $appname = get_value_from_sis_lng($language, $languagefile, $searchstring );
471*b1cdbd2cSJim Jagielski
472*b1cdbd2cSJim Jagielski	return $appname;
473*b1cdbd2cSJim Jagielski}
474*b1cdbd2cSJim Jagielski
475*b1cdbd2cSJim Jagielski######################################################################
476*b1cdbd2cSJim Jagielski# Returning the security for the Summary Information Stream
477*b1cdbd2cSJim Jagielski######################################################################
478*b1cdbd2cSJim Jagielski
479*b1cdbd2cSJim Jagielskisub get_security_for_sis
480*b1cdbd2cSJim Jagielski{
481*b1cdbd2cSJim Jagielski	my $security = "0";
482*b1cdbd2cSJim Jagielski	return $security;
483*b1cdbd2cSJim Jagielski}
484*b1cdbd2cSJim Jagielski
485*b1cdbd2cSJim Jagielski#################################################################
486*b1cdbd2cSJim Jagielski# Writing the Summary information stream into the msi database
487*b1cdbd2cSJim Jagielski# This works only on Windows
488*b1cdbd2cSJim Jagielski#################################################################
489*b1cdbd2cSJim Jagielski
490*b1cdbd2cSJim Jagielskisub write_summary_into_msi_database
491*b1cdbd2cSJim Jagielski{
492*b1cdbd2cSJim Jagielski	my ($msifilename, $language, $languagefile, $allvariableshashref) = @_;
493*b1cdbd2cSJim Jagielski
494*b1cdbd2cSJim Jagielski	# -g : requrired msi version
495*b1cdbd2cSJim Jagielski	# -c : codepage
496*b1cdbd2cSJim Jagielski	# -p : template
497*b1cdbd2cSJim Jagielski
498*b1cdbd2cSJim Jagielski	installer::logger::include_header_into_logfile("Writing summary information stream");
499*b1cdbd2cSJim Jagielski
500*b1cdbd2cSJim Jagielski	my $msiinfo = "msiinfo.exe";	# Has to be in the path
501*b1cdbd2cSJim Jagielski
502*b1cdbd2cSJim Jagielski	my $sislanguage = "en-US";	# title, comment, keyword and appname alway in english
503*b1cdbd2cSJim Jagielski
504*b1cdbd2cSJim Jagielski	my $msiversion = get_msiversion_for_sis();
505*b1cdbd2cSJim Jagielski	my $codepage = get_codepage_for_sis($language);
506*b1cdbd2cSJim Jagielski	my $template = get_template_for_sis($language, $allvariableshashref);
507*b1cdbd2cSJim Jagielski	my $guid = get_packagecode_for_sis();
508*b1cdbd2cSJim Jagielski	my $title = get_title_for_sis($sislanguage,$languagefile, "OOO_SIS_TITLE");
509*b1cdbd2cSJim Jagielski	my $author = get_author_for_sis();
510*b1cdbd2cSJim Jagielski	my $subject = get_subject_for_sis($allvariableshashref);
511*b1cdbd2cSJim Jagielski	my $comment = get_comment_for_sis($sislanguage,$languagefile, "OOO_SIS_COMMENT");
512*b1cdbd2cSJim Jagielski	my $keywords = get_keywords_for_sis($sislanguage,$languagefile, "OOO_SIS_KEYWORDS");
513*b1cdbd2cSJim Jagielski	my $appname = get_appname_for_sis($sislanguage,$languagefile, "OOO_SIS_APPNAME");
514*b1cdbd2cSJim Jagielski	my $security = get_security_for_sis();
515*b1cdbd2cSJim Jagielski	my $wordcount = get_wordcount_for_sis();
516*b1cdbd2cSJim Jagielski
517*b1cdbd2cSJim Jagielski	$msifilename = installer::converter::make_path_conform($msifilename);
518*b1cdbd2cSJim Jagielski
519*b1cdbd2cSJim Jagielski	my $systemcall = $msiinfo . " " . $msifilename . " -g " . $msiversion . " -c " . $codepage
520*b1cdbd2cSJim Jagielski					. " -p " . $template . " -v " . $guid . " -t " . $title . " -a " . $author
521*b1cdbd2cSJim Jagielski					. " -j " . $subject . " -o " . $comment . " -k " . $keywords . " -n " . $appname
522*b1cdbd2cSJim Jagielski					. " -u " . $security . " -w " . $wordcount;
523*b1cdbd2cSJim Jagielski
524*b1cdbd2cSJim Jagielski	my $returnvalue = system($systemcall);
525*b1cdbd2cSJim Jagielski
526*b1cdbd2cSJim Jagielski	my $infoline = "Systemcall: $systemcall\n";
527*b1cdbd2cSJim Jagielski	$installer::logger::Lang->print($infoline);
528*b1cdbd2cSJim Jagielski
529*b1cdbd2cSJim Jagielski	if ($returnvalue)
530*b1cdbd2cSJim Jagielski	{
531*b1cdbd2cSJim Jagielski		$infoline = "ERROR: Could not execute $msiinfo!\n";
532*b1cdbd2cSJim Jagielski		$installer::logger::Lang->print($infoline);
533*b1cdbd2cSJim Jagielski	}
534*b1cdbd2cSJim Jagielski	else
535*b1cdbd2cSJim Jagielski	{
536*b1cdbd2cSJim Jagielski		$infoline = "Success: Executed $msiinfo successfully!\n";
537*b1cdbd2cSJim Jagielski		$installer::logger::Lang->print($infoline);
538*b1cdbd2cSJim Jagielski	}
539*b1cdbd2cSJim Jagielski}
540*b1cdbd2cSJim Jagielski
541*b1cdbd2cSJim Jagielski#########################################################################
542*b1cdbd2cSJim Jagielski# For more than one language in the installation set:
543*b1cdbd2cSJim Jagielski# Use one database and create Transformations for all other languages
544*b1cdbd2cSJim Jagielski#########################################################################
545*b1cdbd2cSJim Jagielski
546*b1cdbd2cSJim Jagielskisub create_transforms
547*b1cdbd2cSJim Jagielski{
548*b1cdbd2cSJim Jagielski	my ($languagesarray, $defaultlanguage, $installdir, $allvariableshashref) = @_;
549*b1cdbd2cSJim Jagielski
550*b1cdbd2cSJim Jagielski	installer::logger::include_header_into_logfile("Creating Transforms");
551*b1cdbd2cSJim Jagielski
552*b1cdbd2cSJim Jagielski	my $msitran = "msitran.exe";	# Has to be in the path
553*b1cdbd2cSJim Jagielski
554*b1cdbd2cSJim Jagielski	$installdir = installer::converter::make_path_conform($installdir);
555*b1cdbd2cSJim Jagielski
556*b1cdbd2cSJim Jagielski	# Syntax for creating a transformation
557*b1cdbd2cSJim Jagielski	# msitran.exe -g <baseDB> <referenceDB> <transformfile> [<errorhandling>}
558*b1cdbd2cSJim Jagielski
559*b1cdbd2cSJim Jagielski	my $basedbname = get_msidatabasename($allvariableshashref, $defaultlanguage);
560*b1cdbd2cSJim Jagielski	$basedbname = $installdir . $installer::globals::separator . $basedbname;
561*b1cdbd2cSJim Jagielski
562*b1cdbd2cSJim Jagielski	my $errorhandling = "f";	# Suppress "change codepage" error
563*b1cdbd2cSJim Jagielski
564*b1cdbd2cSJim Jagielski	# Iterating over all files
565*b1cdbd2cSJim Jagielski
566*b1cdbd2cSJim Jagielski	foreach ( @{$languagesarray} )
567*b1cdbd2cSJim Jagielski	{
568*b1cdbd2cSJim Jagielski		my $onelanguage = $_;
569*b1cdbd2cSJim Jagielski
570*b1cdbd2cSJim Jagielski		if ( $onelanguage eq $defaultlanguage ) { next; }
571*b1cdbd2cSJim Jagielski
572*b1cdbd2cSJim Jagielski		my $referencedbname = get_msidatabasename($allvariableshashref, $onelanguage);
573*b1cdbd2cSJim Jagielski		$referencedbname = $installdir . $installer::globals::separator . $referencedbname;
574*b1cdbd2cSJim Jagielski
575*b1cdbd2cSJim Jagielski		my $transformfile = $installdir . $installer::globals::separator . "trans_" . $onelanguage . ".mst";
576*b1cdbd2cSJim Jagielski
577*b1cdbd2cSJim Jagielski		my $systemcall = $msitran . " " . " -g " . $basedbname . " " . $referencedbname . " " . $transformfile . " " . $errorhandling;
578*b1cdbd2cSJim Jagielski
579*b1cdbd2cSJim Jagielski		my $returnvalue = system($systemcall);
580*b1cdbd2cSJim Jagielski
581*b1cdbd2cSJim Jagielski		my $infoline = "Systemcall: $systemcall\n";
582*b1cdbd2cSJim Jagielski		$installer::logger::Lang->print($infoline);
583*b1cdbd2cSJim Jagielski
584*b1cdbd2cSJim Jagielski		# Problem: msitran.exe in version 4.0 always returns "1", even if no failure occured.
585*b1cdbd2cSJim Jagielski		# Therefore it has to be checked, if this is version 4.0. If yes, if the mst file
586*b1cdbd2cSJim Jagielski		# exists and if it is larger than 0 bytes. If this is true, then no error occured.
587*b1cdbd2cSJim Jagielski		# File Version of msitran.exe: 4.0.6000.16384 has checksum: "b66190a70145a57773ec769e16777b29".
588*b1cdbd2cSJim Jagielski		# Same for msitran.exe from wntmsci12: "aa25d3445b94ffde8ef0c1efb77a56b8"
589*b1cdbd2cSJim Jagielski
590*b1cdbd2cSJim Jagielski		if ($returnvalue)
591*b1cdbd2cSJim Jagielski		{
592*b1cdbd2cSJim Jagielski			$infoline = "WARNING: Returnvalue of $msitran is not 0. Checking version of $msitran!\n";
593*b1cdbd2cSJim Jagielski			$installer::logger::Lang->print($infoline);
594*b1cdbd2cSJim Jagielski
595*b1cdbd2cSJim Jagielski			open(FILE, "<$installer::globals::msitranpath") or die "ERROR: Can't open $installer::globals::msitranpath for creating file hash";
596*b1cdbd2cSJim Jagielski			binmode(FILE);
597*b1cdbd2cSJim Jagielski			my $digest = Digest::MD5->new->addfile(*FILE)->hexdigest;
598*b1cdbd2cSJim Jagielski			close(FILE);
599*b1cdbd2cSJim Jagielski
600*b1cdbd2cSJim Jagielski			my @problemchecksums = ("b66190a70145a57773ec769e16777b29", "aa25d3445b94ffde8ef0c1efb77a56b8");
601*b1cdbd2cSJim Jagielski			my $isproblemchecksum = 0;
602*b1cdbd2cSJim Jagielski
603*b1cdbd2cSJim Jagielski			foreach my $problemchecksum ( @problemchecksums )
604*b1cdbd2cSJim Jagielski			{
605*b1cdbd2cSJim Jagielski				$infoline = "Checksum of problematic MsiTran.exe: $problemchecksum\n";
606*b1cdbd2cSJim Jagielski				$installer::logger::Lang->print($infoline);
607*b1cdbd2cSJim Jagielski				$infoline = "Checksum of used MsiTran.exe: $digest\n";
608*b1cdbd2cSJim Jagielski				$installer::logger::Lang->print($infoline);
609*b1cdbd2cSJim Jagielski				if ( $digest eq $problemchecksum ) { $isproblemchecksum = 1; }
610*b1cdbd2cSJim Jagielski			}
611*b1cdbd2cSJim Jagielski
612*b1cdbd2cSJim Jagielski			if ( $isproblemchecksum )
613*b1cdbd2cSJim Jagielski			{
614*b1cdbd2cSJim Jagielski				# Check existence of mst
615*b1cdbd2cSJim Jagielski				if ( -f $transformfile )
616*b1cdbd2cSJim Jagielski				{
617*b1cdbd2cSJim Jagielski					$infoline = "File $transformfile exists.\n";
618*b1cdbd2cSJim Jagielski					$installer::logger::Lang->print($infoline);
619*b1cdbd2cSJim Jagielski					my $filesize = ( -s $transformfile );
620*b1cdbd2cSJim Jagielski					$infoline = "Size of $transformfile: $filesize\n";
621*b1cdbd2cSJim Jagielski					$installer::logger::Lang->print($infoline);
622*b1cdbd2cSJim Jagielski
623*b1cdbd2cSJim Jagielski					if ( $filesize > 0 )
624*b1cdbd2cSJim Jagielski					{
625*b1cdbd2cSJim Jagielski						$infoline = "Info: Returnvalue $returnvalue of $msitran is no problem :-) .\n";
626*b1cdbd2cSJim Jagielski						$installer::logger::Lang->print($infoline);
627*b1cdbd2cSJim Jagielski						$returnvalue = 0; # reset the error
628*b1cdbd2cSJim Jagielski					}
629*b1cdbd2cSJim Jagielski					else
630*b1cdbd2cSJim Jagielski					{
631*b1cdbd2cSJim Jagielski						$infoline = "Filesize indicates that an error occured.\n";
632*b1cdbd2cSJim Jagielski						$installer::logger::Lang->print($infoline);
633*b1cdbd2cSJim Jagielski					}
634*b1cdbd2cSJim Jagielski				}
635*b1cdbd2cSJim Jagielski				else
636*b1cdbd2cSJim Jagielski				{
637*b1cdbd2cSJim Jagielski					$infoline = "File $transformfile does not exist -> An error occured.\n";
638*b1cdbd2cSJim Jagielski					$installer::logger::Lang->print($infoline);
639*b1cdbd2cSJim Jagielski				}
640*b1cdbd2cSJim Jagielski			}
641*b1cdbd2cSJim Jagielski			else
642*b1cdbd2cSJim Jagielski			{
643*b1cdbd2cSJim Jagielski				$infoline = "This is not a problematic version of msitran.exe. Therefore the error is not caused by problematic msitran.exe.\n";
644*b1cdbd2cSJim Jagielski				$installer::logger::Lang->print($infoline);
645*b1cdbd2cSJim Jagielski			}
646*b1cdbd2cSJim Jagielski		}
647*b1cdbd2cSJim Jagielski
648*b1cdbd2cSJim Jagielski		if ($returnvalue)
649*b1cdbd2cSJim Jagielski		{
650*b1cdbd2cSJim Jagielski			$infoline = "ERROR: Could not execute $msitran!\n";
651*b1cdbd2cSJim Jagielski			$installer::logger::Lang->print($infoline);
652*b1cdbd2cSJim Jagielski		}
653*b1cdbd2cSJim Jagielski		else
654*b1cdbd2cSJim Jagielski		{
655*b1cdbd2cSJim Jagielski			$infoline = "Success: Executed $msitran successfully!\n";
656*b1cdbd2cSJim Jagielski			$installer::logger::Lang->print($infoline);
657*b1cdbd2cSJim Jagielski		}
658*b1cdbd2cSJim Jagielski
659*b1cdbd2cSJim Jagielski		# The reference database can be deleted
660*b1cdbd2cSJim Jagielski
661*b1cdbd2cSJim Jagielski		my $result = unlink($referencedbname);
662*b1cdbd2cSJim Jagielski		# $result contains the number of deleted files
663*b1cdbd2cSJim Jagielski
664*b1cdbd2cSJim Jagielski		if ( $result == 0 )
665*b1cdbd2cSJim Jagielski		{
666*b1cdbd2cSJim Jagielski			$infoline = "ERROR: Could not remove file $$referencedbname !\n";
667*b1cdbd2cSJim Jagielski			$installer::logger::Lang->print($infoline);
668*b1cdbd2cSJim Jagielski			installer::exiter::exit_program($infoline, "create_transforms");
669*b1cdbd2cSJim Jagielski		}
670*b1cdbd2cSJim Jagielski	}
671*b1cdbd2cSJim Jagielski}
672*b1cdbd2cSJim Jagielski
673*b1cdbd2cSJim Jagielski#########################################################################
674*b1cdbd2cSJim Jagielski# The default language msi database does not need to contain
675*b1cdbd2cSJim Jagielski# the language in the database name. Therefore the file
676*b1cdbd2cSJim Jagielski# is renamed. Example: "openofficeorg20_01.msi" to "openofficeorg20.msi"
677*b1cdbd2cSJim Jagielski#########################################################################
678*b1cdbd2cSJim Jagielski
679*b1cdbd2cSJim Jagielskisub rename_msi_database_in_installset
680*b1cdbd2cSJim Jagielski{
681*b1cdbd2cSJim Jagielski	my ($defaultlanguage, $installdir, $allvariableshashref) = @_;
682*b1cdbd2cSJim Jagielski
683*b1cdbd2cSJim Jagielski	installer::logger::include_header_into_logfile("Renaming msi database");
684*b1cdbd2cSJim Jagielski
685*b1cdbd2cSJim Jagielski	my $olddatabasename = get_msidatabasename($allvariableshashref, $defaultlanguage);
686*b1cdbd2cSJim Jagielski	$olddatabasename = $installdir . $installer::globals::separator . $olddatabasename;
687*b1cdbd2cSJim Jagielski
688*b1cdbd2cSJim Jagielski	my $newdatabasename = get_msidatabasename($allvariableshashref);
689*b1cdbd2cSJim Jagielski
690*b1cdbd2cSJim Jagielski	$installer::globals::shortmsidatabasename = $newdatabasename;
691*b1cdbd2cSJim Jagielski
692*b1cdbd2cSJim Jagielski	$newdatabasename = $installdir . $installer::globals::separator . $newdatabasename;
693*b1cdbd2cSJim Jagielski
694*b1cdbd2cSJim Jagielski	installer::systemactions::rename_one_file($olddatabasename, $newdatabasename);
695*b1cdbd2cSJim Jagielski
696*b1cdbd2cSJim Jagielski	$installer::globals::msidatabasename = $newdatabasename;
697*b1cdbd2cSJim Jagielski}
698*b1cdbd2cSJim Jagielski
699*b1cdbd2cSJim Jagielski#########################################################################
700*b1cdbd2cSJim Jagielski# Adding the language to the name of the msi databasename,
701*b1cdbd2cSJim Jagielski# if this is required (ADDLANGUAGEINDATABASENAME)
702*b1cdbd2cSJim Jagielski#########################################################################
703*b1cdbd2cSJim Jagielski
704*b1cdbd2cSJim Jagielskisub add_language_to_msi_database
705*b1cdbd2cSJim Jagielski{
706*b1cdbd2cSJim Jagielski	my ($defaultlanguage, $installdir, $allvariables) = @_;
707*b1cdbd2cSJim Jagielski
708*b1cdbd2cSJim Jagielski	my $languagestring = $defaultlanguage;
709*b1cdbd2cSJim Jagielski	if ( $allvariables->{'USELANGUAGECODE'} ) { $languagestring = installer::windows::language::get_windows_language($defaultlanguage); }
710*b1cdbd2cSJim Jagielski	my $newdatabasename = $installer::globals::shortmsidatabasename;
711*b1cdbd2cSJim Jagielski	$newdatabasename =~ s/\.msi\s*$/_$languagestring\.msi/;
712*b1cdbd2cSJim Jagielski	$installer::globals::shortmsidatabasename = $newdatabasename;
713*b1cdbd2cSJim Jagielski	$newdatabasename = $installdir . $installer::globals::separator . $newdatabasename;
714*b1cdbd2cSJim Jagielski
715*b1cdbd2cSJim Jagielski	my $olddatabasename = $installer::globals::msidatabasename;
716*b1cdbd2cSJim Jagielski
717*b1cdbd2cSJim Jagielski	installer::systemactions::rename_one_file($olddatabasename, $newdatabasename);
718*b1cdbd2cSJim Jagielski
719*b1cdbd2cSJim Jagielski	$installer::globals::msidatabasename = $newdatabasename;
720*b1cdbd2cSJim Jagielski}
721*b1cdbd2cSJim Jagielski
722*b1cdbd2cSJim Jagielski##########################################################################
723*b1cdbd2cSJim Jagielski# Writing the databasename into the setup.ini.
724*b1cdbd2cSJim Jagielski##########################################################################
725*b1cdbd2cSJim Jagielski
726*b1cdbd2cSJim Jagielskisub put_databasename_into_setupini
727*b1cdbd2cSJim Jagielski{
728*b1cdbd2cSJim Jagielski	my ($setupinifile, $allvariableshashref) = @_;
729*b1cdbd2cSJim Jagielski
730*b1cdbd2cSJim Jagielski	my $databasename = get_msidatabasename($allvariableshashref);
731*b1cdbd2cSJim Jagielski	my $line = "database=" . $databasename . "\n";
732*b1cdbd2cSJim Jagielski
733*b1cdbd2cSJim Jagielski	push(@{$setupinifile}, $line);
734*b1cdbd2cSJim Jagielski}
735*b1cdbd2cSJim Jagielski
736*b1cdbd2cSJim Jagielski##########################################################################
737*b1cdbd2cSJim Jagielski# Writing the required msi version into setup.ini
738*b1cdbd2cSJim Jagielski##########################################################################
739*b1cdbd2cSJim Jagielski
740*b1cdbd2cSJim Jagielskisub put_msiversion_into_setupini
741*b1cdbd2cSJim Jagielski{
742*b1cdbd2cSJim Jagielski	my ($setupinifile) = @_;
743*b1cdbd2cSJim Jagielski
744*b1cdbd2cSJim Jagielski	my $msiversion = "2.0";
745*b1cdbd2cSJim Jagielski	my $line = "msiversion=" . $msiversion . "\n";
746*b1cdbd2cSJim Jagielski
747*b1cdbd2cSJim Jagielski	push(@{$setupinifile}, $line);
748*b1cdbd2cSJim Jagielski}
749*b1cdbd2cSJim Jagielski
750*b1cdbd2cSJim Jagielski##########################################################################
751*b1cdbd2cSJim Jagielski# Writing the productname into setup.ini
752*b1cdbd2cSJim Jagielski##########################################################################
753*b1cdbd2cSJim Jagielski
754*b1cdbd2cSJim Jagielskisub put_productname_into_setupini
755*b1cdbd2cSJim Jagielski{
756*b1cdbd2cSJim Jagielski	my ($setupinifile, $allvariableshashref) = @_;
757*b1cdbd2cSJim Jagielski
758*b1cdbd2cSJim Jagielski	my $productname = $allvariableshashref->{'PRODUCTNAME'};
759*b1cdbd2cSJim Jagielski	my $line = "productname=" . $productname . "\n";
760*b1cdbd2cSJim Jagielski
761*b1cdbd2cSJim Jagielski	push(@{$setupinifile}, $line);
762*b1cdbd2cSJim Jagielski}
763*b1cdbd2cSJim Jagielski
764*b1cdbd2cSJim Jagielski##########################################################################
765*b1cdbd2cSJim Jagielski# Writing the productcode into setup.ini
766*b1cdbd2cSJim Jagielski##########################################################################
767*b1cdbd2cSJim Jagielski
768*b1cdbd2cSJim Jagielskisub put_productcode_into_setupini
769*b1cdbd2cSJim Jagielski{
770*b1cdbd2cSJim Jagielski	my ($setupinifile) = @_;
771*b1cdbd2cSJim Jagielski
772*b1cdbd2cSJim Jagielski	my $productcode = $installer::globals::productcode;
773*b1cdbd2cSJim Jagielski	my $line = "productcode=" . $productcode . "\n";
774*b1cdbd2cSJim Jagielski
775*b1cdbd2cSJim Jagielski	push(@{$setupinifile}, $line);
776*b1cdbd2cSJim Jagielski}
777*b1cdbd2cSJim Jagielski
778*b1cdbd2cSJim Jagielski##########################################################################
779*b1cdbd2cSJim Jagielski# Writing the ProductVersion from Property table into setup.ini
780*b1cdbd2cSJim Jagielski##########################################################################
781*b1cdbd2cSJim Jagielski
782*b1cdbd2cSJim Jagielskisub put_productversion_into_setupini
783*b1cdbd2cSJim Jagielski{
784*b1cdbd2cSJim Jagielski	my ($setupinifile) = @_;
785*b1cdbd2cSJim Jagielski
786*b1cdbd2cSJim Jagielski	my $line = "productversion=" . $installer::globals::msiproductversion . "\n";
787*b1cdbd2cSJim Jagielski	push(@{$setupinifile}, $line);
788*b1cdbd2cSJim Jagielski}
789*b1cdbd2cSJim Jagielski
790*b1cdbd2cSJim Jagielski##########################################################################
791*b1cdbd2cSJim Jagielski# Writing the key for Minor Upgrades into setup.ini
792*b1cdbd2cSJim Jagielski##########################################################################
793*b1cdbd2cSJim Jagielski
794*b1cdbd2cSJim Jagielskisub put_upgradekey_into_setupini
795*b1cdbd2cSJim Jagielski{
796*b1cdbd2cSJim Jagielski	my ($setupinifile) = @_;
797*b1cdbd2cSJim Jagielski
798*b1cdbd2cSJim Jagielski	if ( $installer::globals::minorupgradekey ne "" )
799*b1cdbd2cSJim Jagielski	{
800*b1cdbd2cSJim Jagielski		my $line = "upgradekey=" . $installer::globals::minorupgradekey . "\n";
801*b1cdbd2cSJim Jagielski		push(@{$setupinifile}, $line);
802*b1cdbd2cSJim Jagielski	}
803*b1cdbd2cSJim Jagielski}
804*b1cdbd2cSJim Jagielski
805*b1cdbd2cSJim Jagielski##########################################################################
806*b1cdbd2cSJim Jagielski# Writing the number of languages into setup.ini
807*b1cdbd2cSJim Jagielski##########################################################################
808*b1cdbd2cSJim Jagielski
809*b1cdbd2cSJim Jagielskisub put_languagecount_into_setupini
810*b1cdbd2cSJim Jagielski{
811*b1cdbd2cSJim Jagielski	my ($setupinifile, $languagesarray) = @_;
812*b1cdbd2cSJim Jagielski
813*b1cdbd2cSJim Jagielski	my $languagecount = $#{$languagesarray} + 1;
814*b1cdbd2cSJim Jagielski	my $line = "count=" . $languagecount . "\n";
815*b1cdbd2cSJim Jagielski
816*b1cdbd2cSJim Jagielski	push(@{$setupinifile}, $line);
817*b1cdbd2cSJim Jagielski}
818*b1cdbd2cSJim Jagielski
819*b1cdbd2cSJim Jagielski##########################################################################
820*b1cdbd2cSJim Jagielski# Writing the defaultlanguage into setup.ini
821*b1cdbd2cSJim Jagielski##########################################################################
822*b1cdbd2cSJim Jagielski
823*b1cdbd2cSJim Jagielskisub put_defaultlanguage_into_setupini
824*b1cdbd2cSJim Jagielski{
825*b1cdbd2cSJim Jagielski	my ($setupinifile, $defaultlanguage) = @_;
826*b1cdbd2cSJim Jagielski
827*b1cdbd2cSJim Jagielski	my $windowslanguage = installer::windows::language::get_windows_language($defaultlanguage);
828*b1cdbd2cSJim Jagielski	my $line = "default=" . $windowslanguage . "\n";
829*b1cdbd2cSJim Jagielski	push(@{$setupinifile}, $line);
830*b1cdbd2cSJim Jagielski}
831*b1cdbd2cSJim Jagielski
832*b1cdbd2cSJim Jagielski##########################################################################
833*b1cdbd2cSJim Jagielski# Writing the information about transformations into setup.ini
834*b1cdbd2cSJim Jagielski##########################################################################
835*b1cdbd2cSJim Jagielski
836*b1cdbd2cSJim Jagielskisub put_transforms_into_setupini
837*b1cdbd2cSJim Jagielski{
838*b1cdbd2cSJim Jagielski	my ($setupinifile, $onelanguage, $counter) = @_;
839*b1cdbd2cSJim Jagielski
840*b1cdbd2cSJim Jagielski	my $windowslanguage = installer::windows::language::get_windows_language($onelanguage);
841*b1cdbd2cSJim Jagielski	my $transformfilename = "trans_" . $onelanguage . ".mst";
842*b1cdbd2cSJim Jagielski
843*b1cdbd2cSJim Jagielski	my $line = "lang" . $counter . "=" . $windowslanguage . "," . $transformfilename . "\n";
844*b1cdbd2cSJim Jagielski
845*b1cdbd2cSJim Jagielski	push(@{$setupinifile}, $line);
846*b1cdbd2cSJim Jagielski}
847*b1cdbd2cSJim Jagielski
848*b1cdbd2cSJim Jagielski###################################################
849*b1cdbd2cSJim Jagielski# Including Windows line ends in ini files
850*b1cdbd2cSJim Jagielski# Profiles on Windows shall have \r\n line ends
851*b1cdbd2cSJim Jagielski###################################################
852*b1cdbd2cSJim Jagielski
853*b1cdbd2cSJim Jagielskisub include_windows_lineends
854*b1cdbd2cSJim Jagielski{
855*b1cdbd2cSJim Jagielski	my ($onefile) = @_;
856*b1cdbd2cSJim Jagielski
857*b1cdbd2cSJim Jagielski	for ( my $i = 0; $i <= $#{$onefile}; $i++ )
858*b1cdbd2cSJim Jagielski	{
859*b1cdbd2cSJim Jagielski		${$onefile}[$i] =~ s/\r?\n$/\r\n/;
860*b1cdbd2cSJim Jagielski	}
861*b1cdbd2cSJim Jagielski}
862*b1cdbd2cSJim Jagielski
863*b1cdbd2cSJim Jagielski##########################################################################
864*b1cdbd2cSJim Jagielski# Generation the file setup.ini, that is used by the loader setup.exe.
865*b1cdbd2cSJim Jagielski##########################################################################
866*b1cdbd2cSJim Jagielski
867*b1cdbd2cSJim Jagielskisub create_setup_ini
868*b1cdbd2cSJim Jagielski{
869*b1cdbd2cSJim Jagielski	my ($languagesarray, $defaultlanguage, $installdir, $allvariableshashref) = @_;
870*b1cdbd2cSJim Jagielski
871*b1cdbd2cSJim Jagielski	installer::logger::include_header_into_logfile("Creating setup.ini");
872*b1cdbd2cSJim Jagielski
873*b1cdbd2cSJim Jagielski	my $setupinifilename = $installdir . $installer::globals::separator . "setup.ini";
874*b1cdbd2cSJim Jagielski
875*b1cdbd2cSJim Jagielski	my @setupinifile = ();
876*b1cdbd2cSJim Jagielski	my $setupinifile = \@setupinifile;
877*b1cdbd2cSJim Jagielski
878*b1cdbd2cSJim Jagielski	my $line = "\[setup\]\n";
879*b1cdbd2cSJim Jagielski	push(@setupinifile, $line);
880*b1cdbd2cSJim Jagielski
881*b1cdbd2cSJim Jagielski	put_databasename_into_setupini($setupinifile, $allvariableshashref);
882*b1cdbd2cSJim Jagielski	put_msiversion_into_setupini($setupinifile);
883*b1cdbd2cSJim Jagielski	put_productname_into_setupini($setupinifile, $allvariableshashref);
884*b1cdbd2cSJim Jagielski	put_productcode_into_setupini($setupinifile);
885*b1cdbd2cSJim Jagielski	put_productversion_into_setupini($setupinifile);
886*b1cdbd2cSJim Jagielski	put_upgradekey_into_setupini($setupinifile);
887*b1cdbd2cSJim Jagielski
888*b1cdbd2cSJim Jagielski	$line = "\[languages\]\n";
889*b1cdbd2cSJim Jagielski	push(@setupinifile, $line);
890*b1cdbd2cSJim Jagielski
891*b1cdbd2cSJim Jagielski	put_languagecount_into_setupini($setupinifile, $languagesarray);
892*b1cdbd2cSJim Jagielski	put_defaultlanguage_into_setupini($setupinifile, $defaultlanguage);
893*b1cdbd2cSJim Jagielski
894*b1cdbd2cSJim Jagielski	if ( $#{$languagesarray} > 0 )	# writing the transforms information
895*b1cdbd2cSJim Jagielski	{
896*b1cdbd2cSJim Jagielski		my $counter = 1;
897*b1cdbd2cSJim Jagielski
898*b1cdbd2cSJim Jagielski		for ( my $i = 0; $i <= $#{$languagesarray}; $i++ )
899*b1cdbd2cSJim Jagielski		{
900*b1cdbd2cSJim Jagielski			if ( ${$languagesarray}[$i] eq $defaultlanguage ) { next; }
901*b1cdbd2cSJim Jagielski
902*b1cdbd2cSJim Jagielski			put_transforms_into_setupini($setupinifile, ${$languagesarray}[$i], $counter);
903*b1cdbd2cSJim Jagielski			$counter++;
904*b1cdbd2cSJim Jagielski		}
905*b1cdbd2cSJim Jagielski	}
906*b1cdbd2cSJim Jagielski
907*b1cdbd2cSJim Jagielski	if ( $installer::globals::iswin && $installer::globals::plat =~ /cygwin/i)		# Windows line ends only for Cygwin
908*b1cdbd2cSJim Jagielski	{
909*b1cdbd2cSJim Jagielski		include_windows_lineends($setupinifile);
910*b1cdbd2cSJim Jagielski	}
911*b1cdbd2cSJim Jagielski
912*b1cdbd2cSJim Jagielski	installer::files::save_file($setupinifilename, $setupinifile);
913*b1cdbd2cSJim Jagielski
914*b1cdbd2cSJim Jagielski	$installer::logger::Lang->printf("Generated file %s\n", $setupinifilename);
915*b1cdbd2cSJim Jagielski}
916*b1cdbd2cSJim Jagielski
917*b1cdbd2cSJim Jagielski#################################################################
918*b1cdbd2cSJim Jagielski# Copying the files defined as ScpActions into the
919*b1cdbd2cSJim Jagielski# installation set.
920*b1cdbd2cSJim Jagielski#################################################################
921*b1cdbd2cSJim Jagielski
922*b1cdbd2cSJim Jagielskisub copy_scpactions_into_installset
923*b1cdbd2cSJim Jagielski{
924*b1cdbd2cSJim Jagielski	my ($defaultlanguage, $installdir, $allscpactions) = @_;
925*b1cdbd2cSJim Jagielski
926*b1cdbd2cSJim Jagielski	installer::logger::include_header_into_logfile("Copying ScpAction files into installation set");
927*b1cdbd2cSJim Jagielski
928*b1cdbd2cSJim Jagielski	for ( my $i = 0; $i <= $#{$allscpactions}; $i++ )
929*b1cdbd2cSJim Jagielski	{
930*b1cdbd2cSJim Jagielski		my $onescpaction = ${$allscpactions}[$i];
931*b1cdbd2cSJim Jagielski
932*b1cdbd2cSJim Jagielski		if ( $onescpaction->{'Name'} eq "loader.exe" ) { next; }	# do not copy this ScpAction loader
933*b1cdbd2cSJim Jagielski
934*b1cdbd2cSJim Jagielski		# only copying language independent files or files with the correct language (the defaultlanguage)
935*b1cdbd2cSJim Jagielski
936*b1cdbd2cSJim Jagielski		my $filelanguage = $onescpaction->{'specificlanguage'};
937*b1cdbd2cSJim Jagielski
938*b1cdbd2cSJim Jagielski		if ( ($filelanguage eq $defaultlanguage) || ($filelanguage eq "") )
939*b1cdbd2cSJim Jagielski		{
940*b1cdbd2cSJim Jagielski			my $sourcefile = $onescpaction->{'sourcepath'};
941*b1cdbd2cSJim Jagielski			my $destfile = $installdir . $installer::globals::separator . $onescpaction->{'DestinationName'};
942*b1cdbd2cSJim Jagielski
943*b1cdbd2cSJim Jagielski			installer::systemactions::copy_one_file($sourcefile, $destfile);
944*b1cdbd2cSJim Jagielski		}
945*b1cdbd2cSJim Jagielski	}
946*b1cdbd2cSJim Jagielski}
947*b1cdbd2cSJim Jagielski
948*b1cdbd2cSJim Jagielski#################################################################
949*b1cdbd2cSJim Jagielski# Copying the files for the Windows installer into the
950*b1cdbd2cSJim Jagielski# installation set (setup.exe).
951*b1cdbd2cSJim Jagielski#################################################################
952*b1cdbd2cSJim Jagielski
953*b1cdbd2cSJim Jagielskisub copy_windows_installer_files_into_installset
954*b1cdbd2cSJim Jagielski{
955*b1cdbd2cSJim Jagielski	my ($installdir, $includepatharrayref, $allvariables) = @_;
956*b1cdbd2cSJim Jagielski
957*b1cdbd2cSJim Jagielski    installer::logger::include_header_into_logfile("Copying Windows installer files into installation set");
958*b1cdbd2cSJim Jagielski
959*b1cdbd2cSJim Jagielski	my @copyfile = ();
960*b1cdbd2cSJim Jagielski	push(@copyfile, "loader2.exe");
961*b1cdbd2cSJim Jagielski
962*b1cdbd2cSJim Jagielski	if ( $allvariables->{'NOLOADERREQUIRED'} ) { @copyfile = (); }
963*b1cdbd2cSJim Jagielski
964*b1cdbd2cSJim Jagielski	for ( my $i = 0; $i <= $#copyfile; $i++ )
965*b1cdbd2cSJim Jagielski	{
966*b1cdbd2cSJim Jagielski		my $filename = $copyfile[$i];
967*b1cdbd2cSJim Jagielski		my $sourcefileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filename, $includepatharrayref, 1);
968*b1cdbd2cSJim Jagielski
969*b1cdbd2cSJim Jagielski		if ( ! -f $$sourcefileref ) { installer::exiter::exit_program("ERROR: msi file not found: $$sourcefileref !", "copy_windows_installer_files_into_installset"); }
970*b1cdbd2cSJim Jagielski
971*b1cdbd2cSJim Jagielski		my $destfile;
972*b1cdbd2cSJim Jagielski		if ( $copyfile[$i] eq "loader2.exe" ) { $destfile = "setup.exe"; }	# renaming the loader
973*b1cdbd2cSJim Jagielski		else { $destfile = $copyfile[$i]; }
974*b1cdbd2cSJim Jagielski
975*b1cdbd2cSJim Jagielski		$destfile = $installdir . $installer::globals::separator . $destfile;
976*b1cdbd2cSJim Jagielski
977*b1cdbd2cSJim Jagielski		installer::systemactions::copy_one_file($$sourcefileref, $destfile);
978*b1cdbd2cSJim Jagielski	}
979*b1cdbd2cSJim Jagielski}
980*b1cdbd2cSJim Jagielski
981*b1cdbd2cSJim Jagielski#################################################################
982*b1cdbd2cSJim Jagielski# Copying the child projects into the
983*b1cdbd2cSJim Jagielski# installation set
984*b1cdbd2cSJim Jagielski#################################################################
985*b1cdbd2cSJim Jagielski
986*b1cdbd2cSJim Jagielskisub copy_child_projects_into_installset
987*b1cdbd2cSJim Jagielski{
988*b1cdbd2cSJim Jagielski	my ($installdir, $allvariables) = @_;
989*b1cdbd2cSJim Jagielski
990*b1cdbd2cSJim Jagielski	my $sourcefile = "";
991*b1cdbd2cSJim Jagielski	my $destdir = "";
992*b1cdbd2cSJim Jagielski
993*b1cdbd2cSJim Jagielski	# adding Java
994*b1cdbd2cSJim Jagielski
995*b1cdbd2cSJim Jagielski	if ( $allvariables->{'JAVAPRODUCT'} )
996*b1cdbd2cSJim Jagielski	{
997*b1cdbd2cSJim Jagielski		$sourcefile = $installer::globals::javafile->{'sourcepath'};
998*b1cdbd2cSJim Jagielski		$destdir = $installdir . $installer::globals::separator . $installer::globals::javafile->{'Subdir'};
999*b1cdbd2cSJim Jagielski		if ( ! -d $destdir) { installer::systemactions::create_directory($destdir); }
1000*b1cdbd2cSJim Jagielski		installer::systemactions::copy_one_file($sourcefile, $destdir);
1001*b1cdbd2cSJim Jagielski	}
1002*b1cdbd2cSJim Jagielski
1003*b1cdbd2cSJim Jagielski	if ( $allvariables->{'UREPRODUCT'} )
1004*b1cdbd2cSJim Jagielski	{
1005*b1cdbd2cSJim Jagielski		$sourcefile = $installer::globals::urefile->{'sourcepath'};
1006*b1cdbd2cSJim Jagielski		$destdir = $installdir . $installer::globals::separator . $installer::globals::urefile->{'Subdir'};
1007*b1cdbd2cSJim Jagielski		if ( ! -d $destdir) { installer::systemactions::create_directory($destdir); }
1008*b1cdbd2cSJim Jagielski		installer::systemactions::copy_one_file($sourcefile, $destdir);
1009*b1cdbd2cSJim Jagielski	}
1010*b1cdbd2cSJim Jagielski}
1011*b1cdbd2cSJim Jagielski
1012*b1cdbd2cSJim Jagielski
1013*b1cdbd2cSJim Jagielski
1014*b1cdbd2cSJim Jagielski=head2 create_guid ()
1015*b1cdbd2cSJim Jagielski
1016*b1cdbd2cSJim Jagielski    Create a single UUID aka GUID via calling the external executable 'uuidgen'.
1017*b1cdbd2cSJim Jagielski    There are Perl modules for that, but do they exist on the build bots?
1018*b1cdbd2cSJim Jagielski
1019*b1cdbd2cSJim Jagielski=cut
1020*b1cdbd2cSJim Jagielskisub create_guid ()
1021*b1cdbd2cSJim Jagielski{
1022*b1cdbd2cSJim Jagielski	my $uuid = qx("uuidgen");
1023*b1cdbd2cSJim Jagielski    $uuid =~ s/\s*$//;
1024*b1cdbd2cSJim Jagielski	return uc($uuid);
1025*b1cdbd2cSJim Jagielski}
1026*b1cdbd2cSJim Jagielski
1027*b1cdbd2cSJim Jagielski#################################################################
1028*b1cdbd2cSJim Jagielski# Calculating a GUID with a string using md5.
1029*b1cdbd2cSJim Jagielski#################################################################
1030*b1cdbd2cSJim Jagielski
1031*b1cdbd2cSJim Jagielskisub calculate_guid
1032*b1cdbd2cSJim Jagielski{
1033*b1cdbd2cSJim Jagielski	my ( $string ) = @_;
1034*b1cdbd2cSJim Jagielski
1035*b1cdbd2cSJim Jagielski	my $guid = "";
1036*b1cdbd2cSJim Jagielski
1037*b1cdbd2cSJim Jagielski    my $md5 = Digest::MD5->new;
1038*b1cdbd2cSJim Jagielski    $md5->add($string);
1039*b1cdbd2cSJim Jagielski    my $digest = $md5->hexdigest;
1040*b1cdbd2cSJim Jagielski    $digest = uc($digest);
1041*b1cdbd2cSJim Jagielski
1042*b1cdbd2cSJim Jagielski	# my $id = pack("A32", $digest);
1043*b1cdbd2cSJim Jagielski	my ($first, $second, $third, $fourth, $fifth) = unpack ('A8 A4 A4 A4 A12', $digest);
1044*b1cdbd2cSJim Jagielski	$guid = "$first-$second-$third-$fourth-$fifth";
1045*b1cdbd2cSJim Jagielski
1046*b1cdbd2cSJim Jagielski    $installer::logger::Lang->printf("guid for '%s' is %s\n",
1047*b1cdbd2cSJim Jagielski        $string, $guid);
1048*b1cdbd2cSJim Jagielski
1049*b1cdbd2cSJim Jagielski	return $guid;
1050*b1cdbd2cSJim Jagielski}
1051*b1cdbd2cSJim Jagielski
1052*b1cdbd2cSJim Jagielski#################################################################
1053*b1cdbd2cSJim Jagielski# Calculating a ID with a string using md5 (very fast).
1054*b1cdbd2cSJim Jagielski#################################################################
1055*b1cdbd2cSJim Jagielski
1056*b1cdbd2cSJim Jagielskisub calculate_id
1057*b1cdbd2cSJim Jagielski{
1058*b1cdbd2cSJim Jagielski	my ( $string, $length ) = @_;
1059*b1cdbd2cSJim Jagielski
1060*b1cdbd2cSJim Jagielski	my $id = "";
1061*b1cdbd2cSJim Jagielski
1062*b1cdbd2cSJim Jagielski    my $md5 = Digest::MD5->new;
1063*b1cdbd2cSJim Jagielski    $md5->add($string);
1064*b1cdbd2cSJim Jagielski    my $digest = lc($md5->hexdigest);
1065*b1cdbd2cSJim Jagielski	$id = substr($digest, 0, $length);
1066*b1cdbd2cSJim Jagielski
1067*b1cdbd2cSJim Jagielski	return $id;
1068*b1cdbd2cSJim Jagielski}
1069*b1cdbd2cSJim Jagielski
1070*b1cdbd2cSJim Jagielski#################################################################
1071*b1cdbd2cSJim Jagielski# Filling the component hash with the values of the
1072*b1cdbd2cSJim Jagielski# component file.
1073*b1cdbd2cSJim Jagielski#################################################################
1074*b1cdbd2cSJim Jagielski
1075*b1cdbd2cSJim Jagielskisub fill_component_hash
1076*b1cdbd2cSJim Jagielski{
1077*b1cdbd2cSJim Jagielski	my ($componentfile) = @_;
1078*b1cdbd2cSJim Jagielski
1079*b1cdbd2cSJim Jagielski	my %components = ();
1080*b1cdbd2cSJim Jagielski
1081*b1cdbd2cSJim Jagielski	for ( my $i = 0; $i <= $#{$componentfile}; $i++ )
1082*b1cdbd2cSJim Jagielski	{
1083*b1cdbd2cSJim Jagielski		my $line = ${$componentfile}[$i];
1084*b1cdbd2cSJim Jagielski
1085*b1cdbd2cSJim Jagielski		if ( $line =~ /^\s*(.*?)\t(.*?)\s*$/ )
1086*b1cdbd2cSJim Jagielski		{
1087*b1cdbd2cSJim Jagielski			my $key = $1;
1088*b1cdbd2cSJim Jagielski			my $value = $2;
1089*b1cdbd2cSJim Jagielski
1090*b1cdbd2cSJim Jagielski			$components{$key} = $value;
1091*b1cdbd2cSJim Jagielski		}
1092*b1cdbd2cSJim Jagielski	}
1093*b1cdbd2cSJim Jagielski
1094*b1cdbd2cSJim Jagielski	return \%components;
1095*b1cdbd2cSJim Jagielski}
1096*b1cdbd2cSJim Jagielski
1097*b1cdbd2cSJim Jagielski#################################################################
1098*b1cdbd2cSJim Jagielski# Creating a new component file, if new guids were generated.
1099*b1cdbd2cSJim Jagielski#################################################################
1100*b1cdbd2cSJim Jagielski
1101*b1cdbd2cSJim Jagielskisub create_new_component_file
1102*b1cdbd2cSJim Jagielski{
1103*b1cdbd2cSJim Jagielski	my ($componenthash) = @_;
1104*b1cdbd2cSJim Jagielski
1105*b1cdbd2cSJim Jagielski	my @componentfile = ();
1106*b1cdbd2cSJim Jagielski
1107*b1cdbd2cSJim Jagielski	my $key;
1108*b1cdbd2cSJim Jagielski
1109*b1cdbd2cSJim Jagielski	foreach $key (keys %{$componenthash})
1110*b1cdbd2cSJim Jagielski	{
1111*b1cdbd2cSJim Jagielski		my $value = $componenthash->{$key};
1112*b1cdbd2cSJim Jagielski		my $input = "$key\t$value\n";
1113*b1cdbd2cSJim Jagielski		push(@componentfile ,$input);
1114*b1cdbd2cSJim Jagielski	}
1115*b1cdbd2cSJim Jagielski
1116*b1cdbd2cSJim Jagielski	return \@componentfile;
1117*b1cdbd2cSJim Jagielski}
1118*b1cdbd2cSJim Jagielski
1119*b1cdbd2cSJim Jagielski#################################################################
1120*b1cdbd2cSJim Jagielski# Filling real component GUID into the component table.
1121*b1cdbd2cSJim Jagielski# This works only on Windows
1122*b1cdbd2cSJim Jagielski#################################################################
1123*b1cdbd2cSJim Jagielski
1124*b1cdbd2cSJim Jagielskisub __set_uuid_into_component_table
1125*b1cdbd2cSJim Jagielski{
1126*b1cdbd2cSJim Jagielski	my ($idtdirbase, $allvariables) = @_;
1127*b1cdbd2cSJim Jagielski
1128*b1cdbd2cSJim Jagielski	my $componenttablename  = $idtdirbase . $installer::globals::separator . "Componen.idt";
1129*b1cdbd2cSJim Jagielski
1130*b1cdbd2cSJim Jagielski	my $componenttable = installer::files::read_file($componenttablename);
1131*b1cdbd2cSJim Jagielski
1132*b1cdbd2cSJim Jagielski	# For update and patch reasons (small update) the GUID of an existing component must not change!
1133*b1cdbd2cSJim Jagielski	# The collection of component GUIDs is saved in the directory $installer::globals::idttemplatepath in the file "components.txt"
1134*b1cdbd2cSJim Jagielski
1135*b1cdbd2cSJim Jagielski	my $infoline = "";
1136*b1cdbd2cSJim Jagielski	my $counter = 0;
1137*b1cdbd2cSJim Jagielski	# my $componentfile = installer::files::read_file($installer::globals::componentfilename);
1138*b1cdbd2cSJim Jagielski	# my $componenthash = fill_component_hash($componentfile);
1139*b1cdbd2cSJim Jagielski
1140*b1cdbd2cSJim Jagielski	for ( my $i = 3; $i <= $#{$componenttable}; $i++ )	# ignoring the first three lines
1141*b1cdbd2cSJim Jagielski	{
1142*b1cdbd2cSJim Jagielski		my $oneline = ${$componenttable}[$i];
1143*b1cdbd2cSJim Jagielski		my $componentname = "";
1144*b1cdbd2cSJim Jagielski		if ( $oneline =~ /^\s*(\S+?)\t/ ) { $componentname = $1; }
1145*b1cdbd2cSJim Jagielski
1146*b1cdbd2cSJim Jagielski		my $uuid = "";
1147*b1cdbd2cSJim Jagielski
1148*b1cdbd2cSJim Jagielski	#	if ( $componenthash->{$componentname} )
1149*b1cdbd2cSJim Jagielski	#	{
1150*b1cdbd2cSJim Jagielski	#		$uuid = $componenthash->{$componentname};
1151*b1cdbd2cSJim Jagielski	#	}
1152*b1cdbd2cSJim Jagielski	#	else
1153*b1cdbd2cSJim Jagielski	#	{
1154*b1cdbd2cSJim Jagielski
1155*b1cdbd2cSJim Jagielski			if ( exists($installer::globals::calculated_component_guids{$componentname}))
1156*b1cdbd2cSJim Jagielski			{
1157*b1cdbd2cSJim Jagielski				$uuid = $installer::globals::calculated_component_guids{$componentname};
1158*b1cdbd2cSJim Jagielski			}
1159*b1cdbd2cSJim Jagielski			else
1160*b1cdbd2cSJim Jagielski			{
1161*b1cdbd2cSJim Jagielski				# Calculating new GUID with the help of the component name.
1162*b1cdbd2cSJim Jagielski				my $useooobaseversion = 1;
1163*b1cdbd2cSJim Jagielski				if ( exists($installer::globals::base_independent_components{$componentname}))
1164*b1cdbd2cSJim Jagielski                {
1165*b1cdbd2cSJim Jagielski                    $useooobaseversion = 0;
1166*b1cdbd2cSJim Jagielski                }
1167*b1cdbd2cSJim Jagielski				my $sourcestring = $componentname;
1168*b1cdbd2cSJim Jagielski
1169*b1cdbd2cSJim Jagielski				if ( $useooobaseversion )
1170*b1cdbd2cSJim Jagielski				{
1171*b1cdbd2cSJim Jagielski					if ( ! exists($allvariables->{'OOOBASEVERSION'}) )
1172*b1cdbd2cSJim Jagielski                    {
1173*b1cdbd2cSJim Jagielski                        installer::exiter::exit_program(
1174*b1cdbd2cSJim Jagielski                            "ERROR: Could not find variable \"OOOBASEVERSION\" (required value for GUID creation)!",
1175*b1cdbd2cSJim Jagielski                            "set_uuid_into_component_table");
1176*b1cdbd2cSJim Jagielski                    }
1177*b1cdbd2cSJim Jagielski					$sourcestring = $sourcestring . "_" . $allvariables->{'OOOBASEVERSION'};
1178*b1cdbd2cSJim Jagielski				}
1179*b1cdbd2cSJim Jagielski				$uuid = calculate_guid($sourcestring);
1180*b1cdbd2cSJim Jagielski				$counter++;
1181*b1cdbd2cSJim Jagielski
1182*b1cdbd2cSJim Jagielski				# checking, if there is a conflict with an already created guid
1183*b1cdbd2cSJim Jagielski				if ( exists($installer::globals::allcalculated_guids{$uuid}) )
1184*b1cdbd2cSJim Jagielski                {
1185*b1cdbd2cSJim Jagielski                    installer::exiter::exit_program(
1186*b1cdbd2cSJim Jagielski                        "ERROR: \"$uuid\" was already created before!",
1187*b1cdbd2cSJim Jagielski                        "set_uuid_into_component_table");
1188*b1cdbd2cSJim Jagielski                }
1189*b1cdbd2cSJim Jagielski				$installer::globals::allcalculated_guids{$uuid} = 1;
1190*b1cdbd2cSJim Jagielski				$installer::globals::calculated_component_guids{$componentname} = $uuid;
1191*b1cdbd2cSJim Jagielski
1192*b1cdbd2cSJim Jagielski				# Setting new uuid
1193*b1cdbd2cSJim Jagielski				# $componenthash->{$componentname} = $uuid;
1194*b1cdbd2cSJim Jagielski
1195*b1cdbd2cSJim Jagielski				# Setting flag
1196*b1cdbd2cSJim Jagielski				# $installer::globals::created_new_component_guid = 1;	# this is very important!
1197*b1cdbd2cSJim Jagielski			}
1198*b1cdbd2cSJim Jagielski	#	}
1199*b1cdbd2cSJim Jagielski
1200*b1cdbd2cSJim Jagielski		${$componenttable}[$i] =~ s/COMPONENTGUID/$uuid/;
1201*b1cdbd2cSJim Jagielski	}
1202*b1cdbd2cSJim Jagielski
1203*b1cdbd2cSJim Jagielski	installer::files::save_file($componenttablename, $componenttable);
1204*b1cdbd2cSJim Jagielski
1205*b1cdbd2cSJim Jagielski#	if ( $installer::globals::created_new_component_guid )
1206*b1cdbd2cSJim Jagielski#	{
1207*b1cdbd2cSJim Jagielski#		# create new component file!
1208*b1cdbd2cSJim Jagielski#		$componentfile = create_new_component_file($componenthash);
1209*b1cdbd2cSJim Jagielski#		installer::worker::sort_array($componentfile);
1210*b1cdbd2cSJim Jagielski#
1211*b1cdbd2cSJim Jagielski#		# To avoid conflict the components file cannot be saved at the same place
1212*b1cdbd2cSJim Jagielski#		# All important data have to be saved in the directory: $installer::globals::infodirectory
1213*b1cdbd2cSJim Jagielski#		my $localcomponentfilename = $installer::globals::componentfilename;
1214*b1cdbd2cSJim Jagielski#		installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$localcomponentfilename);
1215*b1cdbd2cSJim Jagielski#		$localcomponentfilename = $installer::globals::infodirectory . $installer::globals::separator . $localcomponentfilename;
1216*b1cdbd2cSJim Jagielski#		installer::files::save_file($localcomponentfilename, $componentfile);
1217*b1cdbd2cSJim Jagielski#
1218*b1cdbd2cSJim Jagielski#		# installer::files::save_file($installer::globals::componentfilename, $componentfile);	# version using new file in solver
1219*b1cdbd2cSJim Jagielski#
1220*b1cdbd2cSJim Jagielski#		$infoline = "COMPONENTCODES: Created $counter new GUIDs for components ! \n";
1221*b1cdbd2cSJim Jagielski#		$installer::logger::Lang->print($infoline);
1222*b1cdbd2cSJim Jagielski#	}
1223*b1cdbd2cSJim Jagielski#	else
1224*b1cdbd2cSJim Jagielski#	{
1225*b1cdbd2cSJim Jagielski#		$infoline = "SUCCESS COMPONENTCODES: All component codes exist! \n";
1226*b1cdbd2cSJim Jagielski#		$installer::logger::Lang->print($infoline);
1227*b1cdbd2cSJim Jagielski#	}
1228*b1cdbd2cSJim Jagielski
1229*b1cdbd2cSJim Jagielski}
1230*b1cdbd2cSJim Jagielski
1231*b1cdbd2cSJim Jagielski#########################################################################
1232*b1cdbd2cSJim Jagielski# Adding final 64 properties into msi database, if required.
1233*b1cdbd2cSJim Jagielski# RegLocator : +16 in type column to search in 64 bit registry.
1234*b1cdbd2cSJim Jagielski# All conditions: "VersionNT" -> "VersionNT64" (several tables).
1235*b1cdbd2cSJim Jagielski# Already done: "+256" in Attributes column of table "Component".
1236*b1cdbd2cSJim Jagielski# Still following: Setting "x64" instead of "Intel" in Summary
1237*b1cdbd2cSJim Jagielski# Information Stream of msi database in "get_template_for_sis".
1238*b1cdbd2cSJim Jagielski#########################################################################
1239*b1cdbd2cSJim Jagielski
1240*b1cdbd2cSJim Jagielskisub prepare_64bit_database
1241*b1cdbd2cSJim Jagielski{
1242*b1cdbd2cSJim Jagielski	my ($basedir, $allvariables) = @_;
1243*b1cdbd2cSJim Jagielski
1244*b1cdbd2cSJim Jagielski	my $infoline = "";
1245*b1cdbd2cSJim Jagielski
1246*b1cdbd2cSJim Jagielski	if (( $allvariables->{'64BITPRODUCT'} ) && ( $allvariables->{'64BITPRODUCT'} == 1 ))
1247*b1cdbd2cSJim Jagielski	{
1248*b1cdbd2cSJim Jagielski		# 1. Beginning with table "RegLocat.idt". Adding "16" to the type.
1249*b1cdbd2cSJim Jagielski
1250*b1cdbd2cSJim Jagielski		my $reglocatfile = "";
1251*b1cdbd2cSJim Jagielski		my $reglocatfilename = $basedir . $installer::globals::separator . "RegLocat.idt";
1252*b1cdbd2cSJim Jagielski
1253*b1cdbd2cSJim Jagielski		if ( -f $reglocatfilename )
1254*b1cdbd2cSJim Jagielski		{
1255*b1cdbd2cSJim Jagielski			my $saving_required = 0;
1256*b1cdbd2cSJim Jagielski			$reglocatfile = installer::files::read_file($reglocatfilename);
1257*b1cdbd2cSJim Jagielski
1258*b1cdbd2cSJim Jagielski			for ( my $i = 3; $i <= $#{$reglocatfile}; $i++ ) 	# ignoring the first three lines
1259*b1cdbd2cSJim Jagielski			{
1260*b1cdbd2cSJim Jagielski				my $oneline = ${$reglocatfile}[$i];
1261*b1cdbd2cSJim Jagielski
1262*b1cdbd2cSJim Jagielski				if ( $oneline =~ /^\s*\#/ ) { next; }	# this is a comment line
1263*b1cdbd2cSJim Jagielski				if ( $oneline =~ /^\s*$/ ) { next; }
1264*b1cdbd2cSJim Jagielski
1265*b1cdbd2cSJim Jagielski				if ( $oneline =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(\d+)\s*$/ )
1266*b1cdbd2cSJim Jagielski				{
1267*b1cdbd2cSJim Jagielski					# Syntax: Signature_ Root Key Name Type
1268*b1cdbd2cSJim Jagielski					my $sig = $1;
1269*b1cdbd2cSJim Jagielski					my $root = $2;
1270*b1cdbd2cSJim Jagielski					my $key = $3;
1271*b1cdbd2cSJim Jagielski					my $name = $4;
1272*b1cdbd2cSJim Jagielski					my $type = $5;
1273*b1cdbd2cSJim Jagielski
1274*b1cdbd2cSJim Jagielski					$type = $type + 16;
1275*b1cdbd2cSJim Jagielski
1276*b1cdbd2cSJim Jagielski					my $newline = $sig . "\t" . $root . "\t" . $key . "\t" . $name . "\t" . $type . "\n";
1277*b1cdbd2cSJim Jagielski					${$reglocatfile}[$i] = $newline;
1278*b1cdbd2cSJim Jagielski
1279*b1cdbd2cSJim Jagielski					$saving_required = 1;
1280*b1cdbd2cSJim Jagielski				}
1281*b1cdbd2cSJim Jagielski			}
1282*b1cdbd2cSJim Jagielski
1283*b1cdbd2cSJim Jagielski			if ( $saving_required )
1284*b1cdbd2cSJim Jagielski			{
1285*b1cdbd2cSJim Jagielski				# Saving the files
1286*b1cdbd2cSJim Jagielski				installer::files::save_file($reglocatfilename ,$reglocatfile);
1287*b1cdbd2cSJim Jagielski				$infoline = "Making idt file 64 bit conform: $reglocatfilename\n";
1288*b1cdbd2cSJim Jagielski				$installer::logger::Lang->print($infoline);
1289*b1cdbd2cSJim Jagielski			}
1290*b1cdbd2cSJim Jagielski		}
1291*b1cdbd2cSJim Jagielski
1292*b1cdbd2cSJim Jagielski		# 2. Replacing all occurences of "VersionNT" by "VersionNT64"
1293*b1cdbd2cSJim Jagielski
1294*b1cdbd2cSJim Jagielski		my @versionnt_files = ("Componen.idt", "InstallE.idt", "InstallU.idt", "LaunchCo.idt");
1295*b1cdbd2cSJim Jagielski
1296*b1cdbd2cSJim Jagielski		foreach my $onefile ( @versionnt_files )
1297*b1cdbd2cSJim Jagielski		{
1298*b1cdbd2cSJim Jagielski			my $fullfilename = $basedir . $installer::globals::separator . $onefile;
1299*b1cdbd2cSJim Jagielski
1300*b1cdbd2cSJim Jagielski			if ( -f $fullfilename )
1301*b1cdbd2cSJim Jagielski			{
1302*b1cdbd2cSJim Jagielski				my $saving_required = 0;
1303*b1cdbd2cSJim Jagielski				my $filecontent = installer::files::read_file($fullfilename);
1304*b1cdbd2cSJim Jagielski
1305*b1cdbd2cSJim Jagielski				for ( my $i = 3; $i <= $#{$filecontent}; $i++ ) 	# ignoring the first three lines
1306*b1cdbd2cSJim Jagielski				{
1307*b1cdbd2cSJim Jagielski					my $oneline = ${$filecontent}[$i];
1308*b1cdbd2cSJim Jagielski
1309*b1cdbd2cSJim Jagielski					if ( $oneline =~ /\bVersionNT\b/ )
1310*b1cdbd2cSJim Jagielski					{
1311*b1cdbd2cSJim Jagielski						${$filecontent}[$i] =~ s/\bVersionNT\b/VersionNT64/g;
1312*b1cdbd2cSJim Jagielski						$saving_required = 1;
1313*b1cdbd2cSJim Jagielski					}
1314*b1cdbd2cSJim Jagielski				}
1315*b1cdbd2cSJim Jagielski
1316*b1cdbd2cSJim Jagielski				if ( $saving_required )
1317*b1cdbd2cSJim Jagielski				{
1318*b1cdbd2cSJim Jagielski					# Saving the files
1319*b1cdbd2cSJim Jagielski					installer::files::save_file($fullfilename ,$filecontent);
1320*b1cdbd2cSJim Jagielski					$infoline = "Making idt file 64 bit conform: $fullfilename\n";
1321*b1cdbd2cSJim Jagielski					$installer::logger::Lang->print($infoline);
1322*b1cdbd2cSJim Jagielski				}
1323*b1cdbd2cSJim Jagielski			}
1324*b1cdbd2cSJim Jagielski		}
1325*b1cdbd2cSJim Jagielski	}
1326*b1cdbd2cSJim Jagielski
1327*b1cdbd2cSJim Jagielski}
1328*b1cdbd2cSJim Jagielski
1329*b1cdbd2cSJim Jagielski#################################################################
1330*b1cdbd2cSJim Jagielski# Include all cab files into the msi database.
1331*b1cdbd2cSJim Jagielski# This works only on Windows
1332*b1cdbd2cSJim Jagielski#################################################################
1333*b1cdbd2cSJim Jagielski
1334*b1cdbd2cSJim Jagielskisub include_cabs_into_msi
1335*b1cdbd2cSJim Jagielski{
1336*b1cdbd2cSJim Jagielski	my ($installdir) = @_;
1337*b1cdbd2cSJim Jagielski
1338*b1cdbd2cSJim Jagielski	installer::logger::include_header_into_logfile("Including cabs into msi database");
1339*b1cdbd2cSJim Jagielski
1340*b1cdbd2cSJim Jagielski	my $from = cwd();
1341*b1cdbd2cSJim Jagielski	my $to = $installdir;
1342*b1cdbd2cSJim Jagielski
1343*b1cdbd2cSJim Jagielski	chdir($to);
1344*b1cdbd2cSJim Jagielski
1345*b1cdbd2cSJim Jagielski	my $infoline = "Changing into directory: $to";
1346*b1cdbd2cSJim Jagielski	$installer::logger::Lang->print($infoline);
1347*b1cdbd2cSJim Jagielski
1348*b1cdbd2cSJim Jagielski	my $msidb = "msidb.exe";	# Has to be in the path
1349*b1cdbd2cSJim Jagielski	my $extraslash = "";		# Has to be set for non-ActiveState perl
1350*b1cdbd2cSJim Jagielski
1351*b1cdbd2cSJim Jagielski	my $msifilename = $installer::globals::msidatabasename;
1352*b1cdbd2cSJim Jagielski
1353*b1cdbd2cSJim Jagielski	$msifilename = installer::converter::make_path_conform($msifilename);
1354*b1cdbd2cSJim Jagielski
1355*b1cdbd2cSJim Jagielski	# msidb.exe really wants backslashes. (And double escaping because system() expands the string.)
1356*b1cdbd2cSJim Jagielski	$msifilename =~ s/\//\\\\/g;
1357*b1cdbd2cSJim Jagielski	$extraslash = "\\";
1358*b1cdbd2cSJim Jagielski
1359*b1cdbd2cSJim Jagielski	my $allcabfiles = installer::systemactions::find_file_with_file_extension("cab", $installdir);
1360*b1cdbd2cSJim Jagielski
1361*b1cdbd2cSJim Jagielski	for ( my $i = 0; $i <= $#{$allcabfiles}; $i++ )
1362*b1cdbd2cSJim Jagielski	{
1363*b1cdbd2cSJim Jagielski		my $systemcall = $msidb . " -d " . $msifilename . " -a " . ${$allcabfiles}[$i];
1364*b1cdbd2cSJim Jagielski
1365*b1cdbd2cSJim Jagielski		my $returnvalue = system($systemcall);
1366*b1cdbd2cSJim Jagielski
1367*b1cdbd2cSJim Jagielski		$infoline = "Systemcall: $systemcall\n";
1368*b1cdbd2cSJim Jagielski		$installer::logger::Lang->print($infoline);
1369*b1cdbd2cSJim Jagielski
1370*b1cdbd2cSJim Jagielski		if ($returnvalue)
1371*b1cdbd2cSJim Jagielski		{
1372*b1cdbd2cSJim Jagielski			$infoline = "ERROR: Could not execute $systemcall !\n";
1373*b1cdbd2cSJim Jagielski			$installer::logger::Lang->print($infoline);
1374*b1cdbd2cSJim Jagielski		}
1375*b1cdbd2cSJim Jagielski		else
1376*b1cdbd2cSJim Jagielski		{
1377*b1cdbd2cSJim Jagielski			$infoline = "Success: Executed $systemcall successfully!\n";
1378*b1cdbd2cSJim Jagielski			$installer::logger::Lang->print($infoline);
1379*b1cdbd2cSJim Jagielski		}
1380*b1cdbd2cSJim Jagielski
1381*b1cdbd2cSJim Jagielski		# deleting the cab file
1382*b1cdbd2cSJim Jagielski
1383*b1cdbd2cSJim Jagielski		unlink(${$allcabfiles}[$i]);
1384*b1cdbd2cSJim Jagielski
1385*b1cdbd2cSJim Jagielski		$infoline = "Deleted cab file: ${$allcabfiles}[$i]\n";
1386*b1cdbd2cSJim Jagielski		$installer::logger::Lang->print($infoline);
1387*b1cdbd2cSJim Jagielski	}
1388*b1cdbd2cSJim Jagielski
1389*b1cdbd2cSJim Jagielski	$infoline = "Changing back into directory: $from";
1390*b1cdbd2cSJim Jagielski	$installer::logger::Lang->print($infoline);
1391*b1cdbd2cSJim Jagielski
1392*b1cdbd2cSJim Jagielski	chdir($from);
1393*b1cdbd2cSJim Jagielski}
1394*b1cdbd2cSJim Jagielski
1395*b1cdbd2cSJim Jagielski#################################################################
1396*b1cdbd2cSJim Jagielski# Executing the created batch file to pack all files.
1397*b1cdbd2cSJim Jagielski# This works only on Windows
1398*b1cdbd2cSJim Jagielski#################################################################
1399*b1cdbd2cSJim Jagielski
1400*b1cdbd2cSJim Jagielskisub execute_packaging
1401*b1cdbd2cSJim Jagielski{
1402*b1cdbd2cSJim Jagielski	my ($localpackjobref, $loggingdir, $allvariables) = @_;
1403*b1cdbd2cSJim Jagielski
1404*b1cdbd2cSJim Jagielski	installer::logger::include_header_into_logfile("Packaging process");
1405*b1cdbd2cSJim Jagielski
1406*b1cdbd2cSJim Jagielski	$installer::logger::Lang->add_timestamp("Performance Info: Execute packaging start");
1407*b1cdbd2cSJim Jagielski
1408*b1cdbd2cSJim Jagielski	my $infoline = "";
1409*b1cdbd2cSJim Jagielski	my $from = cwd();
1410*b1cdbd2cSJim Jagielski	my $to = $loggingdir;
1411*b1cdbd2cSJim Jagielski
1412*b1cdbd2cSJim Jagielski	chdir($to);
1413*b1cdbd2cSJim Jagielski	$infoline = "chdir: $to \n";
1414*b1cdbd2cSJim Jagielski	$installer::logger::Lang->print($infoline);
1415*b1cdbd2cSJim Jagielski
1416*b1cdbd2cSJim Jagielski	# if the ddf file contains relative pathes, it is necessary to change into the temp directory
1417*b1cdbd2cSJim Jagielski	if ( $allvariables->{'RELATIVE_PATHES_IN_DDF'} )
1418*b1cdbd2cSJim Jagielski	{
1419*b1cdbd2cSJim Jagielski		$to = $installer::globals::temppath;
1420*b1cdbd2cSJim Jagielski		chdir($to);
1421*b1cdbd2cSJim Jagielski		$infoline = "chdir: $to \n";
1422*b1cdbd2cSJim Jagielski		$installer::logger::Lang->print($infoline);
1423*b1cdbd2cSJim Jagielski	}
1424*b1cdbd2cSJim Jagielski
1425*b1cdbd2cSJim Jagielski	# changing the tmp directory, because makecab.exe generates temporary cab files
1426*b1cdbd2cSJim Jagielski	my $origtemppath = "";
1427*b1cdbd2cSJim Jagielski	if ( $ENV{'TMP'} ) { $origtemppath = $ENV{'TMP'}; }
1428*b1cdbd2cSJim Jagielski	$ENV{'TMP'} = $installer::globals::temppath;	# setting TMP to the new unique directory!
1429*b1cdbd2cSJim Jagielski
1430*b1cdbd2cSJim Jagielski	my $maxmakecabcalls = 3;
1431*b1cdbd2cSJim Jagielski	my $allmakecabcalls = $#{$localpackjobref} + 1;
1432*b1cdbd2cSJim Jagielski
1433*b1cdbd2cSJim Jagielski	for ( my $i = 0; $i <= $#{$localpackjobref}; $i++ )
1434*b1cdbd2cSJim Jagielski	{
1435*b1cdbd2cSJim Jagielski		my $systemcall = ${$localpackjobref}[$i];
1436*b1cdbd2cSJim Jagielski
1437*b1cdbd2cSJim Jagielski		my $callscounter = $i + 1;
1438*b1cdbd2cSJim Jagielski
1439*b1cdbd2cSJim Jagielski		$installer::logger::Info->printf("... makecab.exe (%s/%s) ... \n", $callscounter, $allmakecabcalls);
1440*b1cdbd2cSJim Jagielski
1441*b1cdbd2cSJim Jagielski		# my $returnvalue = system($systemcall);
1442*b1cdbd2cSJim Jagielski
1443*b1cdbd2cSJim Jagielski		for ( my $n = 1; $n <= $maxmakecabcalls; $n++ )
1444*b1cdbd2cSJim Jagielski		{
1445*b1cdbd2cSJim Jagielski			my @ddfoutput = ();
1446*b1cdbd2cSJim Jagielski
1447*b1cdbd2cSJim Jagielski			$infoline = "Systemcall: $systemcall";
1448*b1cdbd2cSJim Jagielski			$installer::logger::Lang->print($infoline);
1449*b1cdbd2cSJim Jagielski
1450*b1cdbd2cSJim Jagielski			open (DDF, "$systemcall");
1451*b1cdbd2cSJim Jagielski			while (<DDF>) {push(@ddfoutput, $_); }
1452*b1cdbd2cSJim Jagielski			close (DDF);
1453*b1cdbd2cSJim Jagielski
1454*b1cdbd2cSJim Jagielski			my $returnvalue = $?;	# $? contains the return value of the systemcall
1455*b1cdbd2cSJim Jagielski
1456*b1cdbd2cSJim Jagielski			if ($returnvalue)
1457*b1cdbd2cSJim Jagielski			{
1458*b1cdbd2cSJim Jagielski				if ( $n < $maxmakecabcalls )
1459*b1cdbd2cSJim Jagielski				{
1460*b1cdbd2cSJim Jagielski                    $installer::logger::Info->printf("makecab_error (Try %s): Trying again\n", $n);
1461*b1cdbd2cSJim Jagielski                    $installer::logger::Lang->printf("makecab_error (Try %s): Trying again\n", $n);
1462*b1cdbd2cSJim Jagielski				}
1463*b1cdbd2cSJim Jagielski				else
1464*b1cdbd2cSJim Jagielski				{
1465*b1cdbd2cSJim Jagielski                    $installer::logger::Info->printf("ERROR (Try %s): Abort packing \n", $n);
1466*b1cdbd2cSJim Jagielski                    $installer::logger::Lang->printf("ERROR (Try %s): Abort packing \n", $n);
1467*b1cdbd2cSJim Jagielski				}
1468*b1cdbd2cSJim Jagielski
1469*b1cdbd2cSJim Jagielski				for ( my $m = 0; $m <= $#ddfoutput; $m++ )
1470*b1cdbd2cSJim Jagielski				{
1471*b1cdbd2cSJim Jagielski					if ( $ddfoutput[$m] =~ /(ERROR\:.*?)\s*$/ )
1472*b1cdbd2cSJim Jagielski					{
1473*b1cdbd2cSJim Jagielski						$infoline = $1 . "\n";
1474*b1cdbd2cSJim Jagielski						if ( $n < $maxmakecabcalls )
1475*b1cdbd2cSJim Jagielski                        {
1476*b1cdbd2cSJim Jagielski                            $infoline =~ s/ERROR\:/makecab_error\:/i;
1477*b1cdbd2cSJim Jagielski                        }
1478*b1cdbd2cSJim Jagielski						$installer::logger::Info->print($infoline);
1479*b1cdbd2cSJim Jagielski						$installer::logger::Lang->print($infoline);
1480*b1cdbd2cSJim Jagielski					}
1481*b1cdbd2cSJim Jagielski				}
1482*b1cdbd2cSJim Jagielski
1483*b1cdbd2cSJim Jagielski				if ( $n == $maxmakecabcalls ) { installer::exiter::exit_program("ERROR: \"$systemcall\"!", "execute_packaging"); }
1484*b1cdbd2cSJim Jagielski			}
1485*b1cdbd2cSJim Jagielski			else
1486*b1cdbd2cSJim Jagielski			{
1487*b1cdbd2cSJim Jagielski				$infoline = "Success (Try $n): $systemcall";
1488*b1cdbd2cSJim Jagielski				$installer::logger::Lang->print($infoline);
1489*b1cdbd2cSJim Jagielski				last;
1490*b1cdbd2cSJim Jagielski			}
1491*b1cdbd2cSJim Jagielski		}
1492*b1cdbd2cSJim Jagielski	}
1493*b1cdbd2cSJim Jagielski
1494*b1cdbd2cSJim Jagielski	$installer::logger::Lang->add_timestamp("Performance Info: Execute packaging end");
1495*b1cdbd2cSJim Jagielski
1496*b1cdbd2cSJim Jagielski	# setting back to the original tmp directory
1497*b1cdbd2cSJim Jagielski	$ENV{'TMP'} = $origtemppath;
1498*b1cdbd2cSJim Jagielski
1499*b1cdbd2cSJim Jagielski	chdir($from);
1500*b1cdbd2cSJim Jagielski	$infoline = "chdir: $from \n";
1501*b1cdbd2cSJim Jagielski	$installer::logger::Lang->print($infoline);
1502*b1cdbd2cSJim Jagielski}
1503*b1cdbd2cSJim Jagielski
1504*b1cdbd2cSJim Jagielski
1505*b1cdbd2cSJim Jagielski=head2 get_source_codes($languagesref)
1506*b1cdbd2cSJim Jagielski
1507*b1cdbd2cSJim Jagielski    Return product code and upgrade code from the source version.
1508*b1cdbd2cSJim Jagielski    When no source version is defined then return undef for both.
1509*b1cdbd2cSJim Jagielski
1510*b1cdbd2cSJim Jagielski=cut
1511*b1cdbd2cSJim Jagielskisub get_source_codes ($)
1512*b1cdbd2cSJim Jagielski{
1513*b1cdbd2cSJim Jagielski    my ($languagesref) = @_;
1514*b1cdbd2cSJim Jagielski
1515*b1cdbd2cSJim Jagielski    if ( ! $installer::globals::is_release)
1516*b1cdbd2cSJim Jagielski    {
1517*b1cdbd2cSJim Jagielski        return (undef, undef);
1518*b1cdbd2cSJim Jagielski    }
1519*b1cdbd2cSJim Jagielski    elsif ( ! defined $installer::globals::source_version)
1520*b1cdbd2cSJim Jagielski    {
1521*b1cdbd2cSJim Jagielski        $installer::logger::Lang->printf("no source version defined\n");
1522*b1cdbd2cSJim Jagielski        return (undef, undef);
1523*b1cdbd2cSJim Jagielski    }
1524*b1cdbd2cSJim Jagielski
1525*b1cdbd2cSJim Jagielski    my $onelanguage = installer::languages::get_key_language($languagesref);
1526*b1cdbd2cSJim Jagielski
1527*b1cdbd2cSJim Jagielski    my $release_data = installer::patch::ReleasesList::Instance()
1528*b1cdbd2cSJim Jagielski        ->{$installer::globals::source_version}
1529*b1cdbd2cSJim Jagielski        ->{$installer::globals::packageformat};
1530*b1cdbd2cSJim Jagielski    if (defined $release_data)
1531*b1cdbd2cSJim Jagielski    {
1532*b1cdbd2cSJim Jagielski        my $normalized_language = installer::languages::get_normalized_language($languagesref);
1533*b1cdbd2cSJim Jagielski        my $language_data = $release_data->{$normalized_language};
1534*b1cdbd2cSJim Jagielski        if (defined $language_data)
1535*b1cdbd2cSJim Jagielski        {
1536*b1cdbd2cSJim Jagielski            $installer::logger::Lang->printf("source product code is %s\n", $language_data->{'product-code'});
1537*b1cdbd2cSJim Jagielski            $installer::logger::Lang->printf("source upgrade code is %s\n", $release_data->{'upgrade-code'});
1538*b1cdbd2cSJim Jagielski
1539*b1cdbd2cSJim Jagielski            return (
1540*b1cdbd2cSJim Jagielski                $language_data->{'product-code'},
1541*b1cdbd2cSJim Jagielski                $release_data->{'upgrade-code'}
1542*b1cdbd2cSJim Jagielski                );
1543*b1cdbd2cSJim Jagielski        }
1544*b1cdbd2cSJim Jagielski        else
1545*b1cdbd2cSJim Jagielski        {
1546*b1cdbd2cSJim Jagielski            $installer::logger::Info->printf(
1547*b1cdbd2cSJim Jagielski                "Warning: can not access information about previous version %s and language %s/%s/%s\n",
1548*b1cdbd2cSJim Jagielski                $installer::globals::source_version,
1549*b1cdbd2cSJim Jagielski                $onelanguage,
1550*b1cdbd2cSJim Jagielski                join(", ",@$languagesref),
1551*b1cdbd2cSJim Jagielski                $normalized_language);
1552*b1cdbd2cSJim Jagielski            return (undef,undef);
1553*b1cdbd2cSJim Jagielski        }
1554*b1cdbd2cSJim Jagielski    }
1555*b1cdbd2cSJim Jagielski    else
1556*b1cdbd2cSJim Jagielski    {
1557*b1cdbd2cSJim Jagielski        $installer::logger::Info->printf("Warning: can not access information about previous version %s\n",
1558*b1cdbd2cSJim Jagielski            $installer::globals::source_version);
1559*b1cdbd2cSJim Jagielski        return (undef,undef);
1560*b1cdbd2cSJim Jagielski    }
1561*b1cdbd2cSJim Jagielski}
1562*b1cdbd2cSJim Jagielski
1563*b1cdbd2cSJim Jagielski
1564*b1cdbd2cSJim Jagielski
1565*b1cdbd2cSJim Jagielski
1566*b1cdbd2cSJim Jagielski=head2 set_global_code_variables ($languagesref, $allvariableshashref)
1567*b1cdbd2cSJim Jagielski
1568*b1cdbd2cSJim Jagielski    Determine values for the product code and upgrade code of the target version.
1569*b1cdbd2cSJim Jagielski
1570*b1cdbd2cSJim Jagielski    As perparation for building a Windows patch, certain conditions have to be fullfilled.
1571*b1cdbd2cSJim Jagielski     - The upgrade code changes from old to new version
1572*b1cdbd2cSJim Jagielski     - The product code remains the same
1573*b1cdbd2cSJim Jagielski     In order to inforce that we have to access information about the source version.
1574*b1cdbd2cSJim Jagielski
1575*b1cdbd2cSJim Jagielski    The resulting values are stored as global variables
1576*b1cdbd2cSJim Jagielski        $installer::globals::productcode
1577*b1cdbd2cSJim Jagielski        $installer::globals::upgradecode
1578*b1cdbd2cSJim Jagielski    and as variables in the given hash
1579*b1cdbd2cSJim Jagielski    	$allvariableshashref->{'PRODUCTCODE'}
1580*b1cdbd2cSJim Jagielski        $allvariableshashref->{'UPGRADECODE'}
1581*b1cdbd2cSJim Jagielski
1582*b1cdbd2cSJim Jagielski=cut
1583*b1cdbd2cSJim Jagielskisub set_global_code_variables ($$)
1584*b1cdbd2cSJim Jagielski{
1585*b1cdbd2cSJim Jagielski    my ($languagesref, $allvariableshashref) = @_;
1586*b1cdbd2cSJim Jagielski
1587*b1cdbd2cSJim Jagielski    my ($source_product_code, $source_upgrade_code) = get_source_codes($languagesref);
1588*b1cdbd2cSJim Jagielski    my ($target_product_code, $target_upgrade_code) = (undef, undef);
1589*b1cdbd2cSJim Jagielski
1590*b1cdbd2cSJim Jagielski    if (defined $source_product_code && defined $source_upgrade_code)
1591*b1cdbd2cSJim Jagielski    {
1592*b1cdbd2cSJim Jagielski        if ($installer::globals::is_major_release)
1593*b1cdbd2cSJim Jagielski        {
1594*b1cdbd2cSJim Jagielski            # For a major release we have to change the product code.
1595*b1cdbd2cSJim Jagielski            $target_product_code = "{" . create_guid() . "}";
1596*b1cdbd2cSJim Jagielski            $installer::logger::Lang->printf("building a major release, created new product code %s\n",
1597*b1cdbd2cSJim Jagielski                $target_product_code);
1598*b1cdbd2cSJim Jagielski
1599*b1cdbd2cSJim Jagielski            # Let's do a paranoia check that the new and the old guids are
1600*b1cdbd2cSJim Jagielski            # different.  In reality the new guid really has to be
1601*b1cdbd2cSJim Jagielski            # different from all other guids used for * codes, components,
1602*b1cdbd2cSJim Jagielski            # etc.
1603*b1cdbd2cSJim Jagielski            if ($target_product_code eq $source_product_code)
1604*b1cdbd2cSJim Jagielski            {
1605*b1cdbd2cSJim Jagielski                installer::logger::PrintError(
1606*b1cdbd2cSJim Jagielski                    "new GUID for product code is the same as the old product code but should be different.");
1607*b1cdbd2cSJim Jagielski            }
1608*b1cdbd2cSJim Jagielski        }
1609*b1cdbd2cSJim Jagielski        else
1610*b1cdbd2cSJim Jagielski        {
1611*b1cdbd2cSJim Jagielski            # For minor or micro releases we have to keeep the old product code.
1612*b1cdbd2cSJim Jagielski            $target_product_code = "{" . $source_product_code . "}";
1613*b1cdbd2cSJim Jagielski            $installer::logger::Lang->printf("building a minor or micro release, reusing product code %s\n",
1614*b1cdbd2cSJim Jagielski                $target_product_code);
1615*b1cdbd2cSJim Jagielski        }
1616*b1cdbd2cSJim Jagielski
1617*b1cdbd2cSJim Jagielski        $target_upgrade_code = "{" . create_guid() . "}";
1618*b1cdbd2cSJim Jagielski        # Again, just one test for paranoia.
1619*b1cdbd2cSJim Jagielski        if ($target_upgrade_code eq $source_upgrade_code)
1620*b1cdbd2cSJim Jagielski        {
1621*b1cdbd2cSJim Jagielski            installer::logger::PrintError(
1622*b1cdbd2cSJim Jagielski                "new GUID for upgrade code is the same as the old upgrade code but should be different.");
1623*b1cdbd2cSJim Jagielski        }
1624*b1cdbd2cSJim Jagielski    }
1625*b1cdbd2cSJim Jagielski    else
1626*b1cdbd2cSJim Jagielski    {
1627*b1cdbd2cSJim Jagielski        # There is no previous version with which to compare the product code.
1628*b1cdbd2cSJim Jagielski        # Just create two new uuids.
1629*b1cdbd2cSJim Jagielski        $target_product_code = "{" . create_guid() . "}";
1630*b1cdbd2cSJim Jagielski        $target_upgrade_code = "{" . create_guid() . "}";
1631*b1cdbd2cSJim Jagielski        $installer::logger::Lang->printf("there is no source version => created new guids\n");
1632*b1cdbd2cSJim Jagielski    }
1633*b1cdbd2cSJim Jagielski
1634*b1cdbd2cSJim Jagielski    # Keep the upgrade code constant between versions.  Read it from the codes.txt file.
1635*b1cdbd2cSJim Jagielski    # Note that this handles regular installation sets and language packs.
1636*b1cdbd2cSJim Jagielski    my $onelanguage = ${$languagesref}[0];
1637*b1cdbd2cSJim Jagielski    $installer::logger::Lang->printf("reading upgrade code for language %s from %s\n",
1638*b1cdbd2cSJim Jagielski        $onelanguage,
1639*b1cdbd2cSJim Jagielski        $installer::globals::codefilename);
1640*b1cdbd2cSJim Jagielski    if (defined $installer::globals::codefilename)
1641*b1cdbd2cSJim Jagielski    {
1642*b1cdbd2cSJim Jagielski        my $code_filename = $installer::globals::codefilename;
1643*b1cdbd2cSJim Jagielski        installer::files::check_file($code_filename);
1644*b1cdbd2cSJim Jagielski        my $codefile = installer::files::read_file($code_filename);
1645*b1cdbd2cSJim Jagielski        my $searchstring = "UPGRADECODE";
1646*b1cdbd2cSJim Jagielski        my $codeblock = installer::windows::idtglobal::get_language_block_from_language_file(
1647*b1cdbd2cSJim Jagielski            $searchstring,
1648*b1cdbd2cSJim Jagielski            $codefile);
1649*b1cdbd2cSJim Jagielski        $target_upgrade_code = installer::windows::idtglobal::get_language_string_from_language_block(
1650*b1cdbd2cSJim Jagielski            $codeblock,
1651*b1cdbd2cSJim Jagielski            $onelanguage,
1652*b1cdbd2cSJim Jagielski            "");
1653*b1cdbd2cSJim Jagielski    }
1654*b1cdbd2cSJim Jagielski    # else use the previously generated upgrade code.
1655*b1cdbd2cSJim Jagielski
1656*b1cdbd2cSJim Jagielski    $installer::globals::productcode = $target_product_code;
1657*b1cdbd2cSJim Jagielski    $installer::globals::upgradecode = $target_upgrade_code;
1658*b1cdbd2cSJim Jagielski    $allvariableshashref->{'PRODUCTCODE'} = $target_product_code;
1659*b1cdbd2cSJim Jagielski    $allvariableshashref->{'UPGRADECODE'} = $target_upgrade_code;
1660*b1cdbd2cSJim Jagielski
1661*b1cdbd2cSJim Jagielski    $installer::logger::Lang->printf("target product code is %s\n", $target_product_code);
1662*b1cdbd2cSJim Jagielski    $installer::logger::Lang->printf("target upgrade code is %s\n", $target_upgrade_code);
1663*b1cdbd2cSJim Jagielski}
1664*b1cdbd2cSJim Jagielski
1665*b1cdbd2cSJim Jagielski
1666*b1cdbd2cSJim Jagielski
1667*b1cdbd2cSJim Jagielski
1668*b1cdbd2cSJim Jagielski###############################################################
1669*b1cdbd2cSJim Jagielski# Setting the product version used in property table and
1670*b1cdbd2cSJim Jagielski# upgrade table. Saving in global variable $msiproductversion
1671*b1cdbd2cSJim Jagielski###############################################################
1672*b1cdbd2cSJim Jagielski
1673*b1cdbd2cSJim Jagielskisub set_msiproductversion
1674*b1cdbd2cSJim Jagielski{
1675*b1cdbd2cSJim Jagielski	my ( $allvariables ) = @_;
1676*b1cdbd2cSJim Jagielski
1677*b1cdbd2cSJim Jagielski	my $productversion = $allvariables->{'PRODUCTVERSION'};
1678*b1cdbd2cSJim Jagielski
1679*b1cdbd2cSJim Jagielski	if (( $productversion =~ /^\s*\d+\s*$/ ) && ( $productversion > 255 )) { $productversion = $productversion%256; }
1680*b1cdbd2cSJim Jagielski
1681*b1cdbd2cSJim Jagielski	if ( $productversion =~ /^\s*(\d+)\.(\d+)\.(\d+)\s*$/ )
1682*b1cdbd2cSJim Jagielski	{
1683*b1cdbd2cSJim Jagielski		$productversion = $1 . "\." . $2 . $3 . "\." . $installer::globals::buildid;
1684*b1cdbd2cSJim Jagielski	}
1685*b1cdbd2cSJim Jagielski	elsif  ( $productversion =~ /^\s*(\d+)\.(\d+)\s*$/ )
1686*b1cdbd2cSJim Jagielski	{
1687*b1cdbd2cSJim Jagielski		$productversion = $1 . "\." . $2 . "\." . $installer::globals::buildid;
1688*b1cdbd2cSJim Jagielski	}
1689*b1cdbd2cSJim Jagielski	else
1690*b1cdbd2cSJim Jagielski	{
1691*b1cdbd2cSJim Jagielski		my $productminor = "00";
1692*b1cdbd2cSJim Jagielski		if (( $allvariables->{'PACKAGEVERSION'} ) && ( $allvariables->{'PACKAGEVERSION'} ne "" ))
1693*b1cdbd2cSJim Jagielski		{
1694*b1cdbd2cSJim Jagielski			if ( $allvariables->{'PACKAGEVERSION'} =~ /^\s*(\d+)\.(\d+)\.(\d+)\s*$/ ) { $productminor = $2; }
1695*b1cdbd2cSJim Jagielski		}
1696*b1cdbd2cSJim Jagielski
1697*b1cdbd2cSJim Jagielski		$productversion = $productversion . "\." . $productminor . "\." . $installer::globals::buildid;
1698*b1cdbd2cSJim Jagielski	}
1699*b1cdbd2cSJim Jagielski
1700*b1cdbd2cSJim Jagielski	$installer::globals::msiproductversion = $productversion;
1701*b1cdbd2cSJim Jagielski
1702*b1cdbd2cSJim Jagielski	# Setting $installer::globals::msimajorproductversion, to differ between old version in upgrade table
1703*b1cdbd2cSJim Jagielski
1704*b1cdbd2cSJim Jagielski	if ( $installer::globals::msiproductversion =~ /^\s*(\d+)\./ )
1705*b1cdbd2cSJim Jagielski	{
1706*b1cdbd2cSJim Jagielski		my $major = $1;
1707*b1cdbd2cSJim Jagielski		$installer::globals::msimajorproductversion = $major . "\.0\.0";
1708*b1cdbd2cSJim Jagielski	}
1709*b1cdbd2cSJim Jagielski}
1710*b1cdbd2cSJim Jagielski
1711*b1cdbd2cSJim Jagielski#################################################################################
1712*b1cdbd2cSJim Jagielski# Including the msi product version into the bootstrap.ini, Windows only
1713*b1cdbd2cSJim Jagielski#################################################################################
1714*b1cdbd2cSJim Jagielski
1715*b1cdbd2cSJim Jagielskisub put_msiproductversion_into_bootstrapfile
1716*b1cdbd2cSJim Jagielski{
1717*b1cdbd2cSJim Jagielski	my ($filesref) = @_;
1718*b1cdbd2cSJim Jagielski
1719*b1cdbd2cSJim Jagielski	for ( my $i = 0; $i <= $#{$filesref}; $i++ )
1720*b1cdbd2cSJim Jagielski	{
1721*b1cdbd2cSJim Jagielski		my $onefile = ${$filesref}[$i];
1722*b1cdbd2cSJim Jagielski
1723*b1cdbd2cSJim Jagielski		if ( $onefile->{'gid'} eq "gid_Profile_Version_Ini" )
1724*b1cdbd2cSJim Jagielski		{
1725*b1cdbd2cSJim Jagielski			my $file = installer::files::read_file($onefile->{'sourcepath'});
1726*b1cdbd2cSJim Jagielski
1727*b1cdbd2cSJim Jagielski			for ( my $j = 0; $j <= $#{$file}; $j++ )
1728*b1cdbd2cSJim Jagielski			{
1729*b1cdbd2cSJim Jagielski				${$file}[$j] =~ s/\<msiproductversion\>/$installer::globals::msiproductversion/;
1730*b1cdbd2cSJim Jagielski			}
1731*b1cdbd2cSJim Jagielski
1732*b1cdbd2cSJim Jagielski			installer::files::save_file($onefile->{'sourcepath'}, $file);
1733*b1cdbd2cSJim Jagielski
1734*b1cdbd2cSJim Jagielski			last;
1735*b1cdbd2cSJim Jagielski		}
1736*b1cdbd2cSJim Jagielski	}
1737*b1cdbd2cSJim Jagielski}
1738*b1cdbd2cSJim Jagielski
1739*b1cdbd2cSJim Jagielski####################################################################################
1740*b1cdbd2cSJim Jagielski# Updating the file Property.idt dynamically
1741*b1cdbd2cSJim Jagielski# Content:
1742*b1cdbd2cSJim Jagielski# Property Value
1743*b1cdbd2cSJim Jagielski####################################################################################
1744*b1cdbd2cSJim Jagielski
1745*b1cdbd2cSJim Jagielskisub update_reglocat_table
1746*b1cdbd2cSJim Jagielski{
1747*b1cdbd2cSJim Jagielski	my ($basedir, $allvariables) = @_;
1748*b1cdbd2cSJim Jagielski
1749*b1cdbd2cSJim Jagielski	my $reglocatfilename = $basedir . $installer::globals::separator . "RegLocat.idt";
1750*b1cdbd2cSJim Jagielski
1751*b1cdbd2cSJim Jagielski	# Only do something, if this file exists
1752*b1cdbd2cSJim Jagielski
1753*b1cdbd2cSJim Jagielski	if ( -f $reglocatfilename )
1754*b1cdbd2cSJim Jagielski	{
1755*b1cdbd2cSJim Jagielski		my $reglocatfile = installer::files::read_file($reglocatfilename);
1756*b1cdbd2cSJim Jagielski
1757*b1cdbd2cSJim Jagielski		my $layername = "";
1758*b1cdbd2cSJim Jagielski		if ( $allvariables->{'REGISTRYLAYERNAME'} )
1759*b1cdbd2cSJim Jagielski		{
1760*b1cdbd2cSJim Jagielski			$layername = $allvariables->{'REGISTRYLAYERNAME'};
1761*b1cdbd2cSJim Jagielski		}
1762*b1cdbd2cSJim Jagielski		else
1763*b1cdbd2cSJim Jagielski		{
1764*b1cdbd2cSJim Jagielski			for ( my $i = 0; $i <= $#{$reglocatfile}; $i++ )
1765*b1cdbd2cSJim Jagielski			{
1766*b1cdbd2cSJim Jagielski				if ( ${$reglocatfile}[$i] =~ /\bLAYERNAMETEMPLATE\b/ )
1767*b1cdbd2cSJim Jagielski				{
1768*b1cdbd2cSJim Jagielski					installer::exiter::exit_program("ERROR: Variable \"REGISTRYLAYERNAME\" has to be defined", "update_reglocat_table");
1769*b1cdbd2cSJim Jagielski				}
1770*b1cdbd2cSJim Jagielski			}
1771*b1cdbd2cSJim Jagielski		}
1772*b1cdbd2cSJim Jagielski
1773*b1cdbd2cSJim Jagielski		if ( $layername ne "" )
1774*b1cdbd2cSJim Jagielski		{
1775*b1cdbd2cSJim Jagielski			# Updating the layername in
1776*b1cdbd2cSJim Jagielski
1777*b1cdbd2cSJim Jagielski			for ( my $i = 0; $i <= $#{$reglocatfile}; $i++ )
1778*b1cdbd2cSJim Jagielski			{
1779*b1cdbd2cSJim Jagielski				${$reglocatfile}[$i] =~ s/\bLAYERNAMETEMPLATE\b/$layername/;
1780*b1cdbd2cSJim Jagielski			}
1781*b1cdbd2cSJim Jagielski
1782*b1cdbd2cSJim Jagielski			# Saving the file
1783*b1cdbd2cSJim Jagielski			installer::files::save_file($reglocatfilename ,$reglocatfile);
1784*b1cdbd2cSJim Jagielski			my $infoline = "Updated idt file: $reglocatfilename\n";
1785*b1cdbd2cSJim Jagielski			$installer::logger::Lang->print($infoline);
1786*b1cdbd2cSJim Jagielski		}
1787*b1cdbd2cSJim Jagielski	}
1788*b1cdbd2cSJim Jagielski}
1789*b1cdbd2cSJim Jagielski
1790*b1cdbd2cSJim Jagielski
1791*b1cdbd2cSJim Jagielski
1792*b1cdbd2cSJim Jagielski####################################################################################
1793*b1cdbd2cSJim Jagielski# Updating the file RemoveRe.idt dynamically (RemoveRegistry.idt)
1794*b1cdbd2cSJim Jagielski# The name of the component has to be replaced.
1795*b1cdbd2cSJim Jagielski####################################################################################
1796*b1cdbd2cSJim Jagielski
1797*b1cdbd2cSJim Jagielskisub update_removere_table
1798*b1cdbd2cSJim Jagielski{
1799*b1cdbd2cSJim Jagielski	my ($basedir) = @_;
1800*b1cdbd2cSJim Jagielski
1801*b1cdbd2cSJim Jagielski	my $removeregistryfilename = $basedir . $installer::globals::separator . "RemoveRe.idt";
1802*b1cdbd2cSJim Jagielski
1803*b1cdbd2cSJim Jagielski	# Only do something, if this file exists
1804*b1cdbd2cSJim Jagielski
1805*b1cdbd2cSJim Jagielski	if ( -f $removeregistryfilename )
1806*b1cdbd2cSJim Jagielski	{
1807*b1cdbd2cSJim Jagielski		my $removeregistryfile = installer::files::read_file($removeregistryfilename);
1808*b1cdbd2cSJim Jagielski
1809*b1cdbd2cSJim Jagielski		for ( my $i = 0; $i <= $#{$removeregistryfile}; $i++ )
1810*b1cdbd2cSJim Jagielski		{
1811*b1cdbd2cSJim Jagielski			for ( my $i = 0; $i <= $#{$removeregistryfile}; $i++ )
1812*b1cdbd2cSJim Jagielski			{
1813*b1cdbd2cSJim Jagielski				${$removeregistryfile}[$i] =~ s/\bREGISTRYROOTCOMPONENT\b/$installer::globals::registryrootcomponent/;
1814*b1cdbd2cSJim Jagielski			}
1815*b1cdbd2cSJim Jagielski		}
1816*b1cdbd2cSJim Jagielski
1817*b1cdbd2cSJim Jagielski		# Saving the file
1818*b1cdbd2cSJim Jagielski		installer::files::save_file($removeregistryfilename ,$removeregistryfile);
1819*b1cdbd2cSJim Jagielski		my $infoline = "Updated idt file: $removeregistryfilename \n";
1820*b1cdbd2cSJim Jagielski		$installer::logger::Lang->print($infoline);
1821*b1cdbd2cSJim Jagielski	}
1822*b1cdbd2cSJim Jagielski}
1823*b1cdbd2cSJim Jagielski
1824*b1cdbd2cSJim Jagielski
1825*b1cdbd2cSJim Jagielski1;
1826*b1cdbd2cSJim Jagielski
1827