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