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