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