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