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