xref: /trunk/main/solenv/bin/modules/installer/scriptitems.pm (revision f3385db031069db3e0655c6a4d85518bf39a7b68)
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 built.
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 patches
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 paths
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 paths 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            # On Mac OS X the installation root is the bundle's Contents
1717            # directory, where only the entries defined by Apple may live --
1718            # a stray LICENSE or README there makes the bundle unsignable.
1719            # The copy in the installation set (the .dmg root, below) is the
1720            # one users actually see anyway.
1721            if ( ! $installer::globals::ismacosx )
1722            {
1723                push(@newfilesarray, $newfile);
1724
1725                $installer::logger::Lang->printf(
1726                    "New files: Adding file %s for the installation root to the file list. Language: %s\n",
1727                    $newfilename,
1728                    $defaultlanguage);
1729            }
1730
1731            if ( defined $newfile->{'InstallName'} )
1732            {
1733                $installer::logger::Lang->printf(
1734                    "New files: Using installation name: %s\n", $newfile->{'InstallName'});
1735            }
1736
1737            # Collecting license and readme file for the installation set
1738
1739            push(@installer::globals::installsetfiles, $newfile);
1740            $installer::logger::Lang->printf(
1741                "New files: Adding file %s to the file collector for the installation set. Language: %s\n",
1742                $newfilename,
1743                $defaultlanguage);
1744        }
1745
1746        push(@newfilesarray, $onefile);
1747    }
1748
1749    return \@newfilesarray;
1750}
1751
1752############################################################################
1753# Removing files with flag ONLY_ASIA_LANGUAGE, only if no Asian
1754# language is part of the product.
1755# This special files are connected to the root module and are not
1756# included into a language pack (would lead to conflicts!).
1757# But this files shall only be included into the product, if the
1758# product contains at least one Asian language.
1759############################################################################
1760
1761sub remove_onlyasialanguage_files_from_productlists
1762{
1763    my ($filesarrayref) = @_;
1764
1765    my $infoline;
1766
1767    my @newfilesarray = ();
1768    my $returnfilesarrayref;
1769
1770    my $containsasianlanguage = installer::languages::detect_asian_language($installer::globals::alllanguagesinproductarrayref);
1771
1772    my $alllangstring = installer::converter::convert_array_to_comma_separated_string($installer::globals::alllanguagesinproductarrayref);
1773    $installer::logger::Lang->printf("\n");
1774    $installer::logger::Lang->printf("Languages in complete product: %s\n", $alllangstring);
1775
1776    if ( ! $containsasianlanguage )
1777    {
1778        $installer::logger::Lang->printf("Product does not contain Asian language -> removing files\n");
1779
1780        for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
1781        {
1782            my $onefile = ${$filesarrayref}[$i];
1783            my $styles = "";
1784            if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }
1785            if ( $styles =~ /\bONLY_ASIA_LANGUAGE\b/ )
1786            {
1787                $installer::logger::Lang->printf(
1788                    "Flag ONLY_ASIA_LANGUAGE: Removing file %s from files collector!\n",
1789                    $onefile->{'Name'});
1790                next;
1791            }
1792
1793            push(@newfilesarray, $onefile);
1794        }
1795
1796        $returnfilesarrayref = \@newfilesarray;
1797    }
1798    else
1799    {
1800        $returnfilesarrayref = $filesarrayref;
1801
1802        $installer::logger::Lang->printf("Product contains Asian language -> Nothing to do\n");
1803    }
1804
1805    return $returnfilesarrayref;
1806}
1807
1808############################################################################
1809# Removing files with flag ONLY_WESTERN_LANGUAGE, only if no western
1810# language is part of the product.
1811# This special files are connected to the root module and are not
1812# included into a language pack (would lead to conflicts!).
1813# But this files shall only be included into the product, if the
1814# product contains at least one western language.
1815############################################################################
1816
1817sub remove_onlywesternlanguage_files_from_productlists
1818{
1819    my ($filesarrayref) = @_;
1820
1821    my $infoline;
1822
1823    my @newfilesarray = ();
1824    my $returnfilesarrayref;
1825
1826    my $containswesternlanguage = installer::languages::detect_western_language($installer::globals::alllanguagesinproductarrayref);
1827
1828    my $alllangstring = installer::converter::convert_array_to_comma_separated_string($installer::globals::alllanguagesinproductarrayref);
1829    $installer::logger::Lang->printf("\n");
1830    $installer::logger::Lang->printf("Languages in complete product: %s\n", $alllangstring);
1831
1832    if ( ! $containswesternlanguage )
1833    {
1834        $installer::logger::Lang->printf("Product does not contain western language -> removing files\n");
1835
1836        for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
1837        {
1838            my $onefile = ${$filesarrayref}[$i];
1839            my $styles = "";
1840            if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }
1841            if ( $styles =~ /\bONLY_WESTERN_LANGUAGE\b/ )
1842            {
1843                $installer::logger::Lang->printf(
1844                    "Flag ONLY_WESTERN_LANGUAGE: Removing file %s from files collector!\n",
1845                    $onefile->{'Name'});
1846                next;
1847            }
1848
1849            push(@newfilesarray, $onefile);
1850        }
1851
1852        $returnfilesarrayref = \@newfilesarray;
1853    }
1854    else
1855    {
1856        $returnfilesarrayref = $filesarrayref;
1857
1858        $installer::logger::Lang->printf("Product contains western language -> Nothing to do\n");
1859    }
1860
1861    return $returnfilesarrayref;
1862}
1863
1864############################################################################
1865# Some files are included for more than one language and have the same
1866# name and the same destination directory for all languages. This would
1867# lead to conflicts, if the filenames are not changed.
1868# In scp project this files must have the flag MAKE_LANG_SPECIFIC
1869# For this files, the language is included into the filename.
1870############################################################################
1871
1872sub make_filename_language_specific
1873{
1874    my ($filesarrayref) = @_;
1875
1876    my $infoline = "";
1877
1878    for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
1879    {
1880        my $onefile = ${$filesarrayref}[$i];
1881
1882        if ( $onefile->{'ismultilingual'} )
1883        {
1884            my $styles = "";
1885            if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }
1886            if ( $styles =~ /\bMAKE_LANG_SPECIFIC\b/ )
1887            {
1888                my $language = $onefile->{'specificlanguage'};
1889                my $olddestination = $onefile->{'destination'};
1890                my $oldname = $onefile->{'Name'};
1891
1892                # Including the language into the file name.
1893                # But be sure, to include the language before the file extension.
1894
1895                my $fileextension = "";
1896
1897                if ( $onefile->{'Name'} =~ /(\.\w+?)\s*$/ ) { $fileextension = $1; }
1898                if ( $fileextension ne "" )
1899                {
1900                    $onefile->{'Name'} =~ s/\Q$fileextension\E\s*$/_$language$fileextension/;
1901                    $onefile->{'destination'} =~ s/\Q$fileextension\E\s*$/_$language$fileextension/;
1902                }
1903
1904                $installer::logger::Lang->printf("Flag MAKE_LANG_SPECIFIC:\n");
1905                $installer::logger::Lang->printf("Changing name from %s to %s !\n", $oldname, $onefile->{'Name'});
1906                $installer::logger::Lang->printf("Changing destination from %s to %s !\n",
1907                    $olddestination, $onefile->{'destination'});
1908            }
1909        }
1910    }
1911}
1912
1913############################################################################
1914# Removing all scpactions, that have no name.
1915# See: FlatLoaderZip
1916############################################################################
1917
1918sub remove_scpactions_without_name
1919{
1920    my ($itemsarrayref) = @_;
1921
1922    my $infoline;
1923
1924    my @newitemsarray = ();
1925
1926    for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
1927    {
1928        my $oneitem = ${$itemsarrayref}[$i];
1929        my $name = "";
1930
1931        if ( $oneitem->{'Name'} ) { $name = $oneitem->{'Name'}; }
1932
1933        if  ( $name eq "" )
1934        {
1935            $installer::logger::Lang->printf(
1936                "ATTENTION: Removing scpaction %s from the installation set.\n",
1937                $oneitem->{'gid'});
1938            next;
1939        }
1940
1941        push(@newitemsarray, $oneitem);
1942    }
1943
1944    return \@newitemsarray;
1945}
1946
1947############################################################################
1948# Because of the item "File" the source name must be "Name". Therefore
1949# "Copy" is changed to "Name" and "Name" is changed to "DestinationName".
1950############################################################################
1951
1952sub change_keys_of_scpactions
1953{
1954    my ($itemsarrayref) = @_;
1955
1956    for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
1957    {
1958        my $oneitem = ${$itemsarrayref}[$i];
1959
1960        my $key;
1961
1962        # First Name to DestinationName, then deleting Name
1963        foreach $key (keys %{$oneitem})
1964        {
1965            if ( $key =~ /\bName\b/ )
1966            {
1967                my $value = $oneitem->{$key};
1968                my $oldkey = $key;
1969                $key =~ s/Name/DestinationName/;
1970                $oneitem->{$key} = $value;
1971                delete($oneitem->{$oldkey});
1972            }
1973        }
1974
1975        # Second Copy to Name, then deleting Copy
1976        foreach $key (keys %{$oneitem})
1977        {
1978            if ( $key =~ /\bCopy\b/ )
1979            {
1980                my $value = $oneitem->{$key};
1981                my $oldkey = $key;
1982                $key =~ s/Copy/Name/;
1983                $oneitem->{$key} = $value;
1984                delete($oneitem->{$oldkey});
1985            }
1986        }
1987    }
1988}
1989
1990############################################################################
1991# Removing all xpd only items from installation set (scpactions with
1992# the style XPD_ONLY), except an xpd installation set is created
1993############################################################################
1994
1995sub remove_Xpdonly_Items
1996{
1997    my ($itemsarrayref) = @_;
1998
1999    my $infoline;
2000
2001    my @newitemsarray = ();
2002
2003    for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
2004    {
2005        my $oneitem = ${$itemsarrayref}[$i];
2006        my $styles = "";
2007        if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
2008
2009        if ( $styles =~ /\bXPD_ONLY\b/ )
2010        {
2011            $installer::logger::Global->printf(
2012                "Removing \"xpd only\" item %s from the installation set.\n",
2013                $oneitem->{'gid'});
2014
2015            next;
2016        }
2017
2018        push(@newitemsarray, $oneitem);
2019    }
2020
2021    $installer::logger::Global->print("\n");
2022
2023    return \@newitemsarray;
2024}
2025
2026############################################################################
2027# Removing all language pack files from installation set (files with
2028# the style LANGUAGEPACK), except this is a language pack.
2029############################################################################
2030
2031sub remove_Languagepacklibraries_from_Installset
2032{
2033    my ($itemsarrayref) = @_;
2034
2035    my $infoline;
2036
2037    my @newitemsarray = ();
2038
2039    for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
2040    {
2041        my $oneitem = ${$itemsarrayref}[$i];
2042        my $styles = "";
2043        if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
2044
2045        if ( $styles =~ /\bLANGUAGEPACK\b/ )
2046        {
2047            $installer::logger::Global->printf(
2048                "Removing language pack file %s from the installation set.\n",
2049                $oneitem->{'gid'});
2050
2051            next;
2052        }
2053
2054        push(@newitemsarray, $oneitem);
2055    }
2056
2057    $installer::logger::Global->print("\n");
2058
2059    return \@newitemsarray;
2060}
2061
2062############################################################################
2063# Removing all files with flag PATCH_ONLY from installation set.
2064# This function is not called during patch creation.
2065############################################################################
2066
2067sub remove_patchonlyfiles_from_Installset
2068{
2069    my ($itemsarrayref) = @_;
2070
2071    my $infoline;
2072
2073    my @newitemsarray = ();
2074
2075    for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
2076    {
2077        my $oneitem = ${$itemsarrayref}[$i];
2078        my $styles = "";
2079        if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
2080
2081        if ( $styles =~ /\bPATCH_ONLY\b/ )
2082        {
2083            $installer::logger::Global->printf(
2084                "Removing file with flag PATCH_ONLY %s from the installation set.\n",
2085                $oneitem->{'gid'});
2086
2087            next;
2088        }
2089
2090        push(@newitemsarray, $oneitem);
2091    }
2092
2093    $installer::logger::Global->print("\n");
2094
2095    return \@newitemsarray;
2096}
2097
2098############################################################################
2099# Removing all files with flag TAB_ONLY from installation set.
2100# This function is not called during tab creation.
2101############################################################################
2102
2103sub remove_tabonlyfiles_from_Installset
2104{
2105    my ($itemsarrayref) = @_;
2106
2107    my $infoline;
2108
2109    my @newitemsarray = ();
2110
2111    for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
2112    {
2113        my $oneitem = ${$itemsarrayref}[$i];
2114        my $styles = "";
2115        if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
2116
2117        if ( $styles =~ /\bTAB_ONLY\b/ )
2118        {
2119            $installer::logger::Global->printf(
2120                "Removing tab only file %s from the installation set.\n",
2121                $oneitem->{'gid'});
2122
2123            next;
2124        }
2125
2126        push(@newitemsarray, $oneitem);
2127    }
2128
2129    $installer::logger::Global->print("\n");
2130
2131    return \@newitemsarray;
2132}
2133
2134###############################################################################
2135# Removing all files with flag ONLY_INSTALLED_PRODUCT from installation set.
2136# This function is not called for PKGFORMAT installed and archive.
2137###############################################################################
2138
2139sub remove_installedproductonlyfiles_from_Installset
2140{
2141    my ($itemsarrayref) = @_;
2142
2143    my $infoline;
2144
2145    my @newitemsarray = ();
2146
2147    for ( my $i = 0; $i <= $#{$itemsarrayref}; $i++ )
2148    {
2149        my $oneitem = ${$itemsarrayref}[$i];
2150        my $styles = "";
2151        if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
2152
2153        if ( $styles =~ /\bONLY_INSTALLED_PRODUCT\b/ )
2154        {
2155            $installer::logger::Global->printf(
2156                "Removing file from the installation set. This file is only required for PKGFORMAT archive or installed).\n",
2157                $oneitem->{'gid'});
2158            next;
2159        }
2160
2161        push(@newitemsarray, $oneitem);
2162    }
2163
2164    $installer::logger::Global->print("\n");
2165
2166    return \@newitemsarray;
2167}
2168
2169############################################################################
2170# Some files contain a $ in their name. epm conflicts with such files.
2171# Solution: Renaming this files, converting "$" to "$$"
2172############################################################################
2173
2174sub quoting_illegal_filenames
2175{
2176    my ($filesarrayref) = @_;
2177
2178    # This function has to be removed as soon as possible!
2179
2180    installer::logger::include_header_into_logfile("Renaming illegal filenames:");
2181
2182    for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
2183    {
2184        my $onefile = ${$filesarrayref}[$i];
2185        my $filename = $onefile->{'Name'};
2186
2187        if ( $filename =~ /\$/ )
2188        {
2189            my $sourcepath = $onefile->{'sourcepath'};
2190            my $destpath = $onefile->{'destination'};
2191
2192            # sourcepath and destination have to be quoted for epm list file
2193
2194            $destpath =~ s/\$/\$\$/g;
2195            $sourcepath =~ s/\$/\$\$/g;
2196
2197            $installer::logger::Lang->printf("ATTENTION: Files: Quoting sourcepath %s to %s\n",
2198                $onefile->{'sourcepath'},
2199                $sourcepath);
2200            $installer::logger::Lang->printf("ATTENTION: Files: Quoting destination path %s to %s\n",
2201                $onefile->{'destination'},
2202                $destpath);
2203
2204            # $onefile->{'Name'} = $filename;
2205            $onefile->{'sourcepath'} = $sourcepath;
2206            $onefile->{'destination'} = $destpath;
2207        }
2208    }
2209}
2210
2211############################################################################
2212# Removing multiple occurrences of same module.
2213############################################################################
2214
2215sub optimize_list
2216{
2217    my ( $longlist ) = @_;
2218
2219    my $shortlist = "";
2220    my $hashref = installer::converter::convert_stringlist_into_hash(\$longlist, ",");
2221    foreach my $key (sort keys %{$hashref} ) { $shortlist = "$shortlist,$key"; }
2222    $shortlist =~ s/^\s*\,//;
2223
2224    return $shortlist;
2225}
2226
2227#######################################################################
2228# Collecting all directories needed for the epm list
2229# 1. Looking for all destination paths in the files array
2230# 2. Looking for directories with CREATE flag in the directory array
2231#######################################################################
2232
2233##################################
2234# Collecting directories: Part 1
2235##################################
2236
2237sub collect_directories_from_filesarray
2238{
2239    my ($filesarrayref) = @_;
2240
2241    my @alldirectories = ();
2242    my %alldirectoryhash = ();
2243
2244    my $predefinedprogdir_added = 0;
2245    my $alreadyincluded = 0;
2246
2247    # Preparing this already as hash, although the only needed value at the moment is the HostName
2248    # But also adding: "specificlanguage" and "Dir" (for instance gid_Dir_Program)
2249
2250    for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
2251    {
2252        my $onefile = ${$filesarrayref}[$i];
2253        my $destinationpath = $onefile->{'destination'};
2254        installer::pathanalyzer::get_path_from_fullqualifiedname(\$destinationpath);
2255        $destinationpath =~ s/\Q$installer::globals::separator\E\s*$//;     # removing ending slashes or backslashes
2256
2257        $alreadyincluded = 0;
2258        if ( exists($alldirectoryhash{$destinationpath}) ) { $alreadyincluded = 1; }
2259
2260        if (!($alreadyincluded))
2261        {
2262            my %directoryhash = ();
2263            $directoryhash{'HostName'} = $destinationpath;
2264            $directoryhash{'specificlanguage'} = $onefile->{'specificlanguage'};
2265            $directoryhash{'Dir'} = $onefile->{'Dir'};
2266            $directoryhash{'modules'} = $onefile->{'modules'}; # NEW, saving modules
2267            # NEVER!!!  if ( ! $installer::globals::iswindowsbuild ) { $directoryhash{'Styles'} = "(CREATE)"; } # this directories must be created
2268
2269            if ( $onefile->{'Dir'} eq "PREDEFINED_PROGDIR" ) { $predefinedprogdir_added = 1; }
2270
2271            $alldirectoryhash{$destinationpath} = \%directoryhash;
2272
2273            # Problem: The $destinationpath can be share/registry/schema/org/openoffice
2274            # but not all directories contain files and will be added to this list.
2275            # Therefore the path has to be analyzed.
2276
2277            while ( $destinationpath =~ /(^.*\S)\Q$installer::globals::separator\E(\S.*?)\s*$/ )    # as long as the path contains slashes
2278            {
2279                $destinationpath = $1;
2280
2281                $alreadyincluded = 0;
2282                if ( exists($alldirectoryhash{$destinationpath}) ) { $alreadyincluded = 1; }
2283
2284                if (!($alreadyincluded))
2285                {
2286                    my %directoryhash = ();
2287
2288                    $directoryhash{'HostName'} = $destinationpath;
2289                    $directoryhash{'specificlanguage'} = $onefile->{'specificlanguage'};
2290                    $directoryhash{'Dir'} = $onefile->{'Dir'};
2291                    $directoryhash{'modules'} = $onefile->{'modules'}; # NEW, saving modules
2292                    # NEVER!!! if ( ! $installer::globals::iswindowsbuild ) { $directoryhash{'Styles'} = "(CREATE)"; }  # this directories must be created
2293
2294                    $alldirectoryhash{$destinationpath} = \%directoryhash;
2295                }
2296                else
2297                {
2298                    # Adding the modules to the module list!
2299                    $alldirectoryhash{$destinationpath}->{'modules'} = $alldirectoryhash{$destinationpath}->{'modules'} . "," . $onefile->{'modules'};
2300                }
2301            }
2302        }
2303        else
2304        {
2305            # Adding the modules to the module list!
2306            $alldirectoryhash{$destinationpath}->{'modules'} = $alldirectoryhash{$destinationpath}->{'modules'} . "," . $onefile->{'modules'};
2307
2308            # Also adding the module to all parents
2309            while ( $destinationpath =~ /(^.*\S)\Q$installer::globals::separator\E(\S.*?)\s*$/ )    # as long as the path contains slashes
2310            {
2311                $destinationpath = $1;
2312                $alldirectoryhash{$destinationpath}->{'modules'} = $alldirectoryhash{$destinationpath}->{'modules'} . "," . $onefile->{'modules'};
2313            }
2314        }
2315    }
2316
2317    # if there is no file in the root directory PREDEFINED_PROGDIR, it has to be included into the directory array now
2318    # HostName= specificlanguage=   Dir=PREDEFINED_PROGDIR
2319
2320    if (! $predefinedprogdir_added )
2321    {
2322        my %directoryhash = ();
2323        $directoryhash{'HostName'} = "";
2324        $directoryhash{'specificlanguage'} = "";
2325        $directoryhash{'modules'} = ""; # ToDo?
2326        $directoryhash{'Dir'} = "PREDEFINED_PROGDIR";
2327
2328        push(@alldirectories, \%directoryhash);
2329    }
2330
2331    # Creating directory array
2332    foreach my $destdir ( sort keys %alldirectoryhash )
2333    {
2334        $alldirectoryhash{$destdir}->{'modules'} = optimize_list($alldirectoryhash{$destdir}->{'modules'});
2335        push(@alldirectories, $alldirectoryhash{$destdir});
2336    }
2337
2338    return (\@alldirectories, \%alldirectoryhash);
2339}
2340
2341##################################
2342# Collecting directories: Part 2
2343##################################
2344
2345sub collect_directories_with_create_flag_from_directoryarray ($$)
2346{
2347    my ($directoryarrayref, $alldirectoryhash) = @_;
2348
2349    my $alreadyincluded = 0;
2350    my @alldirectories = ();
2351
2352    for ( my $i = 0; $i <= $#{$directoryarrayref}; $i++ )
2353    {
2354        my $onedir = ${$directoryarrayref}[$i];
2355        my $styles = "";
2356        my $newdirincluded = 0;
2357
2358        if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; }
2359
2360        if ( $styles =~ /\bCREATE\b/ )
2361        {
2362            my $directoryname = "";
2363
2364            if ( $onedir->{'HostName'} ) { $directoryname = $onedir->{'HostName'}; }
2365            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"); }
2366
2367            $alreadyincluded = 0;
2368            if ( exists($alldirectoryhash->{$directoryname}) ) { $alreadyincluded = 1; }
2369
2370            if (!($alreadyincluded))
2371            {
2372                my %directoryhash = ();
2373                $directoryhash{'HostName'} = $directoryname;
2374                $directoryhash{'specificlanguage'} = $onedir->{'specificlanguage'};
2375                # $directoryhash{'gid'} = $onedir->{'gid'};
2376                $directoryhash{'Dir'} = $onedir->{'gid'};
2377                $directoryhash{'Styles'} = $onedir->{'Styles'};
2378
2379                # saving also the modules
2380                if ( ! $onedir->{'modules'} ) { installer::exiter::exit_program("ERROR: No assigned modules found for directory $onedir->{'gid'}", "collect_directories_with_create_flag_from_directoryarray"); }
2381                $directoryhash{'modules'} = $onedir->{'modules'};
2382
2383                $alldirectoryhash->{$directoryname} = \%directoryhash;
2384                $newdirincluded = 1;
2385
2386                # Problem: The $destinationpath can be share/registry/schema/org/openoffice
2387                # but not all directories contain files and will be added to this list.
2388                # Therefore the path has to be analyzed.
2389
2390                while ( $directoryname =~ /(^.*\S)\Q$installer::globals::separator\E(\S.*?)\s*$/ )  # as long as the path contains slashes
2391                {
2392                    $directoryname = $1;
2393
2394                    $alreadyincluded = 0;
2395                    if ( exists($alldirectoryhash->{$directoryname}) ) { $alreadyincluded = 1; }
2396
2397                    if (!($alreadyincluded))
2398                    {
2399                        my %directoryhash = ();
2400
2401                        $directoryhash{'HostName'} = $directoryname;
2402                        $directoryhash{'specificlanguage'} = $onedir->{'specificlanguage'};
2403                        $directoryhash{'Dir'} = $onedir->{'gid'};
2404                        if ( ! $installer::globals::iswindowsbuild ) { $directoryhash{'Styles'} = "(CREATE)"; } # Exception for Windows?
2405
2406                        # saving also the modules
2407                        $directoryhash{'modules'} = $onedir->{'modules'};
2408
2409                        $alldirectoryhash->{$directoryname} = \%directoryhash;
2410                        $newdirincluded = 1;
2411                    }
2412                    else
2413                    {
2414                        # Adding the modules to the module list!
2415                        $alldirectoryhash->{$directoryname}->{'modules'} = $alldirectoryhash->{$directoryname}->{'modules'} . "," . $onedir->{'modules'};
2416                    }
2417                }
2418            }
2419            else
2420            {
2421                # Adding the modules to the module list!
2422                $alldirectoryhash->{$directoryname}->{'modules'} = $alldirectoryhash->{$directoryname}->{'modules'} . "," . $onedir->{'modules'};
2423
2424                while ( $directoryname =~ /(^.*\S)\Q$installer::globals::separator\E(\S.*?)\s*$/ )  # as long as the path contains slashes
2425                {
2426                    $directoryname = $1;
2427                    # Adding the modules to the module list!
2428                    $alldirectoryhash->{$directoryname}->{'modules'} = $alldirectoryhash->{$directoryname}->{'modules'} . "," . $onedir->{'modules'};
2429                }
2430            }
2431        }
2432
2433        # Saving the styles for already added directories in function collect_directories_from_filesarray
2434
2435        if (( ! $newdirincluded ) && ( $styles ne "" ))
2436        {
2437            $styles =~ s/\bWORKSTATION\b//;
2438            $styles =~ s/\bCREATE\b//;
2439
2440            if (( ! ( $styles =~ /^\s*\(\s*\)\s*$/ )) && ( ! ( $styles =~ /^\s*\(\s*\,\s*\)\s*$/ )) && ( ! ( $styles =~ /^\s*$/ ))) # checking, if there are styles left
2441            {
2442                my $directoryname = "";
2443                if ( $onedir->{'HostName'} ) { $directoryname = $onedir->{'HostName'}; }
2444                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"); }
2445
2446                if ( exists($alldirectoryhash->{$directoryname}) )
2447                {
2448                    $alldirectoryhash->{$directoryname}->{'Styles'} = $styles;
2449                }
2450            }
2451        }
2452    }
2453
2454    # Creating directory array
2455    foreach my $destdir ( sort keys %{$alldirectoryhash} )
2456    {
2457        $alldirectoryhash->{$destdir}->{'modules'} = optimize_list($alldirectoryhash->{$destdir}->{'modules'});
2458        push(@alldirectories, $alldirectoryhash->{$destdir});
2459    }
2460
2461    return (\@alldirectories, $alldirectoryhash);
2462}
2463
2464#################################################
2465# Determining the destination file of a link
2466#################################################
2467
2468sub get_destination_file_path_for_links ($$)
2469{
2470    my ($linksarrayref, $filesarrayref) = @_;
2471
2472    my $infoline;
2473
2474    for ( my $i = 0; $i <= $#{$linksarrayref}; $i++ )
2475    {
2476        my $fileid = "";
2477        my $onelink = ${$linksarrayref}[$i];
2478        if ( $onelink->{'FileID'} ) { $fileid = $onelink->{'FileID'}; }
2479
2480        if (!( $fileid eq "" ))
2481        {
2482            my $foundfile = 0;
2483
2484            for ( my $j = 0; $j <= $#{$filesarrayref}; $j++ )
2485            {
2486                my $onefile = ${$filesarrayref}[$j];
2487                my $filegid = $onefile->{'gid'};
2488
2489                if ( $filegid eq $fileid )
2490                {
2491                    $foundfile = 1;
2492                    $onelink->{'destinationfile'} = $onefile->{'destination'};
2493                    last;
2494                }
2495            }
2496
2497            if (!($foundfile))
2498            {
2499                $installer::logger::Lang->printf("Warning: FileID %s for Link %s not found!\n",
2500                    $fileid,
2501                    $onelink->{'gid'});
2502            }
2503        }
2504    }
2505
2506    $installer::logger::Lang->printf("\n");
2507}
2508
2509#################################################
2510# Determining the destination link of a link
2511#################################################
2512
2513sub get_destination_link_path_for_links ($)
2514{
2515    my ($linksarrayref) = @_;
2516
2517    my $infoline;
2518
2519    foreach my $onelink (@$linksarrayref)
2520    {
2521        my $shortcutid = "";
2522        if ($onelink->{'ShortcutID'})
2523        {
2524            $shortcutid = $onelink->{'ShortcutID'};
2525        }
2526
2527        if ($shortcutid ne "")
2528        {
2529            my $foundlink = 0;
2530
2531            foreach my $destlink (@$linksarrayref)
2532            {
2533                if ($destlink->{'gid'} eq $shortcutid)
2534                {
2535                    $foundlink = 1;
2536                    $onelink->{'destinationfile'} = $destlink->{'destination'};     # making key 'destinationfile'
2537                    last;
2538                }
2539            }
2540
2541            if ( ! $foundlink)
2542            {
2543                $installer::logger::Lang->printf("Warning: ShortcutID %s for Link %s not found!\n",
2544                    $shortcutid,
2545                    $onelink->{'gid'});
2546            }
2547        }
2548    }
2549
2550    $installer::logger::Lang->printf("\n");
2551}
2552
2553###################################################################################
2554# Items with flag WORKSTATION are not needed (here: links and configurationitems)
2555###################################################################################
2556
2557sub remove_workstation_only_items
2558{
2559    my ($itemarrayref) = @_;
2560
2561    my @newitemarray = ();
2562
2563    for ( my $i = 0; $i <= $#{$itemarrayref}; $i++ )
2564    {
2565        my $oneitem = ${$itemarrayref}[$i];
2566        my $styles = $oneitem->{'Styles'};
2567
2568        if (( $styles =~ /\bWORKSTATION\b/ ) &&
2569            (!( $styles =~ /\bNETWORK\b/ )) &&
2570            (!( $styles =~ /\bSTANDALONE\b/ )))
2571        {
2572            next;   # removing this link, it is only needed for a workstation installation
2573        }
2574
2575        push(@newitemarray, $oneitem);
2576    }
2577
2578    return \@newitemarray;
2579}
2580
2581################################################
2582# Resolving relative path in links
2583################################################
2584
2585sub resolve_links_with_flag_relative
2586{
2587    my ($linksarrayref) = @_;
2588
2589    # Before this step is:
2590    # destination=program/libsalhelperC52.so.3, this will be the name of the link
2591    # destinationfile=program/libsalhelperC52.so.3, this will be the linked file or name
2592    # If the flag RELATIVE is set, the paths have to be analyzed. If the flag is not set
2593    # (this will not occur in the future?) destinationfile has to be an absolute path name
2594
2595    for ( my $i = 0; $i <= $#{$linksarrayref}; $i++ )
2596    {
2597        my $onelink = ${$linksarrayref}[$i];
2598        my $styles = $onelink->{'Styles'};
2599
2600        if ( $styles =~ /\bRELATIVE\b/ )
2601        {
2602            # ToDo: This is only a simple not sufficient mechanism
2603
2604            my $destination = $onelink->{'destination'};
2605            my $destinationfile = $onelink->{'destinationfile'};
2606
2607            my $destinationpath = $destination;
2608
2609            installer::pathanalyzer::get_path_from_fullqualifiedname(\$destinationpath);
2610
2611            my $destinationfilepath = $destinationfile;
2612
2613            # it is possible, that the destinationfile is no longer part of the files collector
2614            if ($destinationfilepath) { installer::pathanalyzer::get_path_from_fullqualifiedname(\$destinationfilepath); }
2615            else { $destinationfilepath = ""; }
2616
2617            if ( $destinationpath eq $destinationfilepath )
2618            {
2619                # link and file are in the same directory
2620                # Therefore the path of the file can be removed
2621
2622                my $newdestinationfile = $destinationfile;
2623                installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$newdestinationfile);
2624
2625                $onelink->{'destinationfile'} = $newdestinationfile;
2626            }
2627        }
2628    }
2629}
2630
2631########################################################################
2632# This function is a helper of function "assigning_modules_to_items"
2633########################################################################
2634
2635sub insert_for_item ($$$)
2636{
2637    my ($hash, $item, $id) = @_;
2638
2639    # print STDERR "insert '$id' for '$item'\n";
2640    if (!defined $hash->{$item})
2641    {
2642        my @gids = ();
2643        $hash->{$item} = \@gids;
2644    }
2645    my $gid_list = $hash->{$item};
2646    push @{$gid_list}, $id;
2647    $hash->{$item} = $gid_list;
2648}
2649
2650sub build_modulegids_table ($$)
2651{
2652    my ($modulesref, $itemname) = @_;
2653
2654    my %module_lookup_table = ();
2655
2656    # build map of item names to list of respective module gids
2657    # containing these items
2658    foreach my $onemodule (@$modulesref)
2659    {
2660        next if ! defined $onemodule->{$itemname};
2661
2662        # these are the items contained in this module
2663        # e.g. Files = (gid_a_b_c,gid_d_e_f)
2664        my $module_gids = $onemodule->{$itemname};
2665
2666        # prune outer brackets
2667        $module_gids =~ s|^\s*\(||g;
2668        $module_gids =~ s|\)\s*$||g;
2669        for my $id (split (/,/, $module_gids))
2670        {
2671            chomp $id;
2672            insert_for_item(\%module_lookup_table, lc ($id), $onemodule->{'gid'});
2673        }
2674    }
2675
2676    return \%module_lookup_table;
2677}
2678
2679########################################################################
2680# Items like files do not know their modules
2681# This function is a helper of function "assigning_modules_to_items"
2682########################################################################
2683
2684sub get_string_of_modulegids_for_itemgid ($$)
2685{
2686    my ($module_lookup_table, $itemgid) = @_;
2687
2688    my $haslanguagemodule = 0;
2689    my %foundmodules = ();
2690
2691    my $gid_list = $module_lookup_table->{lc($itemgid)};
2692
2693    foreach my $gid (@$gid_list)
2694    {
2695        $foundmodules{$gid} = 1;
2696        # Is this module a language module? This info should be stored at the file.
2697        if ( exists($installer::globals::alllangmodules{$gid}) )
2698        {
2699            $haslanguagemodule = 1;
2700        }
2701    }
2702
2703    my $allmodules = join(",", keys %foundmodules);
2704
2705    # Check: All modules or no module must have flag LANGUAGEMODULE
2706    if ( $haslanguagemodule )
2707    {
2708        my $isreallylanguagemodule = installer::worker::key_in_a_is_also_key_in_b(
2709            \%foundmodules,
2710            \%installer::globals::alllangmodules);
2711        if ( ! $isreallylanguagemodule )
2712        {
2713            installer::exiter::exit_program(
2714                sprintf(
2715                    "ERROR: \"%s\" is assigned to modules with flag "
2716                    ."\"LANGUAGEMODULE\" and also to modules without this flag! Modules: %s",
2717                    $itemgid,
2718                    $allmodules),
2719                "get_string_of_modulegids_for_itemgid");
2720        }
2721    }
2722
2723    return ($allmodules, $haslanguagemodule);
2724}
2725
2726########################################################
2727# Items like files do not know their modules
2728# This function add the {'modules'} to these items
2729########################################################
2730
2731sub assigning_modules_to_items
2732{
2733    my ($modulesref, $itemsref, $itemname) = @_;
2734
2735    my $languageassignmenterror = 0;
2736    my @languageassignmenterrors = ();
2737
2738    my $module_lookup_table = build_modulegids_table($modulesref, $itemname);
2739
2740    for my $oneitem (@{$itemsref})
2741    {
2742        my $itemgid = $oneitem->{'gid'};
2743
2744        my $styles = "";
2745        if ( $oneitem->{'Styles'} ) { $styles = $oneitem->{'Styles'}; }
2746        if (( $itemname eq "Dirs" ) && ( ! ( $styles =~ /\bCREATE\b/ ))) { next; }
2747
2748        if ( $itemgid eq "" )
2749        {
2750            installer::exiter::exit_program(
2751                sprintf("ERROR in item collection: No gid for item %s", $oneitem->{'Name'}),
2752                "assigning_modules_to_items");
2753        }
2754
2755        # every item can belong to many modules
2756
2757        my ($modulegids, $haslanguagemodule) = get_string_of_modulegids_for_itemgid(
2758            $module_lookup_table,
2759            $itemgid);
2760
2761        if ($modulegids eq "")
2762        {
2763            installer::exiter::exit_program(
2764                sprintf("ERROR in file collection: No module found for %s %s",
2765                    $itemname,
2766                    $itemgid),
2767                "assigning_modules_to_items");
2768        }
2769
2770        $oneitem->{'modules'} = $modulegids;
2771        $oneitem->{'haslanguagemodule'} = $haslanguagemodule;
2772
2773        # Important check: "ismultilingual" and "haslanguagemodule" must have the same value !
2774        if ($oneitem->{'ismultilingual'} && ! $oneitem->{'haslanguagemodule'})
2775        {
2776            my $infoline = sprintf(
2777                "Error: \"%s\" is multi lingual, but not in language pack (Assigned module: %s)\n",
2778                $oneitem->{'gid'},
2779                $modulegids);
2780            $installer::logger::Global->print($infoline);
2781            push(@languageassignmenterrors, $infoline);
2782            $languageassignmenterror = 1;
2783        }
2784        elsif ($oneitem->{'haslanguagemodule'} && ! $oneitem->{'ismultilingual'})
2785        {
2786            my $infoline = sprintf(
2787                "Error: \"%s\" is in language pack, but not multi lingual (Assigned module: %s)\n",
2788                $oneitem->{'gid'},
2789                $modulegids);
2790            $installer::logger::Global->print($infoline);
2791            push(@languageassignmenterrors, $infoline);
2792            $languageassignmenterror = 1;
2793        }
2794    }
2795
2796    if ($languageassignmenterror)
2797    {
2798        for ( my $i = 0; $i <= $#languageassignmenterrors; $i++ ) { print "$languageassignmenterrors[$i]"; }
2799        installer::exiter::exit_program("ERROR: Incorrect assignments for language packs.", "assigning_modules_to_items");
2800    }
2801
2802}
2803
2804#################################################################################################
2805# Root path (for instance /opt/openofficeorg20) needs to be added to directories, files and links
2806#################################################################################################
2807
2808sub add_rootpath_to_directories
2809{
2810    my ($dirsref, $rootpath) = @_;
2811
2812    for ( my $i = 0; $i <= $#{$dirsref}; $i++ )
2813    {
2814        my $onedir = ${$dirsref}[$i];
2815        my $dir = "";
2816
2817        if ( $onedir->{'Dir'} ) { $dir = $onedir->{'Dir'}; }
2818
2819        if (!($dir =~ /\bPREDEFINED_/ ))
2820        {
2821            my $hostname = $onedir->{'HostName'};
2822            $hostname = $rootpath . $installer::globals::separator . $hostname;
2823            $onedir->{'HostName'} = $hostname;
2824        }
2825
2826        # added
2827
2828        if ( $dir =~ /\bPREDEFINED_PROGDIR\b/ )
2829        {
2830            my $hostname = $onedir->{'HostName'};
2831            if ( $hostname eq "" ) { $onedir->{'HostName'} = $rootpath; }
2832            else { $onedir->{'HostName'} = $rootpath . $installer::globals::separator . $hostname; }
2833        }
2834    }
2835}
2836
2837sub add_rootpath_to_files
2838{
2839    my ($filesref, $rootpath) = @_;
2840
2841    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
2842    {
2843        my $onefile = ${$filesref}[$i];
2844        my $destination = $onefile->{'destination'};
2845        $destination = $rootpath . $installer::globals::separator . $destination;
2846        $onefile->{'destination'} = $destination;
2847    }
2848}
2849
2850sub add_rootpath_to_links
2851{
2852    my ($linksref, $rootpath) = @_;
2853
2854    for ( my $i = 0; $i <= $#{$linksref}; $i++ )
2855    {
2856        my $onelink = ${$linksref}[$i];
2857        my $styles = $onelink->{'Styles'};
2858
2859        my $destination = $onelink->{'destination'};
2860        $destination = $rootpath . $installer::globals::separator . $destination;
2861        $onelink->{'destination'} = $destination;
2862
2863        if (!($styles =~ /\bRELATIVE\b/ )) # for absolute links
2864        {
2865            my $destinationfile = $onelink->{'destinationfile'};
2866            $destinationfile = $rootpath . $installer::globals::separator . $destinationfile;
2867            $onelink->{'destinationfile'} = $destinationfile;
2868        }
2869    }
2870}
2871
2872#################################################################################
2873# Collecting all parent gids
2874#################################################################################
2875
2876sub collect_all_parent_feature
2877{
2878    my ($modulesref) = @_;
2879
2880    my @allparents = ();
2881
2882    my $found_root_module = 0;
2883
2884    for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
2885    {
2886        my $onefeature = ${$modulesref}[$i];
2887
2888        my $parentgid = "";
2889        if ( $onefeature->{'ParentID'} )
2890        {
2891            $parentgid = $onefeature->{'ParentID'};
2892        }
2893
2894        if ( $parentgid ne "" )
2895        {
2896            if (! installer::existence::exists_in_array($parentgid, \@allparents))
2897            {
2898                push(@allparents, $parentgid);
2899            }
2900        }
2901
2902        # Setting the global root module
2903
2904        if ( $parentgid eq "" )
2905        {
2906            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"); }
2907            $installer::globals::rootmodulegid = $onefeature->{'gid'};
2908            $found_root_module = 1;
2909            $installer::logger::Global->printf("Setting Root Module: %s\n", $installer::globals::rootmodulegid);
2910        }
2911
2912        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"); }
2913
2914    }
2915
2916    return \@allparents;
2917}
2918
2919#################################################################################
2920# Checking for every feature, whether it has children
2921#################################################################################
2922
2923sub set_children_flag
2924{
2925    my ($modulesref) = @_;
2926
2927    my $allparents = collect_all_parent_feature($modulesref);
2928
2929    for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
2930    {
2931        my $onefeature = ${$modulesref}[$i];
2932        my $gid = $onefeature->{'gid'};
2933
2934        # is this gid a parent?
2935
2936        if ( installer::existence::exists_in_array($gid, $allparents) )
2937        {
2938            $onefeature->{'has_children'} = 1;
2939        }
2940        else
2941        {
2942            $onefeature->{'has_children'} = 0;
2943        }
2944    }
2945}
2946
2947#################################################################################
2948# All modules, that use a template module, do now get the assignments of
2949# the template module.
2950#################################################################################
2951
2952sub resolve_assigned_modules
2953{
2954    my ($modulesref) = @_;
2955
2956    # collecting all template modules
2957
2958    my %directaccess = ();
2959
2960    for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
2961    {
2962        my $onefeature = ${$modulesref}[$i];
2963        my $styles = "";
2964        if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; }
2965        if ( $styles =~ /\bTEMPLATEMODULE\b/ ) { $directaccess{$onefeature->{'gid'}} = $onefeature; }
2966
2967        # also looking for module with flag ROOT_BRAND_PACKAGE, to save is for further usage
2968        if ( $styles =~ /\bROOT_BRAND_PACKAGE\b/ )
2969        {
2970            $installer::globals::rootbrandpackage = $onefeature->{'gid'};
2971            $installer::globals::rootbrandpackageset = 1;
2972        }
2973    }
2974
2975    # looking, where template modules are assigned
2976
2977    for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
2978    {
2979        my $onefeature = ${$modulesref}[$i];
2980        if ( $onefeature->{'Assigns'} )
2981        {
2982            my $templategid = $onefeature->{'Assigns'};
2983
2984            if ( ! exists($directaccess{$templategid}) )
2985            {
2986                installer::exiter::exit_program("ERROR: Did not find definition of assigned template module \"$templategid\"", "resolve_assigned_modules");
2987            }
2988
2989            # Currently no merging of Files, Dirs, ...
2990            # This has to be included here, if it is required
2991            my $item;
2992            foreach $item (@installer::globals::items_at_modules)
2993            {
2994                if ( exists($directaccess{$templategid}->{$item}) ) { $onefeature->{$item} = $directaccess{$templategid}->{$item}; }
2995            }
2996        }
2997    }
2998}
2999
3000#################################################################################
3001# Removing the template modules from the list, after all
3002# assignments are transferred to the "real" modules.
3003#################################################################################
3004
3005sub remove_template_modules
3006{
3007    my ($modulesref) = @_;
3008
3009    my @modules = ();
3010
3011    for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
3012    {
3013        my $onefeature = ${$modulesref}[$i];
3014        my $styles = "";
3015        if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; }
3016        if ( $styles =~ /\bTEMPLATEMODULE\b/ ) { next; }
3017
3018        push(@modules, $onefeature);
3019    }
3020
3021    return \@modules;
3022}
3023
3024#################################################################################
3025# Collecting all modules with flag LANGUAGEMODULE in a global
3026# collector.
3027#################################################################################
3028
3029sub collect_all_languagemodules
3030{
3031    my ($modulesref) = @_;
3032
3033    for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
3034    {
3035        my $onefeature = ${$modulesref}[$i];
3036        my $styles = "";
3037        if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; }
3038        if ( $styles =~ /\bLANGUAGEMODULE\b/ )
3039        {
3040            if ( ! exists($onefeature->{'Language'}) ) { installer::exiter::exit_program("ERROR: \"$onefeature->{'gid'}\" has flag LANGUAGEMODULE, but does not know its language!", "collect_all_languagemodules"); }
3041            $installer::globals::alllangmodules{$onefeature->{'gid'}} = $onefeature->{'Language'};
3042            # Collecting also the English names, that are used for NSIS unpack directory for language packs
3043            my $lang = $onefeature->{'Language'};
3044            my $name = "";
3045            foreach my $localkey ( keys %{$onefeature} )
3046            {
3047                if ( $localkey =~ /^\s*Name\s*\(\s*en-US\s*\)\s*$/ )
3048                {
3049                    $installer::globals::all_english_languagestrings{$lang} = $onefeature->{$localkey};
3050                }
3051            }
3052        }
3053    }
3054}
3055
3056#################################################################################
3057# Selecting from all collected English language strings those, that are really
3058# required in this installation set.
3059#################################################################################
3060
3061sub select_required_language_strings
3062{
3063    my ($modulesref) = @_;
3064
3065    for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
3066    {
3067        my $onefeature = ${$modulesref}[$i];
3068        my $styles = "";
3069        if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; }
3070        if ( $styles =~ /\bLANGUAGEMODULE\b/ )
3071        {
3072            if ( ! exists($onefeature->{'Language'}) ) { installer::exiter::exit_program("ERROR: \"$onefeature->{'gid'}\" has flag LANGUAGEMODULE, but does not know its language!", "select_required_language_strings"); }
3073            my $lang = $onefeature->{'Language'};
3074
3075            if (( exists($installer::globals::all_english_languagestrings{$lang}) ) && ( ! exists($installer::globals::all_required_english_languagestrings{$lang}) ))
3076            {
3077                $installer::globals::all_required_english_languagestrings{$lang} = $installer::globals::all_english_languagestrings{$lang};
3078            }
3079        }
3080    }
3081}
3082
3083#####################################################################################
3084# Unixlinks are not always required. For Linux RPMs and Solaris Packages they are
3085# created dynamically. Exception: For package formats "installed" or "archive".
3086# In scp2 this unixlinks have the flag LAYERLINK.
3087#####################################################################################
3088
3089sub filter_layerlinks_from_unixlinks
3090{
3091    my ( $unixlinksref ) = @_;
3092
3093    my @alllinks = ();
3094
3095    for ( my $i = 0; $i <= $#{$unixlinksref}; $i++ )
3096    {
3097        my $isrequired = 1;
3098
3099        my $onelink = ${$unixlinksref}[$i];
3100        my $styles = "";
3101        if ( $onelink->{'Styles'} ) { $styles = $onelink->{'Styles'}; }
3102
3103        if ( $styles =~ /\bLAYERLINK\b/ )
3104        {
3105            # Platforms, that do not need the layer links
3106            if (( $installer::globals::islinuxrpmbuild ) || ( $installer::globals::issolarispkgbuild ))
3107            {
3108                $isrequired = 0;
3109            }
3110
3111            # Package formats, that need the layer link (platform independent)
3112            if (( $installer::globals::packageformat eq "installed" ) || ( $installer::globals::packageformat eq "archive" ))
3113            {
3114                $isrequired = 1;
3115            }
3116        }
3117
3118        if ( $isrequired ) { push(@alllinks, $onelink); }
3119    }
3120
3121    return \@alllinks;
3122}
3123
3124
3125
3126
3127=head2 print_script_item($item)
3128
3129    For debugging.
3130    Print the contents of the given script item to $installer::logger::Lang.
3131
3132=cut
3133sub print_script_item ($)
3134{
3135    my ($item) = @_;
3136
3137    $installer::logger::Lang->printf("script item %s\n", $item->{'uniquename'});
3138    foreach my $key (sort keys %$item)
3139    {
3140        my $value = $item->{$key};
3141        $value = "<undef>" unless defined $value;
3142        $installer::logger::Lang->printf("    %20s -> %s\n", $key, $value);
3143    }
3144}
3145
3146
31471;
3148