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