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