1#**************************************************************
2#
3#  Licensed to the Apache Software Foundation (ASF) under one
4#  or more contributor license agreements.  See the NOTICE file
5#  distributed with this work for additional information
6#  regarding copyright ownership.  The ASF licenses this file
7#  to you under the Apache License, Version 2.0 (the
8#  "License"); you may not use this file except in compliance
9#  with the License.  You may obtain a copy of the License at
10#
11#    http://www.apache.org/licenses/LICENSE-2.0
12#
13#  Unless required by applicable law or agreed to in writing,
14#  software distributed under the License is distributed on an
15#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16#  KIND, either express or implied.  See the License for the
17#  specific language governing permissions and limitations
18#  under the License.
19#
20#**************************************************************
21
22
23
24package installer::setupscript;
25
26use installer::existence;
27use installer::exiter;
28use installer::globals;
29use installer::logger;
30use installer::remover;
31use installer::scriptitems;
32use installer::ziplist;
33
34use strict;
35
36#######################################################
37# Set setup script name, if not defined as parameter
38#######################################################
39
40sub set_setupscript_name
41{
42	my ( $allsettingsarrayref, $includepatharrayref ) = @_;
43
44	my $scriptnameref = installer::ziplist::getinfofromziplist($allsettingsarrayref, "script");
45
46	my $scriptname = $$scriptnameref;
47
48	if ( $scriptname eq "" )	# not defined on command line and not in product list
49	{
50		installer::exiter::exit_program("ERROR: Setup script not defined on command line (-l) and not in product list!", "set_setupscript_name");
51	}
52
53	if ( $installer::globals::compiler =~ /wnt/ )
54	{
55		$scriptname .= ".inf";
56	}
57	else
58	{
59		$scriptname .= ".ins";
60	}
61
62	# and now the complete path for the setup script is needed
63	# The log file cannot be used, because this is the language independent section
64
65	$scriptnameref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$scriptname, $includepatharrayref, 1);
66
67	$installer::globals::setupscriptname = $$scriptnameref;
68
69	if ( $installer::globals::setupscriptname eq "" )
70	{
71		installer::exiter::exit_program("ERROR: Script $scriptname not found!", "set_setupscript_name");
72	}
73}
74
75#####################################################################
76# Reading script variables from installation object of script file
77#####################################################################
78
79sub get_all_scriptvariables_from_installation_object ($$)
80{
81	my ($scriptref, $script_filename) = @_;
82
83	my @installobjectvariables;
84
85	for ( my $i = 0; $i <= $#{$scriptref}; $i++ )
86	{
87		my $line = ${$scriptref}[$i];
88
89		if ( $line =~ /^\s*Installation\s+\w+\s*$/ )	# should be the first line
90		{
91			my $counter = $i+1;
92			my $installline = ${$scriptref}[$counter];
93
94			while (!($installline =~ /^\s*End\s*$/ ))
95			{
96				if ( $installline =~ /^\s*(\w+)\s+\=\s*(.*?)\s*\;\s*$/ )
97				{
98					my $key = $1;
99					my $value = $2;
100
101					# removing leading and ending " in $value
102
103					if ( $value =~ /^\s*\"(.*)\"\s*$/ )
104					{
105						$value = $1;
106					}
107
108					$key = "\%" . uc($key);  # $key is %PRODUCTNAME
109
110					my $input = $key . " " . $value . "\n";	  # $key can only be the first word
111
112					push(@installobjectvariables ,$input);
113				}
114
115				$counter++;
116				$installline = ${$scriptref}[$counter];
117			}
118		}
119
120		last;	# not interesting after installation object
121	}
122
123	return \@installobjectvariables;
124}
125
126######################################################################
127# Including LCPRODUCTNAME into the array
128######################################################################
129
130sub add_lowercase_productname_setupscriptvariable
131{
132	my ( $variablesref ) = @_;
133
134	for ( my $j = 0; $j <= $#{$variablesref}; $j++ )
135	{
136		my $variableline = ${$variablesref}[$j];
137
138		my ($key, $value);
139
140		if ( $variableline =~ /^\s*\%(\w+?)\s+(.*?)\s*$/ )
141		{
142			$key = $1;
143			$value = $2;
144
145			if ( $key eq "PRODUCTNAME" )
146			{
147				my $newline = "\%LCPRODUCTNAME " . lc($value) . "\n";
148				push(@{$variablesref} ,$newline);
149				my $original = $value;
150				$value =~ s/\s*//g;
151				$newline = "\%ONEWORDPRODUCTNAME " . $value . "\n";
152				push(@{$variablesref} ,$newline);
153				$newline = "\%LCONEWORDPRODUCTNAME " . lc($value) . "\n";
154				push(@{$variablesref} ,$newline);
155				$value = $original;
156				$value =~ s/\s*$//g;
157				$value =~ s/^\s*//g;
158				$value =~ s/ /\%20/g;
159				$newline = "\%MASKEDPRODUCTNAME " . $value . "\n";
160				push(@{$variablesref} ,$newline);
161				$value = $original;
162				$value =~ s/\s/\_/g;
163				# if ( $value =~ /^\s*(.*?)\_(\w)(.*?)\_(\w)(.*)\s*$/ ) { $value = $1 . $2 . $4; }
164				$newline = "\%UNIXPRODUCTNAME " . lc($value) . "\n";
165				push(@{$variablesref} ,$newline);
166				$newline = "\%SYSTEMINTUNIXPACKAGENAME " . lc($value) . "\n";
167				push(@{$variablesref} ,$newline);
168				# if ( $value =~ /^\s*(.*?)\_(\w)(.*?)\_(\w)(.*)\s*$/ ) { $value = $1 . $2 . $4; }
169				# if ( $value =~ /^\s*(.*?)\_(\w)(.*?)\_(\w)(.*)\s*$/ ) { $value = $2 . $4; }
170				$newline = "\%UNIXPACKAGENAME " . lc($value) . "\n";
171				push(@{$variablesref} ,$newline);
172				$value = $original;
173				$value =~ s/\s/\_/g;
174				$value =~ s/\.//g;
175				# if ( $value =~ /^\s*(.*?)\_(\w)(.*?)\_(\w)(.*)\s*$/ ) { $value = $1 . $2 . $4; }
176				$newline = "\%WITHOUTDOTUNIXPRODUCTNAME " . lc($value) . "\n";
177				push(@{$variablesref} ,$newline);
178				# if ( $value =~ /^\s*(.*?)\_(\w)(.*?)\_(\w)(.*)\s*$/ ) { $value = $1 . $2 . $4; }
179				# if ( $value =~ /^\s*(.*?)\_(\w)(.*?)\_(\w)(.*)\s*$/ ) { $value = $2 . $4; }
180				$newline = "\%WITHOUTDOTUNIXPACKAGENAME " . lc($value) . "\n";
181				push(@{$variablesref} ,$newline);
182				$newline = "\%SOLARISBRANDPACKAGENAME " . lc($value) . "\n";
183				push(@{$variablesref} ,$newline);
184				$value = $original;
185			}
186			elsif  ( $key eq "PRODUCTEXTENSION" )
187			{
188				my $newline = "\%LCPRODUCTEXTENSION " . lc($value) . "\n";
189				push(@{$variablesref} ,$newline);
190			}
191			elsif  ( $key eq "PRODUCTVERSION" )
192			{
193				$value =~ s/\.//g;
194				my $newline = "\%WITHOUTDOTPRODUCTVERSION " . $value . "\n";
195				push(@{$variablesref} ,$newline);
196			}
197			elsif  ( $key eq "OOOBASEVERSION" )
198			{
199				$value =~ s/\.//g;
200				my $newline = "\%WITHOUTDOTOOOBASEVERSION " . $value . "\n";
201				push(@{$variablesref} ,$newline);
202			}
203
204		}
205	}
206}
207
208######################################################################
209# Resolving the new introduced lowercase script variables
210######################################################################
211
212sub resolve_lowercase_productname_setupscriptvariable
213{
214	my ( $variablesref ) = @_;
215
216	my %variables = ();
217
218	# First step: Collecting variables
219
220	for ( my $j = 0; $j <= $#{$variablesref}; $j++ )
221	{
222		my $variableline = ${$variablesref}[$j];
223
224		my ($key, $value);
225
226		if ( $variableline =~ /^\s*\%(\w+?)\s+(.*?)\s*$/ )
227		{
228			$key = $1;
229			$value = $2;
230			$variables{$key} = $value;
231		}
232	}
233
234	# Second step: Resolving variables
235
236	for ( my $j = 0; $j <= $#{$variablesref}; $j++ )
237	{
238		if ( ${$variablesref}[$j] =~ /\$\{(.*?)\}/ )
239		{
240			my $key = $1;
241			${$variablesref}[$j] =~ s/\$\{\Q$key\E\}/$variables{$key}/g;
242		}
243	}
244
245}
246
247######################################################################
248# Replacing all setup script variables inside the setup script file
249######################################################################
250
251sub replace_all_setupscriptvariables_in_script
252{
253	my ( $scriptref, $variablesref ) = @_;
254
255	installer::logger::include_header_into_globallogfile("Replacing variables in setup script (start)");
256
257	# make hash of variables to be substituted if they appear in the script
258	my %subs;
259	for ( my $j = 0; $j <= $#{$variablesref}; $j++ )
260	{
261		my $variableline = ${$variablesref}[$j];
262
263		if ( $variableline =~ /^\s*(\%\w+?)\s+(.*?)\s*$/ )
264		{
265			$subs{$1}= $2;
266		}
267	}
268
269	# This is far faster than running a regexp for each line
270	my $bigstring = '';
271	for my $line (@{$scriptref}) { $bigstring = $bigstring . $line; }
272
273	foreach my $key ( keys %subs )
274	{
275		# Attention: It must be possible to substitute "%PRODUCTNAMEn", "%PRODUCTNAME%PRODUCTVERSIONabc"
276		my $value = $subs{$key};
277		$bigstring =~ s/$key/$value/g;
278	}
279
280	my @newlines = split /\n/, $bigstring;
281	$scriptref = \@newlines;
282
283	# now check for any mis-named '%' variables that we have left
284	my $num = 0;
285	for my $check (@newlines)
286	{
287		$num++;
288		if ( $check =~ /^.*\%\w+.*$/ )
289		{
290			if (( $check =~ /%1/ ) || ( $check =~ /%2/ ) || ( $check =~ /%verify/ ))
291            {
292                next;
293            }
294            $installer::logger::Global->printf(
295                "WARNING: mis-named or un-known '%s' variable in setup script at line %s:\n",
296                "%", $num);
297            $installer::logger::Global->printf("%s\n", $check);
298		}
299	}
300
301	installer::logger::include_header_into_globallogfile("Replacing variables in setup script (end)");
302
303	return $scriptref;
304}
305
306#######################################################################
307# Collecting all items of the type "searchitem" from the setup script
308#######################################################################
309
310sub get_all_items_from_script
311{
312	my ($scriptref, $searchitem) = @_;
313
314	my @allitemarray = ();
315
316	my ($itemkey, $itemvalue, $valuecounter);
317
318	for ( my $i = 0; $i <= $#{$scriptref}; $i++ )
319	{
320		my $line = ${$scriptref}[$i];
321
322		if ( $line =~ /^\s*\Q$searchitem\E\s+(\S+)\s*$/ )
323		{
324			my $gid = $1;
325			my $counter = $i + 1;
326
327			my %oneitemhash = ();
328			my $ismultilang = 0;
329
330			$oneitemhash{'gid'} = $gid;
331
332			while  (!( $line =~ /^\s*End\s*$/ ))
333			{
334				if ( $counter > $#{$scriptref} ) {
335					installer::exiter::exit_program("Invalid setup script file. End of file reached before 'End' line of '$searchitem' section.", "get_all_items_from_script");
336				}
337				$line = ${$scriptref}[$counter];
338				$counter++;
339
340				if ( $line =~ /^\s*(.+?)\s*\=\s*(.+?)\s*\;\s*$/ )	# only oneliner!
341				{
342					$itemkey = $1;
343					$itemvalue = $2;
344
345					installer::remover::remove_leading_and_ending_quotationmarks(\$itemvalue);
346					$itemvalue =~ s/\s*$//; # removing ending whitespaces. Could be introduced by empty variables.
347
348					$oneitemhash{$itemkey} = $itemvalue;
349
350					if ( $itemkey =~ /^\s*\S+\s+\(\S+\)\s*$/ )
351					{
352						$ismultilang = 1;
353					}
354				}
355				else
356				{
357					if ( $searchitem eq "Module" ) # more than one line, for instance files at modules!
358					{
359						if (( $line =~ /^\s*(.+?)\s*\=\s*\(/ ) && (!($line =~ /\)\;\s*$ / )))
360						{
361							if ( $line =~ /^\s*(.+?)\s*\=\s*(.+)/ )	# the first line
362							{
363								$itemkey = $1;
364								$itemvalue = $2;
365								$itemvalue =~ s/\s*$//;
366							}
367
368							# collecting the complete itemvalue
369
370							$valuecounter = $counter;
371							$line = ${$scriptref}[$valuecounter];
372							installer::remover::remove_leading_and_ending_whitespaces(\$line);
373							$itemvalue = $itemvalue . $line;
374
375							while (!( $line =~ /\)\;\s*$/ ))
376							{
377								$valuecounter++;
378								$line = ${$scriptref}[$valuecounter];
379								installer::remover::remove_leading_and_ending_whitespaces(\$line);
380								$itemvalue = $itemvalue . $line;
381							}
382
383							# removing ending ";"
384							$itemvalue =~ s/\;\s*$//;
385
386							$oneitemhash{$itemkey} = $itemvalue;
387
388							if ( $itemkey =~ /^\s*\S+\s+\(\S+\)\s*$/ )
389							{
390								$ismultilang = 1;
391							}
392						}
393					}
394				}
395			}
396
397			$oneitemhash{'ismultilingual'} = $ismultilang;
398
399			push(@allitemarray, \%oneitemhash);
400		}
401	}
402
403	return \@allitemarray;
404}
405
406######################################################################
407# Collecting all folder at folderitems, that are predefined values
408# For example: PREDEFINED_AUTOSTART
409######################################################################
410
411sub add_predefined_folder
412{
413	my ( $folderitemref, $folderref ) = @_;
414
415	for ( my $i = 0; $i <= $#{$folderitemref}; $i++ )
416	{
417		my $folderitem = ${$folderitemref}[$i];
418		my $folderid = $folderitem->{'FolderID'};
419
420		if ( $folderid =~ /PREDEFINED_/ )
421		{
422			if (! installer::existence::exists_in_array_of_hashes("gid", $folderid, $folderref))
423			{
424				my %folder = ();
425				$folder{'ismultilingual'} = "0";
426				$folder{'Name'} = "";
427				$folder{'gid'} = $folderid;
428
429				push(@{$folderref}, \%folder);
430			}
431		}
432	}
433}
434
435#####################################################################################
436# If folderitems are non-advertised, the component needs to have a registry key
437# below HKCU as key path. Therefore it is required, to mark the file belonging
438# to a non-advertised shortcut, that a special userreg_xxx registry key can be
439# created during packing process.
440#####################################################################################
441
442sub prepare_non_advertised_files
443{
444	my ( $folderitemref, $filesref ) = @_;
445
446	for ( my $i = 0; $i <= $#{$folderitemref}; $i++ )
447	{
448		my $folderitem = ${$folderitemref}[$i];
449		my $styles = "";
450		if ( $folderitem->{'Styles'} ) { $styles = $folderitem->{'Styles'}; }
451
452		if ( $styles =~ /\bNON_ADVERTISED\b/ )
453		{
454			my $fileid = $folderitem->{'FileID'};
455			if ( $folderitem->{'ComponentIDFile'} ) { $fileid = $folderitem->{'ComponentIDFile'}; }
456			my $onefile = installer::worker::find_file_by_id($filesref, $fileid);
457
458			# Attention: If $onefile with "FileID" is not found, this is not always an error.
459			# FileID can also contain an executable file, for example msiexec.exe.
460			if ( $onefile ne "" ) { $onefile->{'needs_user_registry_key'} = 1; }
461		}
462	}
463}
464
465#####################################################################################
466# Adding all variables defined in the installation object into the hash
467# of all variables from the zip list file.
468# This is needed if variables are defined in the installation object,
469# but not in the zip list file.
470# If there is a definition in the zip list file and in the installation
471# object, the installation object is more important
472#####################################################################################
473
474sub add_installationobject_to_variables
475{
476	my ($allvariables, $allscriptvariablesref) = @_;
477
478	for ( my $i = 0; $i <= $#{$allscriptvariablesref}; $i++ )
479	{
480		my $line = ${$allscriptvariablesref}[$i];
481
482		if ( $line =~ /^\s*\%(\w+)\s+(.*?)\s*$/ )
483		{
484			my $key = $1;
485			my $value = $2;
486
487			$allvariables->{$key} = $value;	# overwrite existing values from zip.lst
488		}
489	}
490}
491
492#####################################################################################
493# Adding all variables, that must be defined, but are not defined until now.
494# List of this varibles: @installer::globals::forced_properties
495#####################################################################################
496
497sub add_forced_properties
498{
499	my ($allvariables) = @_;
500
501	my $property;
502	foreach $property ( @installer::globals::forced_properties )
503	{
504		if ( ! exists($allvariables->{$property}) ) { $allvariables->{$property} = ""; }
505	}
506}
507
508#####################################################################################
509# Some properties are created automatically. It should be possible to
510# overwrite them, with PRESET properties. For example UNIXPRODUCTNAME
511# with PRESETUNIXPRODUCTNAME, if this is defined and the automatic process
512# does not deliver the desired results.
513#####################################################################################
514
515sub replace_preset_properties
516{
517	my ($allvariables) = @_;
518
519	# SOLARISBRANDPACKAGENAME
520	# needs to be replaced by
521	# PRESETSOLARISBRANDPACKAGENAME
522
523	my @presetproperties = ();
524	push(@presetproperties, "SOLARISBRANDPACKAGENAME");
525	push(@presetproperties, "SYSTEMINTUNIXPACKAGENAME");
526
527
528	foreach my $property (@presetproperties)
529	{
530		my $presetproperty = "PRESET" . $property;
531		if (( exists($allvariables->{$presetproperty}) ) && ( $allvariables->{$presetproperty} ne "" ))
532		{
533			$allvariables->{$property} = $allvariables->{$presetproperty};
534		}
535	}
536}
537
5381;
539