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