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