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