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