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