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