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::scriptitems;
25
26use installer::converter;
27use installer::existence;
28use installer::exiter;
29use installer::globals;
30use installer::languages;
31use installer::logger;
32use installer::pathanalyzer;
33use installer::remover;
34use installer::systemactions;
35
36################################################################
37# Resolving the GID for the directories defined in setup script
38################################################################
39
40sub resolve_all_directory_names
41{
42	my ($directoryarrayref) = @_;
43
44	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::resolve_all_directory_names : $#{$directoryarrayref}"); }
45
46	# After this procedure the hash shall contain the complete language
47	# dependent path, not only the language dependent HostName.
48
49	my ($key, $value, $parentvalue, $parentgid, $parentdirectoryhashref);
50
51	for ( my $i = 0; $i <= $#{$directoryarrayref}; $i++ )
52	{
53		my $directoryhashref = ${$directoryarrayref}[$i];
54		my $gid = $directoryhashref-> {'gid'};
55		my $parentid = $directoryhashref-> {'ParentID'};
56
57		if ( $parentid ne "PREDEFINED_PROGDIR" )
58		{
59			# find the array of the parentid, which has to be defined before in setup script
60			# and is therefore listed before in this array
61
62			for ( my $j = 0; $j <= $i; $j++ )
63			{
64				$parentdirectoryhashref = ${$directoryarrayref}[$j];
65				$parentgid = $parentdirectoryhashref->{'gid'};
66
67				if ( $parentid eq $parentgid)
68				{
69					last;
70				}
71			}
72
73			# and now we can put the path together
74			# But take care of the languages!
75
76			my $dirismultilingual = $directoryhashref->{'ismultilingual'};
77			my $parentismultilingual = $parentdirectoryhashref->{'ismultilingual'};
78
79			# First: Both directories are language independent or both directories are language dependent
80
81			if ((( ! $dirismultilingual ) && ( ! $parentismultilingual )) ||
82				(( $dirismultilingual ) && ( $parentismultilingual )))
83			{
84				foreach $key (keys %{$directoryhashref})
85				{
86					# the key ("HostName (en-US)") must be usable for both hashes
87
88					if ( $key =~ /\bHostName\b/ )
89					{
90						$parentvalue = "";
91						$value = $directoryhashref->{$key};
92						if ( $parentdirectoryhashref->{$key} ) { $parentvalue = $parentdirectoryhashref->{$key}; }
93
94						# It is possible, that in scp project, a directory is defined in more languages than
95						# the directory parent (happened after automatic generation of macros.inc).
96						# Therefore this is checked now and written with a warning into the logfile.
97						# This is no error, because (in most cases) the concerned language is not build.
98
99						if ($parentvalue eq "")
100						{
101							$directoryhashref->{$key} = "FAILURE";
102							my $infoline = "WARNING: No hostname for $parentid with \"$key\". Needed by child directory $gid !\n";
103							push( @installer::globals::globallogfileinfo, $infoline);
104						}
105						else
106						{
107							$directoryhashref->{$key} = $parentvalue . $installer::globals::separator . $value;
108						}
109					}
110				}
111			}
112
113			# Second: The directory is language dependent, the parent not
114
115			if (( $dirismultilingual ) && ( ! $parentismultilingual ))
116			{
117				$parentvalue = $parentdirectoryhashref->{'HostName'};		# there is only one
118
119				foreach $key (keys %{$directoryhashref})		# the current directory
120				{
121					if ( $key =~ /\bHostName\b/ )
122					{
123						$value = $directoryhashref->{$key};
124						$directoryhashref->{$key} = $parentvalue . $installer::globals::separator . $value;
125					}
126				}
127			}
128
129			# Third: The directory is not language dependent, the parent is language dependent
130
131			if (( ! $dirismultilingual ) && ( $parentismultilingual ))
132			{
133				$value = $directoryhashref->{'HostName'};		# there is only one
134				delete($directoryhashref->{'HostName'});
135
136				foreach $key (keys %{$parentdirectoryhashref})		# the parent directory
137				{
138					if ( $key =~ /\bHostName\b/ )
139					{
140						$parentvalue = $parentdirectoryhashref->{$key};		# there is only one
141						$directoryhashref->{$key} = $parentvalue . $installer::globals::separator . $value;
142					}
143				}
144
145				$directoryhashref->{'ismultilingual'} = 1;	# now this directory is also language dependent
146			}
147		}
148	}
149}
150
151#############################################################################
152# Files with flag DELETE_ONLY do not need to be packed into installation set
153#############################################################################
154
155sub remove_delete_only_files_from_productlists
156{
157	my ($productarrayref) = @_;
158
159	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_delete_only_files_from_productlists : $#{$productarrayref}"); }
160
161	my @newitems = ();
162
163	for ( my $i = 0; $i <= $#{$productarrayref}; $i++ )
164	{
165		my $oneitem = ${$productarrayref}[$i];
166		my $styles = "";
167
168		if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
169
170		if (!($styles =~ /\bDELETE_ONLY\b/))
171		{
172			push(@newitems, $oneitem);
173		}
174	}
175
176	return \@newitems;
177}
178
179#############################################################################
180# Files with flag NOT_IN_SUITE do not need to be packed into
181# Suite installation sets
182#############################################################################
183
184sub remove_notinsuite_files_from_productlists
185{
186	my ($productarrayref) = @_;
187
188	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_notinsuite_files_from_productlists : $#{$productarrayref}"); }
189
190	my @newitems = ();
191
192	for ( my $i = 0; $i <= $#{$productarrayref}; $i++ )
193	{
194		my $oneitem = ${$productarrayref}[$i];
195		my $styles = "";
196
197		if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
198
199		if (!($styles =~ /\bNOT_IN_SUITE\b/))
200		{
201			push(@newitems, $oneitem);
202		}
203		else
204		{
205			my $infoline = "INFO: Flag NOT_IN_SUITE \-\> Removing $oneitem->{'gid'} from file list.\n";
206			push( @installer::globals::globallogfileinfo, $infoline);
207		}
208	}
209
210	return \@newitems;
211}
212
213#############################################################################
214# Files with flag NOT_IN_SUITE do not need to be packed into
215# Suite installation sets
216#############################################################################
217
218sub remove_office_start_language_files
219{
220	my ($productarrayref) = @_;
221
222	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_notinsuite_files_from_productlists : $#{$productarrayref}"); }
223
224	my @newitems = ();
225
226	for ( my $i = 0; $i <= $#{$productarrayref}; $i++ )
227	{
228		my $oneitem = ${$productarrayref}[$i];
229		my $styles = "";
230
231		if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
232
233		if (!($styles =~ /\bSET_OFFICE_LANGUAGE\b/))
234		{
235			push(@newitems, $oneitem);
236		}
237		else
238		{
239			my $infoline = "INFO: Flag SET_OFFICE_LANGUAGE \-\> Removing $oneitem->{'gid'} from file list.\n";
240			push( @installer::globals::logfileinfo, $infoline);
241		}
242	}
243
244	return \@newitems;
245}
246
247#############################################################################
248# Registryitems for Uninstall have to be removed
249#############################################################################
250
251sub remove_uninstall_regitems_from_script
252{
253	my ($registryarrayref) = @_;
254
255	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_uninstall_regitems_from_script : $#{$registryarrayref}"); }
256
257	my @newitems = ();
258
259	for ( my $i = 0; $i <= $#{$registryarrayref}; $i++ )
260	{
261		my $oneitem = ${$registryarrayref}[$i];
262		my $subkey = "";
263
264		if ( $oneitem->{'Subkey'} ) { $subkey = $oneitem->{'Subkey'}; }
265
266		if ( $subkey =~ /Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall/ ) { next; }
267
268		push(@newitems, $oneitem);
269	}
270
271	return \@newitems;
272}
273
274##############################################################################
275# Searching the language module for a specified language
276##############################################################################
277
278sub get_languagespecific_module
279{
280	my ( $lang, $modulestring ) = @_;
281
282	my $langmodulestring = "";
283
284	my $module;
285	foreach	$module ( keys %installer::globals::alllangmodules )
286	{
287		if (( $installer::globals::alllangmodules{$module} eq $lang ) && ( $modulestring =~ /\b$module\b/ ))
288		{
289			$langmodulestring = "$langmodulestring,$module";
290		}
291	}
292
293	$langmodulestring =~ s/^\s*,//;
294
295	if ( $langmodulestring eq "" ) { installer::exiter::exit_program("ERROR: No language pack module found for language $lang in string \"$modulestring\"!", "get_languagespecific_module");  }
296
297	return $langmodulestring;
298}
299
300##############################################################################
301# Removing all items in product lists which do not have the correct languages
302##############################################################################
303
304sub resolving_all_languages_in_productlists
305{
306	my ($productarrayref, $languagesarrayref) = @_;
307
308	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::resolving_all_languages_in_productlists : $#{$productarrayref} : $#{$languagesarrayref}"); }
309
310	my @itemsinalllanguages = ();
311
312	my ($key, $value);
313
314	for ( my $i = 0; $i <= $#{$productarrayref}; $i++ )
315	{
316		my $oneitem = ${$productarrayref}[$i];
317
318		my $ismultilingual = $oneitem->{'ismultilingual'};
319
320		if (!($ismultilingual))	# nothing to do with single language items
321		{
322			$oneitem->{'specificlanguage'} = "";
323			push(@itemsinalllanguages, $oneitem);
324		}
325		else	#all language dependent files
326		{
327			for ( my $j = 0; $j <= $#{$languagesarrayref}; $j++ )	# iterating over all languages
328			{
329				my $onelanguage = ${$languagesarrayref}[$j];
330
331				my %oneitemhash = ();
332
333				foreach $key (keys %{$oneitem})
334				{
335					if ( $key =~ /\(\S+\)/ )	# this are the language dependent keys
336					{
337						if ( $key =~ /\(\Q$onelanguage\E\)/ )
338						{
339							$value = $oneitem->{$key};
340							$oneitemhash{$key} = $value;
341						}
342					}
343					else
344					{
345						$value = $oneitem->{$key};
346						$oneitemhash{$key} = $value;
347					}
348				}
349
350				$oneitemhash{'specificlanguage'} = $onelanguage;
351
352				if ( $oneitemhash{'haslanguagemodule'} )
353				{
354					my $langmodulestring = get_languagespecific_module($onelanguage, $oneitemhash{'modules'});
355					$oneitemhash{'modules'} = $langmodulestring;
356				}
357
358				push(@itemsinalllanguages, \%oneitemhash);
359			}
360		}
361	}
362
363	return \@itemsinalllanguages;
364}
365
366################################################################################
367# Removing all modules, that have the flag LANGUAGEMODULE, but do not
368# have the correct language
369################################################################################
370
371sub remove_not_required_language_modules
372{
373	my ($modulesarrayref, $languagesarrayref) = @_;
374
375	my @allmodules = ();
376
377	for ( my $i = 0; $i <= $#{$modulesarrayref}; $i++ )
378	{
379		my $module = ${$modulesarrayref}[$i];
380		my $styles = "";
381		if ( $module->{'Styles'} ) { $styles = $module->{'Styles'}; }
382
383		if ( $styles =~ /\bLANGUAGEMODULE\b/ )
384		{
385			if ( ! exists($module->{'Language'}) ) { installer::exiter::exit_program("ERROR: \"$module->{'gid'}\" has flag LANGUAGEMODULE, but does not know its language!", "remove_not_required_language_modules"); }
386			my $modulelanguage = $module->{'Language'};
387			# checking, if language is required
388			my $doinclude = 0;
389			for ( my $j = 0; $j <= $#{$languagesarrayref}; $j++ )
390			{
391				my $onelanguage = ${$languagesarrayref}[$j];
392				if ( $onelanguage eq $modulelanguage )
393				{
394					$doinclude = 1;
395					last;
396				}
397			}
398
399			if ( $doinclude ) { push(@allmodules, $module); }
400		}
401		else
402		{
403			push(@allmodules, $module);
404		}
405	}
406
407	return \@allmodules;
408}
409
410################################################################################
411# Removing all modules, that have a spellchecker language that is not
412# required for this product (spellchecker selection).
413# All required spellchecker languages are stored in
414# %installer::globals::spellcheckerlanguagehash
415################################################################################
416
417sub remove_not_required_spellcheckerlanguage_modules
418{
419	my ($modulesarrayref) = @_;
420
421	my $infoline = "";
422	my @allmodules = ();
423
424	for ( my $i = 0; $i <= $#{$modulesarrayref}; $i++ )
425	{
426		my $module = ${$modulesarrayref}[$i];
427		if ( $module->{'Spellcheckerlanguage'} )	# selecting modules with Spellcheckerlanguage
428		{
429			if ( exists($installer::globals::spellcheckerlanguagehash{$module->{'Spellcheckerlanguage'}}) )
430			{
431				push(@allmodules, $module);
432			}
433			else
434			{
435				$infoline = "Spellchecker selection: Removing module $module->{'gid'}\n";
436				push( @installer::globals::logfileinfo, $infoline);
437
438				# Collecting all files at modules that are removed
439
440				if ( $module->{'Files'} )
441				{
442					if ( $module->{'Files'} =~ /^\s*\((.*?)\)\s*$/ )
443					{
444						my $filelist = $1;
445
446						my $filelisthash = installer::converter::convert_stringlist_into_hash(\$filelist, ",");
447						foreach my $onefile ( keys %{$filelisthash} ) { $installer::globals::spellcheckerfilehash{$onefile} = 1; }
448					}
449				}
450			}
451		}
452		else
453		{
454			push(@allmodules, $module);
455		}
456	}
457
458	return \@allmodules;
459}
460
461################################################################################
462# Removing all modules, that belong to a module that was removed
463# in "remove_not_required_spellcheckerlanguage_modules" because of the
464# spellchecker language. The files belonging to the modules are collected
465# in %installer::globals::spellcheckerfilehash.
466################################################################################
467
468sub remove_not_required_spellcheckerlanguage_files
469{
470	my ($filesarrayref) = @_;
471
472	my @filesarray = ();
473	my $infoline = "";
474
475	for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
476	{
477		my $onefile = ${$filesarrayref}[$i];
478		if ( exists($installer::globals::spellcheckerfilehash{$onefile->{'gid'}}) )
479		{
480			$infoline = "Spellchecker selection: Removing file $onefile->{'gid'}\n";
481			push( @installer::globals::logfileinfo, $infoline);
482			next;
483		}
484		push(@filesarray, $onefile);
485	}
486
487	return \@filesarray;
488}
489
490################################################################################
491# Looking for directories without correct HostName
492################################################################################
493
494sub checking_directories_with_corrupt_hostname
495{
496	my ($dirsref, $languagesarrayref) = @_;
497
498	for ( my $i = 0; $i <= $#{$dirsref}; $i++ )
499	{
500		my $onedir = ${$dirsref}[$i];
501
502		my $hostname = "";
503
504		if ( $onedir->{'HostName'} ) { $hostname = $onedir->{'HostName'}; }
505
506		if ( $hostname eq "" )
507		{
508			my $langstring = "";
509			for ( my $j = 0; $j <= $#{$languagesarrayref}; $j++ ) { $langstring .= ${$languagesarrayref}[$j] . " "; }
510			installer::exiter::exit_program("ERROR: HostName not defined for $onedir->{'gid'} for specified language. Probably you wanted to create an installation set, in a language not defined in scp2 project. You selected the following language(s): $langstring", "checking_directories_with_corrupt_hostname");
511		}
512
513		if ( $hostname eq "FAILURE" )
514		{
515			installer::exiter::exit_program("ERROR: Could not create HostName for $onedir->{'gid'} (missing language at parent). See logfile warning for more info!", "checking_directories_with_corrupt_hostname");
516		}
517	}
518}
519
520################################################################################
521# Setting global properties
522################################################################################
523
524sub set_global_directory_hostnames
525{
526	my ($dirsref, $allvariables) = @_;
527
528	for ( my $i = 0; $i <= $#{$dirsref}; $i++ )
529	{
530		my $onedir = ${$dirsref}[$i];
531		my $styles = "";
532		if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; }
533
534		if ( $styles =~ /\bOFFICEDIRECTORY\b/ )
535		{
536			$installer::globals::officedirhostname = $onedir->{'HostName'};
537			$installer::globals::officedirgid = $onedir->{'gid'};
538			$allvariables->{'OFFICEDIRECTORYHOSTNAME'} = $installer::globals::officedirhostname;
539		}
540		if ( $styles =~ /\bSUNDIRECTORY\b/ )
541		{
542			$installer::globals::sundirhostname = $onedir->{'HostName'};
543			$installer::globals::sundirgid = $onedir->{'gid'};
544			$allvariables->{'SUNDIRECTORYHOSTNAME'} = $installer::globals::sundirhostname;
545		}
546	}
547}
548
549########################################################
550# Recursively defined procedure to order
551# modules and directories
552########################################################
553
554sub get_children
555{
556	my ($allitems, $startparent, $newitemorder) = @_;
557
558	for ( my $i = 0; $i <= $#{$allitems}; $i++ )
559	{
560		my $gid = ${$allitems}[$i]->{'gid'};
561		my $parent = "";
562		if ( ${$allitems}[$i]->{'ParentID'} ) { $parent = ${$allitems}[$i]->{'ParentID'}; }
563
564		if ( $parent eq $startparent )
565		{
566			push(@{$newitemorder}, ${$allitems}[$i]);
567			my $parent = $gid;
568			get_children($allitems, $parent, $newitemorder);	# recursive!
569		}
570	}
571}
572
573################################################################################
574# Using different HostName for language packs
575################################################################################
576
577sub use_langpack_hostname
578{
579	my ($dirsref) = @_;
580
581	for ( my $i = 0; $i <= $#{$dirsref}; $i++ )
582	{
583		my $onedir = ${$dirsref}[$i];
584		if (( $onedir->{'LangPackHostName'} ) && ( $onedir->{'LangPackHostName'} ne "" )) { $onedir->{'HostName'} = $onedir->{'LangPackHostName'}; }
585	}
586}
587
588################################################################################
589# Using different HostName for language packs
590################################################################################
591
592sub use_patch_hostname
593{
594	my ($dirsref) = @_;
595
596	for ( my $i = 0; $i <= $#{$dirsref}; $i++ )
597	{
598		my $onedir = ${$dirsref}[$i];
599		if (( $onedir->{'PatchHostName'} ) && ( $onedir->{'PatchHostName'} ne "" )) { $onedir->{'HostName'} = $onedir->{'PatchHostName'}; }
600	}
601}
602
603################################################################################
604# Using langpack copy action for language packs
605################################################################################
606
607sub use_langpack_copy_scpaction
608{
609	my ($scpactionsref) = @_;
610
611	for ( my $i = 0; $i <= $#{$scpactionsref}; $i++ )
612	{
613		my $onescpaction = ${$scpactionsref}[$i];
614		if (( $onescpaction->{'LangPackCopy'} ) && ( $onescpaction->{'LangPackCopy'} ne "" )) { $onescpaction->{'Copy'} = $onescpaction->{'LangPackCopy'}; }
615	}
616}
617
618################################################################################
619# Using copy patch action
620################################################################################
621
622sub use_patch_copy_scpaction
623{
624	my ($scpactionsref) = @_;
625
626	for ( my $i = 0; $i <= $#{$scpactionsref}; $i++ )
627	{
628		my $onescpaction = ${$scpactionsref}[$i];
629		if (( $onescpaction->{'PatchCopy'} ) && ( $onescpaction->{'PatchCopy'} ne "" )) { $onescpaction->{'Copy'} = $onescpaction->{'PatchCopy'}; }
630	}
631}
632
633################################################################################
634# Using dev copy patch action for developer snapshot builds
635################################################################################
636
637sub use_dev_copy_scpaction
638{
639	my ($scpactionsref) = @_;
640
641	for ( my $i = 0; $i <= $#{$scpactionsref}; $i++ )
642	{
643		my $onescpaction = ${$scpactionsref}[$i];
644		if (( $onescpaction->{'DevCopy'} ) && ( $onescpaction->{'DevCopy'} ne "" )) { $onescpaction->{'Copy'} = $onescpaction->{'DevCopy'}; }
645	}
646}
647
648################################################################################
649# Shifting parent directories of URE and Basis layer, so that
650# these directories are located below the Brand layer.
651# Style: SHIFT_BASIS_INTO_BRAND_LAYER
652################################################################################
653
654sub shift_basis_directory_parents
655{
656	my ($dirsref) = @_;
657
658	my @alldirs = ();
659	my @savedirs = ();
660	my @shifteddirs = ();
661
662	my $officedirgid = "";
663
664	for ( my $i = 0; $i <= $#{$dirsref}; $i++ )
665	{
666		my $onedir = ${$dirsref}[$i];
667		my $styles = "";
668		if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; }
669
670		if ( $styles =~ /\bOFFICEDIRECTORY\b/ ) { $officedirgid = $onedir->{'gid'}; }
671	}
672
673	if ( $officedirgid ne "" )
674	{
675		for ( my $i = 0; $i <= $#{$dirsref}; $i++ )
676		{
677			my $onedir = ${$dirsref}[$i];
678			my $styles = "";
679			if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; }
680
681			if (( $styles =~ /\bBASISDIRECTORY\b/ ) || ( $styles =~ /\bUREDIRECTORY\b/ ))
682			{
683				$onedir->{'ParentID'} = $officedirgid;
684			}
685		}
686
687		# Sorting directories
688		my $startgid = "PREDEFINED_PROGDIR";
689		get_children($dirsref, $startgid, \@alldirs);
690	}
691
692	return \@alldirs;
693}
694
695################################################################################
696# Setting the name of the directory with style OFFICEDIRECTORY.
697# The name can be defined in property OFFICEDIRECTORYNAME.
698################################################################################
699
700sub set_officedirectory_name
701{
702	my ($dirsref, $officedirname) = @_;
703
704	for ( my $i = 0; $i <= $#{$dirsref}; $i++ )
705	{
706		my $onedir = ${$dirsref}[$i];
707		my $styles = "";
708		if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; }
709		if ( $styles =~ /\bOFFICEDIRECTORY\b/ )
710		{
711			$onedir->{'HostName'} = $officedirname;
712			last;
713		}
714	}
715}
716
717################################################################################
718# Simplifying the name for language dependent items from "Name (xy)" to "Name"
719################################################################################
720
721sub changing_name_of_language_dependent_keys
722{
723	my ($itemsarrayref) = @_;
724
725	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::changing_name_of_language_dependent_keys : $#{$itemsarrayref}"); }
726
727	# Changing key for multilingual items from "Name ( )" to "Name" or "HostName ( )" to "HostName"
728
729	for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
730	{
731		my $oneitem = ${$itemsarrayref}[$i];
732		my $onelanguage = $oneitem->{'specificlanguage'};
733
734		if (!($onelanguage eq "" )) 				# language dependent item
735		{
736			my $itemkey;
737
738			foreach $itemkey (keys %{$oneitem})
739			{
740				if ( $itemkey =~ /^\s*(\S+?)\s+\(\S+\)\s*$/ )
741				{
742					my $newitemkey = $1;
743					my $itemvalue = $oneitem->{$itemkey};
744					$oneitem->{$newitemkey} = $itemvalue;
745					delete($oneitem->{$itemkey});
746				}
747			}
748		}
749	}
750}
751
752################################################################################
753# Collecting language specific names for language packs
754################################################################################
755
756sub collect_language_specific_names
757{
758	my ($itemsarrayref) = @_;
759
760	for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
761	{
762		my $oneitem = ${$itemsarrayref}[$i];
763		my $styles = "";
764		if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
765
766		if ( $styles =~ /\bUSELANGUAGENAME\b/ )
767		{
768			my $language = "";
769			if ( $oneitem->{'Language'} ) { $language = $oneitem->{'Language'}; }
770			my $specificlanguage = "";
771			if ( $oneitem->{'specificlanguage'} ) { $specificlanguage = $oneitem->{'specificlanguage'}; }
772
773			if (( $language ne "" ) && ( $language eq $specificlanguage ))
774			{
775				if (! installer::existence::exists_in_array($oneitem->{'Name'}, \@installer::globals::languagenames ))
776				{
777					push(@installer::globals::languagenames, $oneitem->{'Name'});
778				}
779			}
780		}
781	}
782}
783
784################################################################################
785# Replacement of setup variables in ConfigurationItems and ProfileItems
786# <productkey>, <buildid>, <sequence_languages>, <productcode>, <upgradecode>, <productupdate>
787################################################################################
788
789sub replace_setup_variables
790{
791	my ($itemsarrayref, $languagestringref, $hashref) = @_;
792
793	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::replace_setup_variables : $#{$itemsarrayref} : $$languagestringref : $hashref->{'PRODUCTNAME'}"); }
794
795	my $languagesstring = $$languagestringref;
796	$languagesstring =~ s/\_/ /g;	# replacing underscore with whitespace
797	# $languagesstring is "01 49" instead of "en-US de"
798	installer::languages::fake_languagesstring(\$languagesstring);
799
800	my $productname = $hashref->{'PRODUCTNAME'};
801	my $productversion = $hashref->{'PRODUCTVERSION'};
802	my $userdirproductversion = "";
803	if ( $hashref->{'USERDIRPRODUCTVERSION'} ) { $userdirproductversion = $hashref->{'USERDIRPRODUCTVERSION'}; }
804	my $productkey = $productname . " " . $productversion;
805
806	# string $buildid, which is used to replace the setup variable <buildid>
807
808	my $localminor = "flat";
809	if ( $installer::globals::minor ne "" ) { $localminor = $installer::globals::minor; }
810	else { $localminor = $installer::globals::lastminor; }
811
812	my $localbuild = $installer::globals::build;
813
814	if ( $localbuild =~ /^\s*(\w+?)(\d+)\s*$/ ) { $localbuild = $2; }	# using "680" instead of "src680"
815
816	my $buildidstring = $localbuild . $localminor . "(Build:" . $installer::globals::buildid . ")";
817
818	# the environment variable CWS_WORK_STAMP is set only in CWS
819	if ( $ENV{'CWS_WORK_STAMP'} ) { $buildidstring = $buildidstring . "\[CWS\:" . $ENV{'CWS_WORK_STAMP'} . "\]"; }
820
821	if ( $localminor =~ /^\s*\w(\d+)\w*\s*$/ ) { $localminor = $1; }
822
823	# $updateid
824	my $updateid = $productname . "_" . $userdirproductversion . "_" . $$languagestringref;
825	$updateid =~ s/ /_/g;
826
827	for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
828	{
829		my $oneitem = ${$itemsarrayref}[$i];
830		my $value = $oneitem->{'Value'};
831
832		$value =~ s/\<buildid\>/$buildidstring/;
833		$value =~ s/\<sequence_languages\>/$languagesstring/;
834		$value =~ s/\<productkey\>/$productkey/;
835		$value =~ s/\<productcode\>/$installer::globals::productcode/;
836		$value =~ s/\<upgradecode\>/$installer::globals::upgradecode/;
837		$value =~ s/\<alllanguages\>/$languagesstring/;
838		$value =~ s/\<productmajor\>/$localbuild/;
839		$value =~ s/\<productminor\>/$localminor/;
840		$value =~ s/\<productbuildid\>/$installer::globals::buildid/;
841		$value =~ s/\<sourceid\>/$installer::globals::build/;
842		$value =~ s/\<updateid\>/$updateid/;
843		$value =~ s/\<pkgformat\>/$installer::globals::packageformat/;
844
845		$oneitem->{'Value'} = $value;
846	}
847}
848
849################################################################################
850# By defining variable LOCALUSERDIR in *.lst it is possible to change
851# the standard destination of user directory defined in scp2 ($SYSUSERCONFIG).
852################################################################################
853
854sub replace_userdir_variable
855{
856	my ($itemsarrayref) = @_;
857
858	my $userdir = "";
859	if ( $allvariableshashref->{'LOCALUSERDIR'} ) { $userdir = $allvariableshashref->{'LOCALUSERDIR'}; }
860	else { $userdir = $installer::globals::simpledefaultuserdir; }
861
862	if ( $userdir ne "" )
863	{
864		for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
865		{
866			my $oneitem = ${$itemsarrayref}[$i];
867			$oneitem->{'Value'} =~ s/\$SYSUSERCONFIG/$userdir/;
868		}
869	}
870}
871
872#####################################################################################
873# Files and ConfigurationItems are not included for all languages.
874# For instance asian fonts. These can be removed, if no "Name" is found.
875# ConfigurationItems are not always defined in the linguistic configuration file.
876# The "Key" cannot be found for them.
877#####################################################################################
878
879sub remove_non_existent_languages_in_productlists
880{
881	my ($itemsarrayref, $languagestringref, $searchkey, $itemtype) = @_;
882
883	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_non_existent_languages_in_productlists : $#{$itemsarrayref} : $$languagestringref : $searchkey : $itemtype"); }
884
885	# Removing of all non existent files, for instance asian fonts
886
887	installer::logger::include_header_into_logfile("Removing for this language $$languagestringref:");
888
889	my @allexistentitems = ();
890
891	my $infoline;
892
893	for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
894	{
895		my $oneitem = ${$itemsarrayref}[$i];
896		my $oneitemname = "";		# $searchkey is "Name" for files and "Key" for ConfigurationItems
897
898		if ( $oneitem->{$searchkey} ) { $oneitemname = $oneitem->{$searchkey} }
899
900		my $itemtoberemoved = 0;
901
902		if ($oneitemname eq "") 					# for instance asian font in english installation set
903		{
904			$itemtoberemoved = 1;
905		}
906
907		if ($itemtoberemoved)
908		{
909			$infoline = "WARNING: Language $$languagestringref: No $itemtype packed for $oneitem->{'gid'}!\n";
910			push( @installer::globals::logfileinfo, $infoline);
911		}
912		else
913		{
914			push(@allexistentitems, $oneitem);
915		}
916	}
917
918	$infoline = "\n";
919	push( @installer::globals::logfileinfo, $infoline);
920
921	return \@allexistentitems;
922}
923
924########################################################################
925# Input is the directory gid, output the "HostName" of the directory
926########################################################################
927
928sub get_Directoryname_From_Directorygid
929{
930	my ($dirsarrayref ,$searchgid, $onelanguage, $oneitemgid) = @_;
931
932	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_Directoryname_From_Directorygid : $#{$dirsarrayref} : $searchgid : $onelanguage"); }
933
934	my $directoryname = "";
935	my $onedirectory;
936	my $foundgid = 0;
937
938	for ( my $i = 0; $i <= $#{$dirsarrayref}; $i++ )
939	{
940		$onedirectory = ${$dirsarrayref}[$i];
941		my $directorygid = $onedirectory->{'gid'};
942
943		if ($directorygid eq $searchgid)
944		{
945			$foundgid = 1;
946			last;
947		}
948	}
949
950	if (!($foundgid))
951	{
952		installer::exiter::exit_program("ERROR: Gid $searchgid not defined in $installer::globals::setupscriptname", "get_Directoryname_From_Directorygid");
953	}
954
955	if ( ! ( $onedirectory->{'ismultilingual'} ))	# the directory is not language dependent
956	{
957 		$directoryname = $onedirectory->{'HostName'};
958	}
959	else
960	{
961		$directoryname = $onedirectory->{"HostName ($onelanguage)"};
962	}
963
964	# gid_Dir_Template_Wizard_Letter is defined as language dependent directory, but the file gid_Dir_Template_Wizard_Letter
965	# is not language dependent. Therefore $onelanguage is not defined. But which language is the correct language for the
966	# directory?
967	# Perhaps better solution: In scp it must be forbidden to have a language independent file in a language dependent directory.
968
969	if (( ! $directoryname ) && ( $onelanguage eq "" ))
970	{
971		installer::exiter::exit_program("ERROR (in scp): Directory $searchgid is language dependent, but not $oneitemgid inside this directory", "get_Directoryname_From_Directorygid");
972	}
973
974	return \$directoryname;
975}
976
977##################################################################
978# Getting destination direcotory for links, files and profiles
979##################################################################
980
981sub get_Destination_Directory_For_Item_From_Directorylist		# this is used for Files, Profiles and Links
982{
983	my ($itemarrayref, $dirsarrayref) = @_;
984
985	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_Destination_Directory_For_Item_From_Directorylist : $#{$itemarrayref} : $#{$dirsarrayref}"); }
986
987	for ( my $i = 0; $i <= $#{$itemarrayref}; $i++ )
988	{
989		my $oneitem = ${$itemarrayref}[$i];
990		my $oneitemgid = $oneitem->{'gid'};
991		my $directorygid = $oneitem->{'Dir'};		# for instance gid_Dir_Program
992		my $netdirectorygid = "";
993		my $onelanguage = $oneitem->{'specificlanguage'};
994		my $ispredefinedprogdir = 0;
995		my $ispredefinedconfigdir = 0;
996
997		my $oneitemname = $oneitem->{'Name'};
998
999		if ( $oneitem->{'NetDir'} ) { $netdirectorygid = $oneitem->{'NetDir'}; }
1000
1001		installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$oneitemname);	# making /registry/schema/org/openoffice/VCL.xcs to VCL.xcs
1002
1003		my $searchdirgid;
1004
1005		if ( $netdirectorygid eq "" )	# if NetDir is defined, it is privileged
1006		{
1007			$searchdirgid = $directorygid
1008		}
1009		else
1010		{
1011			$searchdirgid = $netdirectorygid
1012		}
1013
1014		if ($searchdirgid =~ /PREDEFINED_PROGDIR/)	# the root directory is not defined in setup script
1015		{
1016			$ispredefinedprogdir = 1;
1017		}
1018
1019		if ($searchdirgid =~ /PREDEFINED_CONFIGDIR/)	# the root directory is not defined in setup script
1020		{
1021			$ispredefinedconfigdir = 1;
1022		}
1023
1024		my $destfilename;
1025
1026		if ((!( $ispredefinedprogdir )) && (!( $ispredefinedconfigdir )))
1027		{
1028			my $directorynameref = get_Directoryname_From_Directorygid($dirsarrayref, $searchdirgid, $onelanguage, $oneitemgid);
1029			$destfilename = $$directorynameref . $installer::globals::separator . $oneitemname;
1030		}
1031		else
1032		{
1033			$destfilename = $oneitemname;
1034		}
1035
1036		$oneitem->{'destination'} = $destfilename;
1037	}
1038}
1039
1040##########################################################################
1041# Searching a file in a list of pathes
1042##########################################################################
1043
1044sub get_sourcepath_from_filename_and_includepath_classic
1045{
1046	my ($searchfilenameref, $includepatharrayref, $write_logfile) = @_;
1047
1048	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_sourcepath_from_filename_and_includepath_classic : $$searchfilenameref : $#{$includepatharrayref} : $write_logfile"); }
1049
1050	my ($onefile, $includepath, $infoline);
1051
1052	my $foundsourcefile = 0;
1053
1054	for ( my $j = 0; $j <= $#{$includepatharrayref}; $j++ )
1055	{
1056		$includepath = ${$includepatharrayref}[$j];
1057		installer::remover::remove_leading_and_ending_whitespaces(\$includepath);
1058
1059		$onefile = $includepath . $installer::globals::separator . $$searchfilenameref;
1060
1061		if ( -f $onefile )
1062		{
1063			$foundsourcefile = 1;
1064			last;
1065		}
1066	}
1067
1068	if (!($foundsourcefile))
1069	{
1070		$onefile = "";	# the sourcepath has to be empty
1071		if ( $write_logfile)
1072		{
1073			if ( $ENV{'DEFAULT_TO_ENGLISH_FOR_PACKING'} )
1074			{
1075				$infoline = "WARNING: Source for $$searchfilenameref not found!\n";	 # Important message in log file
1076			}
1077			else
1078			{
1079				$infoline = "ERROR: Source for $$searchfilenameref not found!\n";	 # Important message in log file
1080			}
1081
1082			push( @installer::globals::logfileinfo, $infoline);
1083		}
1084	}
1085	else
1086	{
1087		if ( $write_logfile)
1088		{
1089			$infoline = "SUCCESS: Source for $$searchfilenameref: $onefile\n";
1090			push( @installer::globals::logfileinfo, $infoline);
1091		}
1092	}
1093
1094	return \$onefile;
1095}
1096
1097##########################################################################
1098# Input is one file name, output the complete absolute path of this file
1099##########################################################################
1100
1101sub get_sourcepath_from_filename_and_includepath
1102{
1103	my ($searchfilenameref, $unused, $write_logfile) = @_;
1104
1105	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_sourcepath_from_filename_and_includepath : $$searchfilenameref : $#{$includepatharrayref} : $write_logfile"); }
1106
1107	my ($onefile, $includepath, $infoline);
1108
1109	my $foundsourcefile = 0;
1110	my $foundnewname = 0;
1111
1112	for ( my $j = 0; $j <= $#installer::globals::allincludepathes; $j++ )
1113	{
1114		my $allfiles = $installer::globals::allincludepathes[$j];
1115
1116		if ( exists( $allfiles->{$$searchfilenameref} ))
1117		{
1118			$onefile = $allfiles->{'includepath'} . $installer::globals::separator . $$searchfilenameref;
1119			$foundsourcefile = 1;
1120			last;
1121		}
1122	}
1123
1124	if (!($foundsourcefile))	# testing with lowercase filename
1125	{
1126		# Attention: README01.html is copied for Windows to readme01.html, not case sensitive
1127
1128		for ( my $j = 0; $j <= $#installer::globals::allincludepathes; $j++ )
1129		{
1130			my $allfiles = $installer::globals::allincludepathes[$j];
1131
1132			my $newfilename = $$searchfilenameref;
1133			$newfilename =~ s/readme/README/;		# special handling for readme files
1134			$newfilename =~ s/license/LICENSE/;		# special handling for license files
1135
1136			if ( exists( $allfiles->{$newfilename} ))
1137			{
1138				$onefile = $allfiles->{'includepath'} . $installer::globals::separator . $newfilename;
1139				$foundsourcefile = 1;
1140				$foundnewname = 1;
1141				last;
1142			}
1143		}
1144	}
1145
1146	if (!($foundsourcefile))
1147	{
1148		$onefile = "";	# the sourcepath has to be empty
1149		if ( $write_logfile)
1150		{
1151			if ( $ENV{'DEFAULT_TO_ENGLISH_FOR_PACKING'} )
1152			{
1153				$infoline = "WARNING: Source for $$searchfilenameref not found!\n";	 # Important message in log file
1154			}
1155			else
1156			{
1157				$infoline = "ERROR: Source for $$searchfilenameref not found!\n";	 # Important message in log file
1158			}
1159
1160			push( @installer::globals::logfileinfo, $infoline);
1161		}
1162	}
1163	else
1164	{
1165		if ( $write_logfile)
1166		{
1167			if (!($foundnewname))
1168			{
1169				$infoline = "SUCCESS: Source for $$searchfilenameref: $onefile\n";
1170			}
1171			else
1172			{
1173				$infoline = "SUCCESS/WARNING: Special handling for $$searchfilenameref: $onefile\n";
1174			}
1175			push( @installer::globals::logfileinfo, $infoline);
1176		}
1177	}
1178
1179	return \$onefile;
1180}
1181
1182##############################################################
1183# Determining, whether a specified directory is language
1184# dependent
1185##############################################################
1186
1187sub determine_directory_language_dependency
1188{
1189	my($directorygid, $dirsref) = @_;
1190
1191	my $is_multilingual = 0;
1192
1193	for ( my $i = 0; $i <= $#{$dirsref}; $i++ )
1194	{
1195		my $onedir = ${$dirsref}[$i];
1196		my $gid = $onedir->{'gid'};
1197
1198		if ( $gid eq $directorygid )
1199		{
1200			$is_multilingual = $onedir->{'ismultilingual'};
1201			last;
1202		}
1203	}
1204
1205	return $is_multilingual;
1206}
1207
1208##############################################################
1209# Getting all source pathes for all files to be packed
1210# $item can be "Files" or "ScpActions"
1211##############################################################
1212
1213sub get_Source_Directory_For_Files_From_Includepathlist
1214{
1215	my ($filesarrayref, $includepatharrayref, $dirsref, $item) = @_;
1216
1217	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_Source_Directory_For_Files_From_Includepathlist : $#{$filesarrayref} : $#{$includepatharrayref} : $item"); }
1218
1219	installer::logger::include_header_into_logfile("$item:");
1220
1221	my $infoline = "";
1222
1223	for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
1224	{
1225		my $onefile = ${$filesarrayref}[$i];
1226		my $onelanguage = $onefile->{'specificlanguage'};
1227
1228		if ( ! $onefile->{'Name'} ) { installer::exiter::exit_program("ERROR: $item without name ! GID: $onefile->{'gid'} ! Language: $onelanguage", "get_Source_Directory_For_Files_From_Includepathlist"); }
1229
1230		my $onefilename = $onefile->{'Name'};
1231		if ( $item eq "ScpActions" ) { $onefilename =~ s/\//$installer::globals::separator/g; }
1232		$onefilename =~ s/^\s*\Q$installer::globals::separator\E//;		# filename begins with a slash, for instance /registry/schema/org/openoffice/VCL.xcs
1233
1234		my $styles = "";
1235		my $file_can_miss = 0;
1236		if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }
1237		if ( $styles =~ /\bFILE_CAN_MISS\b/ ) { $file_can_miss = 1; }
1238
1239		if (( $installer::globals::languagepack ) && ( ! $onefile->{'ismultilingual'} ) && ( ! ( $styles =~ /\bFORCELANGUAGEPACK\b/ ))) { $file_can_miss = 1; }
1240
1241		my $sourcepathref = "";
1242
1243		if ( $file_can_miss ) { $sourcepathref = get_sourcepath_from_filename_and_includepath(\$onefilename, $includepatharrayref, 0); }
1244		else { $sourcepathref = get_sourcepath_from_filename_and_includepath(\$onefilename, $includepatharrayref, 1); }
1245
1246		$onefile->{'sourcepath'} = $$sourcepathref;	# This $$sourcepathref is empty, if no source was found
1247
1248		# defaulting to english for multilingual files if DEFAULT_TO_ENGLISH_FOR_PACKING is set
1249
1250		if ( $ENV{'DEFAULT_TO_ENGLISH_FOR_PACKING'} )
1251		{
1252			if (( ! $onefile->{'sourcepath'} ) && ( $onefile->{'ismultilingual'} ))
1253			{
1254				my $oldname = $onefile->{'Name'};
1255				my $oldlanguage = $onefile->{'specificlanguage'};
1256				my $newlanguage = "en-US";
1257				# $onefile->{'Name'} =~ s/$oldlanguage\./$newlanguage\./;	# Example: tplwizfax_it.zip -> tplwizfax_en-US.zip
1258				$onefilename = $onefile->{'Name'};
1259				$onefilename =~ s/$oldlanguage\./$newlanguage\./;	# Example: tplwizfax_it.zip -> tplwizfax_en-US.zip
1260				$onefilename =~ s/^\s*\Q$installer::globals::separator\E//;		# filename begins with a slash, for instance /registry/schema/org/openoffice/VCL.xcs
1261				$sourcepathref = get_sourcepath_from_filename_and_includepath(\$onefilename, $includepatharrayref, 1);
1262				$onefile->{'sourcepath'} = $$sourcepathref;						# This $$sourcepathref is empty, if no source was found
1263
1264				if ($onefile->{'sourcepath'})	# defaulting to english was successful
1265				{
1266					$infoline = "WARNING: Using $onefilename instead of $oldname\n";
1267					push( @installer::globals::logfileinfo, $infoline);
1268					print "    $infoline";
1269					# if ( $onefile->{'destination'} ) { $onefile->{'destination'} =~ s/\Q$oldname\E/$onefile->{'Name'}/; }
1270
1271					# If the directory, in which the new file is installed, is not language dependent,
1272					# the filename has to be changed to avoid installation conflicts
1273					# No mechanism for resource files!
1274					# -> implementing for the content of ARCHIVE files
1275
1276					if ( $onefile->{'Styles'} =~ /\bARCHIVE\b/ )
1277					{
1278						my $directorygid = $onefile->{'Dir'};
1279						my $islanguagedependent = determine_directory_language_dependency($directorygid, $dirsref);
1280
1281						if ( ! $islanguagedependent )
1282						{
1283							$onefile->{'Styles'} =~ s/\bARCHIVE\b/ARCHIVE, RENAME_TO_LANGUAGE/;	# Setting new flag RENAME_TO_LANGUAGE
1284							$infoline = "Setting flag RENAME_TO_LANGUAGE: File $onefile->{'Name'} in directory: $directorygid\n";
1285							push( @installer::globals::logfileinfo, $infoline);
1286						}
1287					}
1288				}
1289				else
1290				{
1291					$infoline = "WARNING: Using $onefile->{'Name'} instead of $oldname was not successful\n";
1292					push( @installer::globals::logfileinfo, $infoline);
1293					$onefile->{'Name'} = $oldname;	# Switching back to old file name
1294				}
1295			}
1296		}
1297	}
1298
1299	$infoline = "\n";	# empty line after listing of all files
1300	push( @installer::globals::logfileinfo, $infoline);
1301}
1302
1303#################################################################################
1304# Removing files, that shall not be included into languagepacks
1305# (because of rpm conflicts)
1306#################################################################################
1307
1308sub remove_Files_For_Languagepacks
1309{
1310	my ($itemsarrayref) = @_;
1311
1312	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_Files_For_Languagepacks : $#{$filesarrayref}"); }
1313
1314	my $infoline;
1315
1316	my @newitemsarray = ();
1317
1318	for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
1319	{
1320		my $oneitem = ${$itemsarrayref}[$i];
1321		my $gid = $oneitem->{'gid'};
1322
1323		# scp Todo: Remove asap after removal of old setup
1324
1325		if (( $gid eq "gid_File_Extra_Fontunxpsprint" ) ||
1326			( $gid eq "gid_File_Extra_Migration_Lang" ))
1327		{
1328			$infoline = "ATTENTION: Removing item $oneitem->{'gid'} from the installation set.\n";
1329			push( @installer::globals::logfileinfo, $infoline);
1330
1331			next;
1332		}
1333
1334		push(@newitemsarray, $oneitem);
1335	}
1336
1337	return \@newitemsarray;
1338}
1339
1340#################################################################################
1341# Files, whose source directory is not found, are removed now (this is an ERROR)
1342#################################################################################
1343
1344sub remove_Files_Without_Sourcedirectory
1345{
1346	my ($filesarrayref) = @_;
1347
1348	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_Files_Without_Sourcedirectory : $#{$filesarrayref}"); }
1349
1350	my $infoline;
1351
1352	my $error_occured = 0;
1353	my @missingfiles = ();
1354	push(@missingfiles, "ERROR: The following files could not be found: \n");
1355
1356	my @newfilesarray = ();
1357
1358	for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
1359	{
1360		my $onefile = ${$filesarrayref}[$i];
1361		my $sourcepath = $onefile->{'sourcepath'};
1362
1363		if ($sourcepath eq "")
1364		{
1365			my $styles = $onefile->{'Styles'};
1366			my $filename = $onefile->{'Name'};
1367
1368			if ( ! $installer::globals::languagepack )
1369			{
1370				$infoline = "ERROR: Removing file $filename from file list.\n";
1371				push( @installer::globals::logfileinfo, $infoline);
1372
1373				push(@missingfiles, "ERROR: File not found: $filename\n");
1374				$error_occured = 1;
1375
1376				next;	# removing this file from list, if sourcepath is empty
1377			}
1378			else # special case for language packs
1379			{
1380				if (( $onefile->{'ismultilingual'} ) || ( $styles =~ /\bFORCELANGUAGEPACK\b/ ))
1381				{
1382					$infoline = "ERROR: Removing file $filename from file list.\n";
1383					push( @installer::globals::logfileinfo, $infoline);
1384
1385					push(@missingfiles, "ERROR: File not found: $filename\n");
1386					$error_occured = 1;
1387
1388					next;	# removing this file from list, if sourcepath is empty
1389				}
1390				else
1391				{
1392					$infoline = "INFO: Removing file $filename from file list. It is not language dependent.\n";
1393					push( @installer::globals::logfileinfo, $infoline);
1394					$infoline = "INFO: It is not language dependent and can be ignored in language packs.\n";
1395					push( @installer::globals::logfileinfo, $infoline);
1396
1397					next;	# removing this file from list, if sourcepath is empty
1398				}
1399			}
1400		}
1401
1402		push(@newfilesarray, $onefile);
1403	}
1404
1405	$infoline = "\n";
1406	push( @installer::globals::logfileinfo, $infoline);
1407
1408	if ( $error_occured )
1409	{
1410		for ( my $i = 0; $i <= $#missingfiles; $i++ ) { print "$missingfiles[$i]"; }
1411		installer::exiter::exit_program("ERROR: Missing files", "remove_Files_Without_Sourcedirectory");
1412	}
1413
1414	return \@newfilesarray;
1415}
1416
1417############################################################################
1418# License and Readme files in the default language have to be installed
1419# in the directory with flag OFFICEDIRECTORY. If this is not defined
1420# they have to be installed in the installation root.
1421############################################################################
1422
1423sub get_office_directory_gid_and_hostname
1424{
1425	my ($dirsarrayref) = @_;
1426
1427	my $foundofficedir = 0;
1428	my $gid = "";
1429	my $hostname = "";
1430
1431	for ( my $i = 0; $i <= $#{$dirsarrayref}; $i++ )
1432	{
1433		my $onedir = ${$dirsarrayref}[$i];
1434		if ( $onedir->{'Styles'} )
1435		{
1436			my $styles = $onedir->{'Styles'};
1437
1438			if ( $styles =~ /\bOFFICEDIRECTORY\b/ )
1439			{
1440				$foundofficedir = 1;
1441				$gid = $onedir->{'gid'};
1442				$hostname = $onedir->{'HostName'};
1443				last;
1444			}
1445		}
1446	}
1447
1448	return ($foundofficedir, $gid, $hostname);
1449}
1450
1451############################################################################
1452# License and Readme files in the default language have to be installed
1453# in the installation root (next to the program dir). This is in scp
1454# project done by a post install basic script
1455############################################################################
1456
1457sub add_License_Files_into_Installdir
1458{
1459	my ($filesarrayref, $dirsarrayref, $languagesarrayref) = @_;
1460
1461	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::add_License_Files_into_Installdir : $#{$filesarrayref} : $#{$languagesarrayref}"); }
1462
1463	my $infoline;
1464
1465	my @newfilesarray = ();
1466
1467	my $defaultlanguage = installer::languages::get_default_language($languagesarrayref);
1468
1469	my ($foundofficedir, $officedirectorygid, $officedirectoryhostname) = get_office_directory_gid_and_hostname($dirsarrayref);
1470
1471	# copy all files from directory share/readme, that contain the default language in their name
1472	# without default language into the installation root. This makes the settings of the correct
1473	# file names superfluous. On the other hand this requires a dependency to the directory
1474	# share/readme
1475
1476	for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
1477	{
1478		my $onefile = ${$filesarrayref}[$i];
1479		my $destination = $onefile->{'destination'};
1480		my $styles = "";
1481		if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }
1482
1483		if ( ( $destination =~ /share\Q$installer::globals::separator\Ereadme\Q$installer::globals::separator\E(\w+?)_?$defaultlanguage\.?(\w*)\s*/ )
1484			|| (( $styles =~ /\bROOTLICENSEFILE\b/ ) && ( $destination =~ /\Q$installer::globals::separator\E?(\w+?)_?$defaultlanguage\.?(\w*?)\s*$/ )) )
1485		{
1486			my $filename = $1;
1487			my $extension = $2;
1488
1489			my $newfilename;
1490
1491			if ( $extension eq "" ) { $newfilename = $filename; }
1492			else { $newfilename = $filename . "\." . $extension; }
1493
1494			my %newfile = ();
1495			my $newfile = \%newfile;
1496
1497			installer::converter::copy_item_object($onefile, $newfile);
1498
1499			$newfile->{'gid'} = $onefile->{'gid'} . "_Copy";
1500			$newfile->{'Name'} = $newfilename;
1501			$newfile->{'ismultilingual'} = "0";
1502			$newfile->{'specificlanguage'} = "";
1503			$newfile->{'haslanguagemodule'} = "0";
1504
1505			if ( defined $newfile->{'InstallName'} )
1506			{
1507				if ( $newfile->{'InstallName'} =~ /^\s*(.*?)_$defaultlanguage\.?(\w*?)\s*$/ )
1508				{
1509					my $localfilename = $1;
1510					my $localextension = $2;
1511
1512					if ( $localextension eq "" ) { $newfile->{'InstallName'} = $localfilename; }
1513					else { $newfile->{'InstallName'} = $localfilename . "\." . $localextension; }
1514				}
1515			}
1516
1517			$newfile->{'removelangfromfile'} = "1"; # Important for files with an InstallName, because language also has to be removed there.
1518
1519			if ( $foundofficedir )
1520			{
1521				$newfile->{'Dir'} = $officedirectorygid;
1522				$newfile->{'destination'} = $officedirectoryhostname . $installer::globals::separator . $newfilename;
1523			}
1524			else
1525			{
1526				$newfile->{'Dir'} = "PREDEFINED_PROGDIR";
1527				$newfile->{'destination'} = $newfilename;
1528			}
1529
1530			# Also setting "modules=gid_Module_Root_Brand" (module with style: ROOT_BRAND_PACKAGE)
1531			if ( $installer::globals::rootbrandpackageset )
1532			{
1533				$newfile->{'modules'} = $installer::globals::rootbrandpackage;
1534			}
1535
1536			push(@newfilesarray, $newfile);
1537
1538			$infoline = "New files: Adding file $newfilename for the installation root to the file list. Language: $defaultlanguage\n";
1539			push( @installer::globals::logfileinfo, $infoline);
1540
1541			if ( defined $newfile->{'InstallName'} )
1542			{
1543				$infoline = "New files: Using installation name: $newfile->{'InstallName'}\n";
1544				push( @installer::globals::logfileinfo, $infoline);
1545			}
1546
1547			# Collecting license and readme file for the installation set
1548
1549			push(@installer::globals::installsetfiles, $newfile);
1550			$infoline = "New files: Adding file $newfilename to the file collector for the installation set. Language: $defaultlanguage\n";
1551			push( @installer::globals::logfileinfo, $infoline);
1552		}
1553
1554		push(@newfilesarray, $onefile);
1555	}
1556
1557	return \@newfilesarray;
1558}
1559
1560############################################################################
1561# Removing files with flag ONLY_ASIA_LANGUAGE, only if no asian
1562# language is part of the product.
1563# This special files are connected to the root module and are not
1564# included into a language pack (would lead to conflicts!).
1565# But this files shall only be included into the product, if the
1566# product contains at least one asian language.
1567############################################################################
1568
1569sub remove_onlyasialanguage_files_from_productlists
1570{
1571	my ($filesarrayref) = @_;
1572
1573	my $infoline;
1574
1575	my @newfilesarray = ();
1576	my $returnfilesarrayref;
1577
1578	my $containsasianlanguage = installer::languages::detect_asian_language($installer::globals::alllanguagesinproductarrayref);
1579
1580	my $alllangstring = installer::converter::convert_array_to_comma_separated_string($installer::globals::alllanguagesinproductarrayref);
1581	$infoline = "\nLanguages in complete product: $alllangstring\n";
1582	push( @installer::globals::logfileinfo, $infoline);
1583
1584	if ( ! $containsasianlanguage )
1585	{
1586		$infoline = "Product does not contain asian language -> removing files\n";
1587		push( @installer::globals::logfileinfo, $infoline);
1588
1589		for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
1590		{
1591			my $onefile = ${$filesarrayref}[$i];
1592			my $styles = "";
1593			if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }
1594			if ( $styles =~ /\bONLY_ASIA_LANGUAGE\b/ )
1595			{
1596				$infoline = "Flag ONLY_ASIA_LANGUAGE: Removing file $onefile->{'Name'} from files collector!\n";
1597				push( @installer::globals::logfileinfo, $infoline);
1598				next;
1599			}
1600
1601			push(@newfilesarray, $onefile);
1602		}
1603
1604		$returnfilesarrayref = \@newfilesarray;
1605	}
1606	else
1607	{
1608		$returnfilesarrayref = $filesarrayref;
1609
1610		$infoline = "Product contains asian language -> Nothing to do\n";
1611		push( @installer::globals::logfileinfo, $infoline);
1612
1613	}
1614
1615	return $returnfilesarrayref;
1616}
1617
1618############################################################################
1619# Removing files with flag ONLY_WESTERN_LANGUAGE, only if no western
1620# language is part of the product.
1621# This special files are connected to the root module and are not
1622# included into a language pack (would lead to conflicts!).
1623# But this files shall only be included into the product, if the
1624# product contains at least one western language.
1625############################################################################
1626
1627sub remove_onlywesternlanguage_files_from_productlists
1628{
1629	my ($filesarrayref) = @_;
1630
1631	my $infoline;
1632
1633	my @newfilesarray = ();
1634	my $returnfilesarrayref;
1635
1636	my $containswesternlanguage = installer::languages::detect_western_language($installer::globals::alllanguagesinproductarrayref);
1637
1638	my $alllangstring = installer::converter::convert_array_to_comma_separated_string($installer::globals::alllanguagesinproductarrayref);
1639	$infoline = "\nLanguages in complete product: $alllangstring\n";
1640	push( @installer::globals::logfileinfo, $infoline);
1641
1642	if ( ! $containswesternlanguage )
1643	{
1644		$infoline = "Product does not contain western language -> removing files\n";
1645		push( @installer::globals::logfileinfo, $infoline);
1646
1647		for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
1648		{
1649			my $onefile = ${$filesarrayref}[$i];
1650			my $styles = "";
1651			if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }
1652			if ( $styles =~ /\bONLY_WESTERN_LANGUAGE\b/ )
1653			{
1654				$infoline = "Flag ONLY_WESTERN_LANGUAGE: Removing file $onefile->{'Name'} from files collector!\n";
1655				push( @installer::globals::logfileinfo, $infoline);
1656				next;
1657			}
1658
1659			push(@newfilesarray, $onefile);
1660		}
1661
1662		$returnfilesarrayref = \@newfilesarray;
1663	}
1664	else
1665	{
1666		$returnfilesarrayref = $filesarrayref;
1667
1668		$infoline = "Product contains western language -> Nothing to do\n";
1669		push( @installer::globals::logfileinfo, $infoline);
1670
1671	}
1672
1673	return $returnfilesarrayref;
1674}
1675
1676############################################################################
1677# Some files are included for more than one language and have the same
1678# name and the same destination directory for all languages. This would
1679# lead to conflicts, if the filenames are not changed.
1680# In scp project this files must have the flag MAKE_LANG_SPECIFIC
1681# For this files, the language is included into the filename.
1682############################################################################
1683
1684sub make_filename_language_specific
1685{
1686	my ($filesarrayref) = @_;
1687
1688	my $infoline = "";
1689
1690	for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
1691	{
1692		my $onefile = ${$filesarrayref}[$i];
1693
1694		if ( $onefile->{'ismultilingual'} )
1695		{
1696			my $styles = "";
1697			if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }
1698			if ( $styles =~ /\bMAKE_LANG_SPECIFIC\b/ )
1699			{
1700				my $language = $onefile->{'specificlanguage'};
1701				my $olddestination = $onefile->{'destination'};
1702				my $oldname = $onefile->{'Name'};
1703
1704				# Including the language into the file name.
1705				# But be sure, to include the language before the file extension.
1706
1707				my $fileextension = "";
1708
1709				if ( $onefile->{'Name'} =~ /(\.\w+?)\s*$/ ) { $fileextension = $1; }
1710				if ( $fileextension ne "" )
1711				{
1712					$onefile->{'Name'} =~ s/\Q$fileextension\E\s*$/_$language$fileextension/;
1713					$onefile->{'destination'} =~ s/\Q$fileextension\E\s*$/_$language$fileextension/;
1714				}
1715
1716				$infoline = "Flag MAKE_LANG_SPECIFIC:\n";
1717				push( @installer::globals::logfileinfo, $infoline);
1718				$infoline = "Changing name from $oldname to $onefile->{'Name'} !\n";
1719				push( @installer::globals::logfileinfo, $infoline);
1720				$infoline = "Changing destination from $olddestination to $onefile->{'destination'} !\n";
1721				push( @installer::globals::logfileinfo, $infoline);
1722			}
1723		}
1724	}
1725}
1726
1727############################################################################
1728# Removing all scpactions, that have no name.
1729# See: FlatLoaderZip
1730############################################################################
1731
1732sub remove_scpactions_without_name
1733{
1734	my ($itemsarrayref) = @_;
1735
1736	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_scpactions_without_name : $#{$itemsarrayref}"); }
1737
1738	my $infoline;
1739
1740	my @newitemsarray = ();
1741
1742	for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
1743	{
1744		my $oneitem = ${$itemsarrayref}[$i];
1745		my $name = "";
1746
1747		if ( $oneitem->{'Name'} ) { $name = $oneitem->{'Name'}; }
1748
1749		if  ( $name eq "" )
1750		{
1751			$infoline = "ATTENTION: Removing scpaction $oneitem->{'gid'} from the installation set.\n";
1752			push( @installer::globals::logfileinfo, $infoline);
1753			next;
1754		}
1755
1756		push(@newitemsarray, $oneitem);
1757	}
1758
1759	return \@newitemsarray;
1760}
1761
1762############################################################################
1763# Because of the item "File" the source name must be "Name". Therefore
1764# "Copy" is changed to "Name" and "Name" is changed to "DestinationName".
1765############################################################################
1766
1767sub change_keys_of_scpactions
1768{
1769	my ($itemsarrayref) = @_;
1770
1771	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::change_keys_of_scpactions : $#{$itemsarrayref}"); }
1772
1773	for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
1774	{
1775		my $oneitem = ${$itemsarrayref}[$i];
1776
1777		my $key;
1778
1779		# First Name to DestinationName, then deleting Name
1780		foreach $key (keys %{$oneitem})
1781		{
1782			if ( $key =~ /\bName\b/ )
1783			{
1784				my $value = $oneitem->{$key};
1785				my $oldkey = $key;
1786				$key =~ s/Name/DestinationName/;
1787				$oneitem->{$key} = $value;
1788				delete($oneitem->{$oldkey});
1789			}
1790		}
1791
1792		# Second Copy to Name, then deleting Copy
1793		foreach $key (keys %{$oneitem})
1794		{
1795			if ( $key =~ /\bCopy\b/ )
1796			{
1797				my $value = $oneitem->{$key};
1798				my $oldkey = $key;
1799				$key =~ s/Copy/Name/;
1800				$oneitem->{$key} = $value;
1801				delete($oneitem->{$oldkey});
1802			}
1803		}
1804	}
1805}
1806
1807############################################################################
1808# Removing all xpd only items from installation set (scpactions with
1809# the style XPD_ONLY), except an xpd installation set is created
1810############################################################################
1811
1812sub remove_Xpdonly_Items
1813{
1814	my ($itemsarrayref) = @_;
1815
1816	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_Xpdonly_Items : $#{$itemsarrayref}"); }
1817
1818	my $infoline;
1819
1820	my @newitemsarray = ();
1821
1822	for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
1823	{
1824		my $oneitem = ${$itemsarrayref}[$i];
1825		my $styles = "";
1826		if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
1827
1828		if ( $styles =~ /\bXPD_ONLY\b/ )
1829		{
1830			$infoline = "Removing \"xpd only\" item $oneitem->{'gid'} from the installation set.\n";
1831			push( @installer::globals::globallogfileinfo, $infoline);
1832
1833			next;
1834		}
1835
1836		push(@newitemsarray, $oneitem);
1837	}
1838
1839	$infoline = "\n";
1840	push( @installer::globals::globallogfileinfo, $infoline);
1841
1842	return \@newitemsarray;
1843}
1844
1845############################################################################
1846# Removing all language pack files from installation set (files with
1847# the style LANGUAGEPACK), except this is a language pack.
1848############################################################################
1849
1850sub remove_Languagepacklibraries_from_Installset
1851{
1852	my ($itemsarrayref) = @_;
1853
1854	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_Languagepacklibraries_from_Installset : $#{$itemsarrayref}"); }
1855
1856	my $infoline;
1857
1858	my @newitemsarray = ();
1859
1860	for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
1861	{
1862		my $oneitem = ${$itemsarrayref}[$i];
1863		my $styles = "";
1864		if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
1865
1866		if ( $styles =~ /\bLANGUAGEPACK\b/ )
1867		{
1868			$infoline = "Removing language pack file $oneitem->{'gid'} from the installation set.\n";
1869			push( @installer::globals::globallogfileinfo, $infoline);
1870
1871			next;
1872		}
1873
1874		push(@newitemsarray, $oneitem);
1875	}
1876
1877	$infoline = "\n";
1878	push( @installer::globals::globallogfileinfo, $infoline);
1879
1880	return \@newitemsarray;
1881}
1882
1883############################################################################
1884# Removing all files with flag PATCH_ONLY from installation set.
1885# This function is not called during patch creation.
1886############################################################################
1887
1888sub remove_patchonlyfiles_from_Installset
1889{
1890	my ($itemsarrayref) = @_;
1891
1892	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_patchonlyfiles_from_Installset : $#{$itemsarrayref}"); }
1893
1894	my $infoline;
1895
1896	my @newitemsarray = ();
1897
1898	for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
1899	{
1900		my $oneitem = ${$itemsarrayref}[$i];
1901		my $styles = "";
1902		if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
1903
1904		if ( $styles =~ /\bPATCH_ONLY\b/ )
1905		{
1906			$infoline = "Removing file with flag PATCH_ONLY $oneitem->{'gid'} from the installation set.\n";
1907			push( @installer::globals::globallogfileinfo, $infoline);
1908
1909			next;
1910		}
1911
1912		push(@newitemsarray, $oneitem);
1913	}
1914
1915	$infoline = "\n";
1916	push( @installer::globals::globallogfileinfo, $infoline);
1917
1918	return \@newitemsarray;
1919}
1920
1921############################################################################
1922# Removing all files with flag TAB_ONLY from installation set.
1923# This function is not called during tab creation.
1924############################################################################
1925
1926sub remove_tabonlyfiles_from_Installset
1927{
1928	my ($itemsarrayref) = @_;
1929
1930	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_tabonlyfiles_from_Installset : $#{$itemsarrayref}"); }
1931
1932	my $infoline;
1933
1934	my @newitemsarray = ();
1935
1936	for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
1937	{
1938		my $oneitem = ${$itemsarrayref}[$i];
1939		my $styles = "";
1940		if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
1941
1942		if ( $styles =~ /\bTAB_ONLY\b/ )
1943		{
1944			$infoline = "Removing tab only file $oneitem->{'gid'} from the installation set.\n";
1945			push( @installer::globals::globallogfileinfo, $infoline);
1946
1947			next;
1948		}
1949
1950		push(@newitemsarray, $oneitem);
1951	}
1952
1953	$infoline = "\n";
1954	push( @installer::globals::globallogfileinfo, $infoline);
1955
1956	return \@newitemsarray;
1957}
1958
1959###############################################################################
1960# Removing all files with flag ONLY_INSTALLED_PRODUCT from installation set.
1961# This function is not called for PKGFORMAT installed and archive.
1962###############################################################################
1963
1964sub remove_installedproductonlyfiles_from_Installset
1965{
1966	my ($itemsarrayref) = @_;
1967
1968	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_installedproductonlyfiles_from_Installset : $#{$itemsarrayref}"); }
1969
1970	my $infoline;
1971
1972	my @newitemsarray = ();
1973
1974	for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
1975	{
1976		my $oneitem = ${$itemsarrayref}[$i];
1977		my $styles = "";
1978		if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
1979
1980		if ( $styles =~ /\bONLY_INSTALLED_PRODUCT\b/ )
1981		{
1982			$infoline = "Removing file $oneitem->{'gid'} from the installation set. This file is only required for PKGFORMAT archive or installed).\n";
1983			push( @installer::globals::globallogfileinfo, $infoline);
1984			next;
1985		}
1986
1987		push(@newitemsarray, $oneitem);
1988	}
1989
1990	$infoline = "\n";
1991	push( @installer::globals::globallogfileinfo, $infoline);
1992
1993	return \@newitemsarray;
1994}
1995
1996############################################################################
1997# Some files cotain a $ in their name. epm conflicts with such files.
1998# Solution: Renaming this files, converting "$" to "$$"
1999############################################################################
2000
2001sub quoting_illegal_filenames
2002{
2003	my ($filesarrayref) = @_;
2004
2005	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::rename_illegal_filenames : $#{$filesarrayref}"); }
2006
2007	# This function has to be removed as soon as possible!
2008
2009	installer::logger::include_header_into_logfile("Renaming illegal filenames:");
2010
2011	for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
2012	{
2013		my $onefile = ${$filesarrayref}[$i];
2014		my $filename = $onefile->{'Name'};
2015
2016		if ( $filename =~ /\$/ )
2017		{
2018			my $sourcepath = $onefile->{'sourcepath'};
2019			my $destpath = $onefile->{'destination'};
2020
2021			# sourcepath and destination have to be quoted for epm list file
2022
2023			# $filename =~ s/\$/\$\$/g;
2024			$destpath =~ s/\$/\$\$/g;
2025			$sourcepath =~ s/\$/\$\$/g;
2026
2027			# my $infoline = "ATTENTION: Files: Renaming $onefile->{'Name'} to $filename\n";
2028			# push( @installer::globals::logfileinfo, $infoline);
2029			my $infoline = "ATTENTION: Files: Quoting sourcepath $onefile->{'sourcepath'} to $sourcepath\n";
2030			push( @installer::globals::logfileinfo, $infoline);
2031			$infoline = "ATTENTION: Files: Quoting destination path $onefile->{'destination'} to $destpath\n";
2032			push( @installer::globals::logfileinfo, $infoline);
2033
2034			# $onefile->{'Name'} = $filename;
2035			$onefile->{'sourcepath'} = $sourcepath;
2036			$onefile->{'destination'} = $destpath;
2037		}
2038	}
2039}
2040
2041############################################################################
2042# Removing multiple occurences of same module.
2043############################################################################
2044
2045sub optimize_list
2046{
2047	my ( $longlist ) = @_;
2048
2049	my $shortlist = "";
2050	my $hashref = installer::converter::convert_stringlist_into_hash(\$longlist, ",");
2051	foreach my $key (sort keys %{$hashref} ) { $shortlist = "$shortlist,$key"; }
2052	$shortlist =~ s/^\s*\,//;
2053
2054	return $shortlist;
2055}
2056
2057#######################################################################
2058# Collecting all directories needed for the epm list
2059# 1. Looking for all destination paths in the files array
2060# 2. Looking for directories with CREATE flag in the directory array
2061#######################################################################
2062
2063##################################
2064# Collecting directories: Part 1
2065##################################
2066
2067sub collect_directories_from_filesarray
2068{
2069	my ($filesarrayref) = @_;
2070
2071	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::collect_directories_from_filesarray : $#{$filesarrayref}"); }
2072
2073	my @alldirectories = ();
2074	my %alldirectoryhash = ();
2075
2076	my $predefinedprogdir_added = 0;
2077	my $alreadyincluded = 0;
2078
2079	# Preparing this already as hash, although the only needed value at the moment is the HostName
2080	# But also adding: "specificlanguage" and "Dir" (for instance gid_Dir_Program)
2081
2082	for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
2083	{
2084		my $onefile = ${$filesarrayref}[$i];
2085		my $destinationpath = $onefile->{'destination'};
2086		installer::pathanalyzer::get_path_from_fullqualifiedname(\$destinationpath);
2087		$destinationpath =~ s/\Q$installer::globals::separator\E\s*$//;		# removing ending slashes or backslashes
2088
2089		$alreadyincluded = 0;
2090		if  ( exists($alldirectoryhash{$destinationpath}) ) { $alreadyincluded = 1; }
2091
2092		if (!($alreadyincluded))
2093		{
2094			my %directoryhash = ();
2095			$directoryhash{'HostName'} = $destinationpath;
2096			$directoryhash{'specificlanguage'} = $onefile->{'specificlanguage'};
2097			$directoryhash{'Dir'} = $onefile->{'Dir'};
2098			$directoryhash{'modules'} = $onefile->{'modules'}; # NEW, saving modules
2099			# NEVER!!!	if ( ! $installer::globals::iswindowsbuild ) { $directoryhash{'Styles'} = "(CREATE)"; }	# this directories must be created
2100
2101			if ( $onefile->{'Dir'} eq "PREDEFINED_PROGDIR" ) { $predefinedprogdir_added = 1; }
2102
2103			$alldirectoryhash{$destinationpath} = \%directoryhash;
2104
2105			# Problem: The $destinationpath can be share/registry/schema/org/openoffice
2106			# but not all directories contain files and will be added to this list.
2107			# Therefore the path has to be analyzed.
2108
2109			while ( $destinationpath =~ /(^.*\S)\Q$installer::globals::separator\E(\S.*?)\s*$/ )	# as long as the path contains slashes
2110			{
2111				$destinationpath = $1;
2112
2113				$alreadyincluded = 0;
2114				if  ( exists($alldirectoryhash{$destinationpath}) ) { $alreadyincluded = 1; }
2115
2116				if (!($alreadyincluded))
2117				{
2118					my %directoryhash = ();
2119
2120					$directoryhash{'HostName'} = $destinationpath;
2121					$directoryhash{'specificlanguage'} = $onefile->{'specificlanguage'};
2122					$directoryhash{'Dir'} = $onefile->{'Dir'};
2123					$directoryhash{'modules'} = $onefile->{'modules'}; # NEW, saving modules
2124					# NEVER!!! if ( ! $installer::globals::iswindowsbuild ) { $directoryhash{'Styles'} = "(CREATE)"; }	# this directories must be created
2125
2126					$alldirectoryhash{$destinationpath} = \%directoryhash;
2127				}
2128				else
2129				{
2130					# Adding the modules to the module list!
2131					$alldirectoryhash{$destinationpath}->{'modules'} = $alldirectoryhash{$destinationpath}->{'modules'} . "," . $onefile->{'modules'};
2132				}
2133			}
2134		}
2135		else
2136		{
2137			# Adding the modules to the module list!
2138			$alldirectoryhash{$destinationpath}->{'modules'} = $alldirectoryhash{$destinationpath}->{'modules'} . "," . $onefile->{'modules'};
2139
2140			# Also adding the module to all parents
2141			while ( $destinationpath =~ /(^.*\S)\Q$installer::globals::separator\E(\S.*?)\s*$/ )	# as long as the path contains slashes
2142			{
2143				$destinationpath = $1;
2144				$alldirectoryhash{$destinationpath}->{'modules'} = $alldirectoryhash{$destinationpath}->{'modules'} . "," . $onefile->{'modules'};
2145			}
2146		}
2147	}
2148
2149	# if there is no file in the root directory PREDEFINED_PROGDIR, it has to be included into the directory array now
2150	# HostName=	specificlanguage=	Dir=PREDEFINED_PROGDIR
2151
2152	if (! $predefinedprogdir_added )
2153	{
2154		my %directoryhash = ();
2155		$directoryhash{'HostName'} = "";
2156		$directoryhash{'specificlanguage'} = "";
2157		$directoryhash{'modules'} = "";	# ToDo?
2158		$directoryhash{'Dir'} = "PREDEFINED_PROGDIR";
2159
2160		push(@alldirectories, \%directoryhash);
2161	}
2162
2163	# Creating directory array
2164	foreach my $destdir ( sort keys %alldirectoryhash )
2165	{
2166		$alldirectoryhash{$destdir}->{'modules'} = optimize_list($alldirectoryhash{$destdir}->{'modules'});
2167		push(@alldirectories, $alldirectoryhash{$destdir});
2168	}
2169
2170	return (\@alldirectories, \%alldirectoryhash);
2171}
2172
2173##################################
2174# Collecting directories: Part 2
2175##################################
2176
2177sub collect_directories_with_create_flag_from_directoryarray
2178{
2179	my ($directoryarrayref, $alldirectoryhash) = @_;
2180
2181	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::collect_directories_with_create_flag_from_directoryarray : $#{$directoryarrayref}"); }
2182
2183	my $alreadyincluded = 0;
2184	my @alldirectories = ();
2185
2186	for ( my $i = 0; $i <= $#{$directoryarrayref}; $i++ )
2187	{
2188		my $onedir = ${$directoryarrayref}[$i];
2189		my $styles = "";
2190		$newdirincluded = 0;
2191
2192		if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; }
2193
2194		if ( $styles =~ /\bCREATE\b/ )
2195		{
2196			my $directoryname = "";
2197
2198			if ( $onedir->{'HostName'} ) { $directoryname = $onedir->{'HostName'}; }
2199			else { installer::exiter::exit_program("ERROR: No directory name (HostName) set for specified language in gid $onedir->{'gid'}", "collect_directories_with_create_flag_from_directoryarray"); }
2200
2201			$alreadyincluded = 0;
2202			if ( exists($alldirectoryhash->{$directoryname}) ) { $alreadyincluded = 1; }
2203
2204			if (!($alreadyincluded))
2205			{
2206				my %directoryhash = ();
2207				$directoryhash{'HostName'} = $directoryname;
2208				$directoryhash{'specificlanguage'} = $onedir->{'specificlanguage'};
2209				# $directoryhash{'gid'} = $onedir->{'gid'};
2210				$directoryhash{'Dir'} = $onedir->{'gid'};
2211				$directoryhash{'Styles'} = $onedir->{'Styles'};
2212
2213				# saving also the modules
2214				if ( ! $onedir->{'modules'} ) { installer::exiter::exit_program("ERROR: No assigned modules found for directory $onedir->{'gid'}", "collect_directories_with_create_flag_from_directoryarray"); }
2215				$directoryhash{'modules'} = $onedir->{'modules'};
2216
2217				$alldirectoryhash->{$directoryname} = \%directoryhash;
2218				$newdirincluded = 1;
2219
2220				# Problem: The $destinationpath can be share/registry/schema/org/openoffice
2221				# but not all directories contain files and will be added to this list.
2222				# Therefore the path has to be analyzed.
2223
2224				while ( $directoryname =~ /(^.*\S)\Q$installer::globals::separator\E(\S.*?)\s*$/ )	# as long as the path contains slashes
2225				{
2226					$directoryname = $1;
2227
2228					$alreadyincluded = 0;
2229					if ( exists($alldirectoryhash->{$directoryname}) ) { $alreadyincluded = 1; }
2230
2231					if (!($alreadyincluded))
2232					{
2233						my %directoryhash = ();
2234
2235						$directoryhash{'HostName'} = $directoryname;
2236						$directoryhash{'specificlanguage'} = $onedir->{'specificlanguage'};
2237						$directoryhash{'Dir'} = $onedir->{'gid'};
2238						if ( ! $installer::globals::iswindowsbuild ) { $directoryhash{'Styles'} = "(CREATE)"; } # Exeception for Windows?
2239
2240						# saving also the modules
2241						$directoryhash{'modules'} = $onedir->{'modules'};
2242
2243						$alldirectoryhash->{$directoryname} = \%directoryhash;
2244						$newdirincluded = 1;
2245					}
2246					else
2247					{
2248						# Adding the modules to the module list!
2249						$alldirectoryhash->{$directoryname}->{'modules'} = $alldirectoryhash->{$directoryname}->{'modules'} . "," . $onedir->{'modules'};
2250					}
2251				}
2252			}
2253			else
2254			{
2255				# Adding the modules to the module list!
2256				$alldirectoryhash->{$directoryname}->{'modules'} = $alldirectoryhash->{$directoryname}->{'modules'} . "," . $onedir->{'modules'};
2257
2258				while ( $directoryname =~ /(^.*\S)\Q$installer::globals::separator\E(\S.*?)\s*$/ )	# as long as the path contains slashes
2259				{
2260					$directoryname = $1;
2261					# Adding the modules to the module list!
2262					$alldirectoryhash->{$directoryname}->{'modules'} = $alldirectoryhash->{$directoryname}->{'modules'} . "," . $onedir->{'modules'};
2263				}
2264			}
2265		}
2266
2267		# Saving the styles for already added directories in function collect_directories_from_filesarray
2268
2269		if (( ! $newdirincluded ) && ( $styles ne "" ))
2270		{
2271			$styles =~ s/\bWORKSTATION\b//;
2272			$styles =~ s/\bCREATE\b//;
2273
2274			if (( ! ( $styles =~ /^\s*\(\s*\)\s*$/ )) && ( ! ( $styles =~ /^\s*\(\s*\,\s*\)\s*$/ )) && ( ! ( $styles =~ /^\s*$/ ))) # checking, if there are styles left
2275			{
2276				my $directoryname = "";
2277				if ( $onedir->{'HostName'} ) { $directoryname = $onedir->{'HostName'}; }
2278				else { installer::exiter::exit_program("ERROR: No directory name (HostName) set for specified language in gid $onedir->{'gid'}", "collect_directories_with_create_flag_from_directoryarray"); }
2279
2280				if ( exists($alldirectoryhash->{$directoryname}) )
2281				{
2282					$alldirectoryhash->{$directoryname}->{'Styles'} = $styles;
2283				}
2284			}
2285		}
2286	}
2287
2288	# Creating directory array
2289	foreach my $destdir ( sort keys %{$alldirectoryhash} )
2290	{
2291		$alldirectoryhash->{$destdir}->{'modules'} = optimize_list($alldirectoryhash->{$destdir}->{'modules'});
2292		push(@alldirectories, $alldirectoryhash->{$destdir});
2293	}
2294
2295	return (\@alldirectories, \%alldirectoryhash);
2296}
2297
2298#################################################
2299# Determining the destination file of a link
2300#################################################
2301
2302sub get_destination_file_path_for_links
2303{
2304	my ($linksarrayref, $filesarrayref) = @_;
2305
2306	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_destination_file_path_for_links : $#{$linksarrayref} : $#{$filesarrayref}"); }
2307
2308	my $infoline;
2309
2310	for ( my $i = 0; $i <= $#{$linksarrayref}; $i++ )
2311	{
2312		my $fileid = "";
2313		my $onelink = ${$linksarrayref}[$i];
2314		if ( $onelink->{'FileID'} ) { $fileid = $onelink->{'FileID'}; }
2315
2316		if (!( $fileid eq "" ))
2317		{
2318			my $foundfile = 0;
2319
2320			for ( my $j = 0; $j <= $#{$filesarrayref}; $j++ )
2321			{
2322				my $onefile = ${$filesarrayref}[$j];
2323				my $filegid = $onefile->{'gid'};
2324
2325				if ( $filegid eq $fileid )
2326				{
2327					$foundfile = 1;
2328					$onelink->{'destinationfile'} = $onefile->{'destination'};
2329					last;
2330				}
2331			}
2332
2333			if (!($foundfile))
2334			{
2335				$infoline = "Warning: FileID $fileid for Link $onelink->{'gid'} not found!\n";
2336				push( @installer::globals::logfileinfo, $infoline);
2337			}
2338		}
2339	}
2340
2341	$infoline = "\n";
2342	push( @installer::globals::logfileinfo, $infoline);
2343}
2344
2345#################################################
2346# Determining the destination link of a link
2347#################################################
2348
2349sub get_destination_link_path_for_links
2350{
2351	my ($linksarrayref) = @_;
2352
2353	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_destination_link_path_for_links : $#{$linksarrayref}"); }
2354
2355	my $infoline;
2356
2357	for ( my $i = 0; $i <= $#{$linksarrayref}; $i++ )
2358	{
2359		my $shortcutid = "";
2360		my $onelink = ${$linksarrayref}[$i];
2361		if ( $onelink->{'ShortcutID'} ) { $shortcutid = $onelink->{'ShortcutID'}; }
2362
2363		if (!( $shortcutid eq "" ))
2364		{
2365			my $foundlink = 0;
2366
2367			for ( my $j = 0; $j <= $#{$linksarrayref}; $j++ )
2368			{
2369				my $destlink = ${$linksarrayref}[$j];
2370				$shortcutgid = $destlink->{'gid'};
2371
2372				if ( $shortcutgid eq $shortcutid )
2373				{
2374					$foundlink = 1;
2375					$onelink->{'destinationfile'} = $destlink->{'destination'};		# making key 'destinationfile'
2376					last;
2377				}
2378			}
2379
2380			if (!($foundlink))
2381			{
2382				$infoline = "Warning: ShortcutID $shortcutid for Link $onelink->{'gid'} not found!\n";
2383				push( @installer::globals::logfileinfo, $infoline);
2384			}
2385		}
2386	}
2387
2388	$infoline = "\n";
2389	push( @installer::globals::logfileinfo, $infoline);
2390}
2391
2392###################################################################################
2393# Items with flag WORKSTATION are not needed (here: links and configurationitems)
2394###################################################################################
2395
2396sub remove_workstation_only_items
2397{
2398	my ($itemarrayref) = @_;
2399
2400	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::remove_workstation_only_items : $#{$itemarrayref}"); }
2401
2402	my @newitemarray = ();
2403
2404	for ( my $i = 0; $i <= $#{$itemarrayref}; $i++ )
2405	{
2406		my $oneitem = ${$itemarrayref}[$i];
2407		my $styles = $oneitem->{'Styles'};
2408
2409		if (( $styles =~ /\bWORKSTATION\b/ ) &&
2410			(!( $styles =~ /\bNETWORK\b/ )) &&
2411			(!( $styles =~ /\bSTANDALONE\b/ )))
2412		{
2413			next;	# removing this link, it is only needed for a workstation installation
2414		}
2415
2416		push(@newitemarray, $oneitem);
2417	}
2418
2419	return \@newitemarray;
2420}
2421
2422################################################
2423# Resolving relative path in links
2424################################################
2425
2426sub resolve_links_with_flag_relative
2427{
2428	my ($linksarrayref) = @_;
2429
2430	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::resolve_links_with_flag_relative : $#{$linksarrayref}"); }
2431
2432	# Before this step is:
2433	# destination=program/libsalhelperC52.so.3, this will be the name of the link
2434	# destinationfile=program/libsalhelperC52.so.3, this will be the linked file or name
2435	# If the flag RELATIVE is set, the pathes have to be analyzed. If the flag is not set
2436	# (this will not occur in the future?) destinationfile has to be an absolute path name
2437
2438	for ( my $i = 0; $i <= $#{$linksarrayref}; $i++ )
2439	{
2440		my $onelink = ${$linksarrayref}[$i];
2441		my $styles = $onelink->{'Styles'};
2442
2443		if ( $styles =~ /\bRELATIVE\b/ )
2444		{
2445			# ToDo: This is only a simple not sufficient mechanism
2446
2447			my $destination = $onelink->{'destination'};
2448			my $destinationfile = $onelink->{'destinationfile'};
2449
2450			my $destinationpath = $destination;
2451
2452			installer::pathanalyzer::get_path_from_fullqualifiedname(\$destinationpath);
2453
2454			my $destinationfilepath = $destinationfile;
2455
2456			# it is possible, that the destinationfile is no longer part of the files collector
2457			if ($destinationfilepath) { installer::pathanalyzer::get_path_from_fullqualifiedname(\$destinationfilepath); }
2458			else { $destinationfilepath = ""; }
2459
2460			if ( $destinationpath eq $destinationfilepath )
2461			{
2462				# link and file are in the same directory
2463				# Therefore the path of the file can be removed
2464
2465				my $newdestinationfile = $destinationfile;
2466				installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$newdestinationfile);
2467
2468				$onelink->{'destinationfile'} = $newdestinationfile;
2469			}
2470		}
2471	}
2472}
2473
2474########################################################################
2475# This function is a helper of function "assigning_modules_to_items"
2476########################################################################
2477
2478sub insert_for_item ($$$)
2479{
2480	my ($hash, $item, $id) = @_;
2481
2482	# print STDERR "insert '$id' for '$item'\n";
2483	if (!defined $hash->{$item})
2484	{
2485		my @gids = ();
2486		$hash->{$item} = \@gids;
2487	}
2488	my $gid_list = $hash->{$item};
2489	push @{$gid_list}, $id;
2490	$hash->{$item} = $gid_list;
2491}
2492
2493sub build_modulegids_table
2494{
2495	my ($modulesref, $itemname) = @_;
2496
2497	my %module_lookup_table = ();
2498
2499	# build map of item names to list of respective module gids
2500	# containing these items
2501	for my $onemodule (@{$modulesref})
2502	{
2503		next if ( ! defined $onemodule->{$itemname} );
2504		# these are the items contained in this module
2505		# eg. Files = (gid_a_b_c,gid_d_e_f)
2506		my $module_gids = $onemodule->{$itemname};
2507
2508		# prune outer brackets
2509		$module_gids =~ s|^\s*\(||g;
2510		$module_gids =~ s|\)\s*$||g;
2511		for my $id (split (/,/, $module_gids))
2512		{
2513			chomp $id;
2514			insert_for_item(\%module_lookup_table, lc ($id), $onemodule->{'gid'});
2515		}
2516	}
2517
2518	return \%module_lookup_table;
2519}
2520
2521########################################################################
2522# Items like files do not know their modules
2523# This function is a helper of function "assigning_modules_to_items"
2524########################################################################
2525
2526sub get_string_of_modulegids_for_itemgid
2527{
2528	my ($module_lookup_table, $modulesref, $itemgid, $itemname) = @_;
2529
2530	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::get_string_of_modulegids_for_itemgid : $#{$modulesref} : $itemgid : $itemname"); }
2531
2532	my $allmodules = "";
2533	my $haslanguagemodule = 0;
2534	my %foundmodules = ();
2535
2536	# print STDERR "lookup '" . lc($itemgid) . "'\n";
2537	my $gid_list = $module_lookup_table->{lc($itemgid)};
2538
2539	for my $gid (@{$gid_list})
2540	{
2541		$foundmodules{$gid} = 1;
2542		$allmodules = $allmodules . "," . $gid;
2543		# Is this module a language module? This info should be stored at the file.
2544		if ( exists($installer::globals::alllangmodules{$gid}) ) { $haslanguagemodule = 1; }
2545 	}
2546
2547	$allmodules =~ s/^\s*\,//;	# removing leading comma
2548
2549	# Check: All modules or no module must have flag LANGUAGEMODULE
2550	if ( $haslanguagemodule )
2551	{
2552		my $isreallylanguagemodule = installer::worker::key_in_a_is_also_key_in_b(\%foundmodules, \%installer::globals::alllangmodules);
2553		if ( ! $isreallylanguagemodule ) { installer::exiter::exit_program("ERROR: \"$itemgid\" is assigned to modules with flag \"LANGUAGEMODULE\" and also to modules without this flag! Modules: $allmodules", "get_string_of_modulegids_for_itemgid");  }
2554	}
2555
2556	# print STDERR "get_string_for_itemgid ($itemgid, $itemname) => $allmodules, $haslanguagemodule\n";
2557
2558	return ($allmodules, $haslanguagemodule);
2559}
2560
2561########################################################
2562# Items like files do not know their modules
2563# This function add the {'modules'} to these items
2564########################################################
2565
2566sub assigning_modules_to_items
2567{
2568	my ($modulesref, $itemsref, $itemname) = @_;
2569
2570	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::assigning_modules_to_items : $#{$modulesref} : $#{$itemsref} : $itemname"); }
2571
2572	my $infoline = "";
2573	my $languageassignmenterror = 0;
2574	my @languageassignmenterrors = ();
2575
2576	my $module_lookup_table = build_modulegids_table($modulesref, $itemname);
2577
2578	for my $oneitem (@{$itemsref})
2579	{
2580		my $itemgid = $oneitem->{'gid'};
2581
2582		my $styles = "";
2583		if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
2584		if (( $itemname eq "Dirs" ) && ( ! ( $styles =~ /\bCREATE\b/ ))) { next; }
2585
2586		if ( $itemgid eq "" )
2587		{
2588			installer::exiter::exit_program("ERROR in item collection: No gid for item $oneitem->{'Name'}", "assigning_modules_to_items");
2589		}
2590
2591		# every item can belong to many modules
2592
2593		my ($modulegids, $haslanguagemodule) = get_string_of_modulegids_for_itemgid($module_lookup_table, $modulesref, $itemgid, $itemname);
2594
2595		if ($modulegids eq "")
2596		{
2597			installer::exiter::exit_program("ERROR in file collection: No module found for $itemname $itemgid", "assigning_modules_to_items");
2598		}
2599
2600		$oneitem->{'modules'} = $modulegids;
2601		$oneitem->{'haslanguagemodule'} = $haslanguagemodule;
2602
2603		# Important check: "ismultilingual" and "haslanguagemodule" must have the same value !
2604		if (( $oneitem->{'ismultilingual'} ) && ( ! $oneitem->{'haslanguagemodule'} ))
2605		{
2606			$infoline = "Error: \"$oneitem->{'gid'}\" is multi lingual, but not in language pack (Assigned module: $modulegids)!\n";
2607			push( @installer::globals::globallogfileinfo, $infoline);
2608			push( @languageassignmenterrors, $infoline );
2609			$languageassignmenterror = 1;
2610		}
2611		if (( $oneitem->{'haslanguagemodule'} ) && ( ! $oneitem->{'ismultilingual'} ))
2612		{
2613			$infoline = "Error: \"$oneitem->{'gid'}\" is in language pack, but not multi lingual (Assigned module: $modulegids)!\n";
2614			push( @installer::globals::globallogfileinfo, $infoline);
2615			push( @languageassignmenterrors, $infoline );
2616			$languageassignmenterror = 1;
2617		}
2618	}
2619
2620	if ($languageassignmenterror)
2621	{
2622		for ( my $i = 0; $i <= $#languageassignmenterrors; $i++ ) { print "$languageassignmenterrors[$i]"; }
2623		installer::exiter::exit_program("ERROR: Incorrect assignments for language packs.", "assigning_modules_to_items");
2624	}
2625
2626}
2627
2628#################################################################################################
2629# Root path (for instance /opt/openofficeorg20) needs to be added to directories, files and links
2630#################################################################################################
2631
2632sub add_rootpath_to_directories
2633{
2634	my ($dirsref, $rootpath) = @_;
2635
2636	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::add_rootpath_to_directories : $#{$dirsref} : $rootpath"); }
2637
2638	for ( my $i = 0; $i <= $#{$dirsref}; $i++ )
2639	{
2640		my $onedir = ${$dirsref}[$i];
2641		my $dir = "";
2642
2643		if ( $onedir->{'Dir'} ) { $dir = $onedir->{'Dir'}; }
2644
2645		if (!($dir =~ /\bPREDEFINED_/ ))
2646		{
2647			my $hostname = $onedir->{'HostName'};
2648			$hostname = $rootpath . $installer::globals::separator . $hostname;
2649			$onedir->{'HostName'} = $hostname;
2650		}
2651
2652		# added
2653
2654		if ( $dir =~ /\bPREDEFINED_PROGDIR\b/ )
2655		{
2656			my $hostname = $onedir->{'HostName'};
2657			if ( $hostname eq "" ) { $onedir->{'HostName'} = $rootpath; }
2658			else { $onedir->{'HostName'} = $rootpath . $installer::globals::separator . $hostname; }
2659		}
2660	}
2661}
2662
2663sub add_rootpath_to_files
2664{
2665	my ($filesref, $rootpath) = @_;
2666
2667	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::add_rootpath_to_files : $#{$filesref} : $rootpath"); }
2668
2669	for ( my $i = 0; $i <= $#{$filesref}; $i++ )
2670	{
2671		my $onefile = ${$filesref}[$i];
2672		my $destination = $onefile->{'destination'};
2673		$destination = $rootpath . $installer::globals::separator . $destination;
2674		$onefile->{'destination'} = $destination;
2675	}
2676}
2677
2678sub add_rootpath_to_links
2679{
2680	my ($linksref, $rootpath) = @_;
2681
2682	if ( $installer::globals::debug ) { installer::logger::debuginfo("installer::scriptitems::add_rootpath_to_links : $#{$linksref} : $rootpath"); }
2683
2684	for ( my $i = 0; $i <= $#{$linksref}; $i++ )
2685	{
2686		my $onelink = ${$linksref}[$i];
2687		my $styles = $onelink->{'Styles'};
2688
2689		my $destination = $onelink->{'destination'};
2690		$destination = $rootpath . $installer::globals::separator . $destination;
2691		$onelink->{'destination'} = $destination;
2692
2693		if (!($styles =~ /\bRELATIVE\b/ )) # for absolute links
2694		{
2695			my $destinationfile = $onelink->{'destinationfile'};
2696			$destinationfile = $rootpath . $installer::globals::separator . $destinationfile;
2697			$onelink->{'destinationfile'} = $destinationfile;
2698		}
2699	}
2700}
2701
2702#################################################################################
2703# Collecting all parent gids
2704#################################################################################
2705
2706sub collect_all_parent_feature
2707{
2708	my ($modulesref) = @_;
2709
2710	my @allparents = ();
2711
2712	my $found_root_module = 0;
2713
2714	for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
2715	{
2716		my $onefeature = ${$modulesref}[$i];
2717
2718		my $parentgid = "";
2719		if ( $onefeature->{'ParentID'} )
2720		{
2721			$parentgid = $onefeature->{'ParentID'};
2722		}
2723
2724		if ( $parentgid ne "" )
2725		{
2726			if (! installer::existence::exists_in_array($parentgid, \@allparents))
2727			{
2728				push(@allparents, $parentgid);
2729			}
2730		}
2731
2732		# Setting the global root module
2733
2734		if ( $parentgid eq "" )
2735		{
2736			if ( $found_root_module ) { installer::exiter::exit_program("ERROR: Only one module without ParentID or with empty ParentID allowed ($installer::globals::rootmodulegid, $onefeature->{'gid'}).", "collect_all_parent_feature"); }
2737			$installer::globals::rootmodulegid = $onefeature->{'gid'};
2738			$found_root_module = 1;
2739			$infoline = "Setting Root Module: $installer::globals::rootmodulegid\n";
2740			push( @installer::globals::globallogfileinfo, $infoline);
2741		}
2742
2743		if ( ! $found_root_module ) { installer::exiter::exit_program("ERROR: Could not define root module. No module without ParentID or with empty ParentID exists.", "collect_all_parent_feature"); }
2744
2745	}
2746
2747	return \@allparents;
2748}
2749
2750#################################################################################
2751# Checking for every feature, whether it has children
2752#################################################################################
2753
2754sub set_children_flag
2755{
2756	my ($modulesref) = @_;
2757
2758	my $allparents = collect_all_parent_feature($modulesref);
2759
2760	for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
2761	{
2762		my $onefeature = ${$modulesref}[$i];
2763		my $gid = $onefeature->{'gid'};
2764
2765		# is this gid a parent?
2766
2767		if ( installer::existence::exists_in_array($gid, $allparents) )
2768		{
2769			$onefeature->{'has_children'} = 1;
2770		}
2771		else
2772		{
2773			$onefeature->{'has_children'} = 0;
2774		}
2775	}
2776}
2777
2778#################################################################################
2779# All modules, that use a template module, do now get the assignments of
2780# the template module.
2781#################################################################################
2782
2783sub resolve_assigned_modules
2784{
2785	my ($modulesref) = @_;
2786
2787	# collecting all template modules
2788
2789	my %directaccess = ();
2790
2791	for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
2792	{
2793		my $onefeature = ${$modulesref}[$i];
2794		my $styles = "";
2795		if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; }
2796		if ( $styles =~ /\bTEMPLATEMODULE\b/ ) { $directaccess{$onefeature->{'gid'}} = $onefeature; }
2797
2798		# also looking for module with flag ROOT_BRAND_PACKAGE, to save is for further usage
2799		if ( $styles =~ /\bROOT_BRAND_PACKAGE\b/ )
2800		{
2801			$installer::globals::rootbrandpackage = $onefeature->{'gid'};
2802			$installer::globals::rootbrandpackageset = 1;
2803		}
2804	}
2805
2806	# looking, where template modules are assigned
2807
2808	for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
2809	{
2810		my $onefeature = ${$modulesref}[$i];
2811		if ( $onefeature->{'Assigns'} )
2812		{
2813			my $templategid = $onefeature->{'Assigns'};
2814
2815			if ( ! exists($directaccess{$templategid}) )
2816			{
2817				installer::exiter::exit_program("ERROR: Did not find definition of assigned template module \"$templategid\"", "resolve_assigned_modules");
2818			}
2819
2820			# Currently no merging of Files, Dirs, ...
2821			# This has to be included here, if it is required
2822			my $item;
2823			foreach $item (@installer::globals::items_at_modules)
2824			{
2825				if ( exists($directaccess{$templategid}->{$item}) ) { $onefeature->{$item} = $directaccess{$templategid}->{$item}; }
2826			}
2827		}
2828	}
2829}
2830
2831#################################################################################
2832# Removing the template modules from the list, after all
2833# assignments are transferred to the "real" modules.
2834#################################################################################
2835
2836sub remove_template_modules
2837{
2838	my ($modulesref) = @_;
2839
2840	my @modules = ();
2841
2842	for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
2843	{
2844		my $onefeature = ${$modulesref}[$i];
2845		my $styles = "";
2846		if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; }
2847		if ( $styles =~ /\bTEMPLATEMODULE\b/ ) { next; }
2848
2849		push(@modules, $onefeature);
2850	}
2851
2852	return \@modules;
2853}
2854
2855#################################################################################
2856# Collecting all modules with flag LANGUAGEMODULE in a global
2857# collector.
2858#################################################################################
2859
2860sub collect_all_languagemodules
2861{
2862	my ($modulesref) = @_;
2863
2864	for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
2865	{
2866		my $onefeature = ${$modulesref}[$i];
2867		my $styles = "";
2868		if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; }
2869		if ( $styles =~ /\bLANGUAGEMODULE\b/ )
2870		{
2871			if ( ! exists($onefeature->{'Language'}) ) { installer::exiter::exit_program("ERROR: \"$onefeature->{'gid'}\" has flag LANGUAGEMODULE, but does not know its language!", "collect_all_languagemodules"); }
2872			$installer::globals::alllangmodules{$onefeature->{'gid'}} = $onefeature->{'Language'};
2873			# Collecting also the english names, that are used for nsis unpack directory for language packs
2874			my $lang = $onefeature->{'Language'};
2875			my $name = "";
2876			foreach my $localkey ( keys %{$onefeature} )
2877			{
2878				if ( $localkey =~ /^\s*Name\s*\(\s*en-US\s*\)\s*$/ )
2879				{
2880					$installer::globals::all_english_languagestrings{$lang} = $onefeature->{$localkey};
2881				}
2882			}
2883		}
2884	}
2885}
2886
2887#################################################################################
2888# Selecting from all collected english language strings those, that are really
2889# required in this installation set.
2890#################################################################################
2891
2892sub select_required_language_strings
2893{
2894	my ($modulesref) = @_;
2895
2896	for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
2897	{
2898		my $onefeature = ${$modulesref}[$i];
2899		my $styles = "";
2900		if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; }
2901		if ( $styles =~ /\bLANGUAGEMODULE\b/ )
2902		{
2903			if ( ! exists($onefeature->{'Language'}) ) { installer::exiter::exit_program("ERROR: \"$onefeature->{'gid'}\" has flag LANGUAGEMODULE, but does not know its language!", "select_required_language_strings"); }
2904			my $lang = $onefeature->{'Language'};
2905
2906			if (( exists($installer::globals::all_english_languagestrings{$lang}) ) && ( ! exists($installer::globals::all_required_english_languagestrings{$lang}) ))
2907			{
2908				$installer::globals::all_required_english_languagestrings{$lang} = $installer::globals::all_english_languagestrings{$lang};
2909			}
2910		}
2911	}
2912}
2913
2914#####################################################################################
2915# Unixlinks are not always required. For Linux RPMs and Solaris Packages they are
2916# created dynamically. Exception: For package formats "installed" or "archive".
2917# In scp2 this unixlinks have the flag LAYERLINK.
2918#####################################################################################
2919
2920sub filter_layerlinks_from_unixlinks
2921{
2922	my ( $unixlinksref ) = @_;
2923
2924	my @alllinks = ();
2925
2926	for ( my $i = 0; $i <= $#{$unixlinksref}; $i++ )
2927	{
2928		my $isrequired = 1;
2929
2930		my $onelink = ${$unixlinksref}[$i];
2931		my $styles = "";
2932		if ( $onelink->{'Styles'} ) { $styles = $onelink->{'Styles'}; }
2933
2934		if ( $styles =~ /\bLAYERLINK\b/ )
2935		{
2936			# Platforms, that do not need the layer links
2937			if (( $installer::globals::islinuxrpmbuild ) || ( $installer::globals::issolarispkgbuild ))
2938			{
2939				$isrequired = 0;
2940			}
2941
2942			# Package formats, that need the layer link (platform independent)
2943			if (( $installer::globals::packageformat eq "installed" ) || ( $installer::globals::packageformat eq "archive" ))
2944			{
2945				$isrequired = 1;
2946			}
2947		}
2948
2949		if ( $isrequired ) { push(@alllinks, $onelink); }
2950	}
2951
2952	return \@alllinks;
2953}
2954
29551;
2956