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