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