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