xref: /AOO41X/main/solenv/bin/modules/installer/windows/directory.pm (revision 4bfbcde8d64cc5d114df10dce4a9ed79eff32278)
1#**************************************************************
2#
3#  Licensed to the Apache Software Foundation (ASF) under one
4#  or more contributor license agreements.  See the NOTICE file
5#  distributed with this work for additional information
6#  regarding copyright ownership.  The ASF licenses this file
7#  to you under the Apache License, Version 2.0 (the
8#  "License"); you may not use this file except in compliance
9#  with the License.  You may obtain a copy of the License at
10#
11#    http://www.apache.org/licenses/LICENSE-2.0
12#
13#  Unless required by applicable law or agreed to in writing,
14#  software distributed under the License is distributed on an
15#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16#  KIND, either express or implied.  See the License for the
17#  specific language governing permissions and limitations
18#  under the License.
19#
20#**************************************************************
21
22
23
24package installer::windows::directory;
25
26use installer::exiter;
27use installer::files;
28use installer::globals;
29use installer::pathanalyzer;
30use installer::windows::idtglobal;
31use installer::windows::msiglobal;
32
33##############################################################
34# Collecting all directory trees in global hash
35##############################################################
36
37sub collectdirectorytrees
38{
39    my ( $directoryref ) = @_;
40
41    for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
42    {
43        my $onedir = ${$directoryref}[$i];
44        my $styles = "";
45        if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; }
46
47        if ( $styles ne "" )
48        {
49            foreach my $treestyle ( keys %installer::globals::treestyles )
50            {
51                if ( $styles =~ /\b$treestyle\b/ )
52                {
53                    my $hostname = $onedir->{'HostName'};
54                    # -> hostname is the key, the style the value!
55                    $installer::globals::hostnametreestyles{$hostname} = $treestyle;
56                }
57            }
58        }
59    }
60}
61
62##############################################################
63# Overwriting global programfilesfolder, if required
64##############################################################
65
66sub overwrite_programfilesfolder
67{
68    my ( $allvariables ) = @_;
69
70    if ( $allvariables->{'PROGRAMFILESFOLDERNAME'} )
71    {
72        $installer::globals::programfilesfolder = $allvariables->{'PROGRAMFILESFOLDERNAME'};
73    }
74}
75
76##############################################################
77# Maximum length of directory name is 72.
78# Taking care of underlines, which are the separator.
79##############################################################
80
81sub make_short_dir_version
82{
83    my ($longstring) = @_;
84
85    my $shortstring = "";
86    my $cutlength = 60;
87    my $length = 5; # So the directory can still be recognized
88    my $longstring_save = $longstring;
89
90    # Splitting the string at each "underline" and allowing only $length characters per directory name.
91    # Checking also uniqueness and length.
92
93    my $stringarray = installer::converter::convert_stringlist_into_array_without_newline(\$longstring, "_");
94
95    foreach my $onestring ( @{$stringarray} )
96    {
97        my $partstring = "";
98
99        if ( $onestring =~ /\-/ )
100        {
101            my $localstringarray = installer::converter::convert_stringlist_into_array_without_newline(\$onestring, "-");
102            foreach my $onelocalstring ( @{$localstringarray} )
103            {
104                if ( length($onelocalstring) > $length ) { $onelocalstring = substr($onelocalstring, 0, $length); }
105                $partstring = $partstring . "-" . $onelocalstring;
106            }
107            $partstring =~ s/^\s*\-//;
108        }
109        else
110        {
111            if ( length($onestring) > $length ) { $partstring = substr($onestring, 0, $length); }
112            else { $partstring = $onestring; }
113        }
114
115        $shortstring = $shortstring . "_" . $partstring;
116    }
117
118    $shortstring =~ s/^\s*\_//;
119
120    # Setting unique ID to each directory
121    # No counter allowed, process must be absolute reproducable due to patch creation process.
122
123    # chomp(my $id = `echo $longstring_save | md5sum | sed -e "s/ .*//g"`);  # Very, very slow
124    # my $subid = substr($id, 0, 9); # taking only the first 9 digits
125
126    my $subid = installer::windows::msiglobal::calculate_id($longstring_save, 9); # taking only the first 9 digits
127
128    if ( length($shortstring) > $cutlength ) { $shortstring = substr($shortstring, 0, $cutlength); }
129
130    $shortstring = $shortstring . "_" . $subid;
131
132    return $shortstring;
133}
134
135##############################################################
136# Adding unique directory names to the directory collection
137##############################################################
138
139sub create_unique_directorynames
140{
141    my ($directoryref, $allvariables) = @_;
142
143    $installer::globals::officeinstalldirectoryset = 0;
144
145    my %completedirhashstep1 = ();
146    my %shortdirhash = ();
147    my %shortdirhashreverse = ();
148    my $infoline = "";
149    my $errorcount = 0;
150
151    for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
152    {
153        my $onedir = ${$directoryref}[$i];
154        my $uniquename = $onedir->{'HostName'};
155
156        my $styles = "";
157        if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; }
158
159        $uniquename =~ s/^\s*//g;               # removing beginning white spaces
160        $uniquename =~ s/\s*$//g;               # removing ending white spaces
161        $uniquename =~ s/\s//g;                 # removing white spaces
162        $uniquename =~ s/\_//g;                 # removing existing underlines
163        $uniquename =~ s/\.//g;                 # removing dots in directoryname
164        $uniquename =~ s/OpenOffice/OO/g;
165
166        $uniquename =~ s/\Q$installer::globals::separator\E/\_/g;   # replacing slash and backslash with underline
167
168        $uniquename =~ s/_registry/_rgy/g;
169        $uniquename =~ s/_registration/_rgn/g;
170        $uniquename =~ s/_extension/_ext/g;
171        $uniquename =~ s/_frame/_frm/g;
172        $uniquename =~ s/_table/_tbl/g;
173        $uniquename =~ s/_chart/_crt/g;
174
175        # The names after this small changes must still be unique!
176        if ( exists($completedirhashstep1{$uniquename}) ) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 1): \"$uniquename\".", "create_unique_directorynames"); }
177        $completedirhashstep1{$uniquename} = 1;
178
179        # Starting to make unique name for the parent and its directory
180        my $originaluniquename = $uniquename;
181
182        $uniquename = make_short_dir_version($uniquename);
183
184        # Checking if the same directory already exists, but has another short version.
185        if (( exists($shortdirhash{$originaluniquename}) ) && ( $shortdirhash{$originaluniquename} ne $uniquename )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 2A): \"$uniquename\".", "create_unique_directorynames"); }
186
187        # Also checking vice versa
188        # Checking if the same short directory already exists, but has another long version.
189        if (( exists($shortdirhashreverse{$uniquename}) ) && ( $shortdirhashreverse{$uniquename} ne $originaluniquename )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 2B): \"$uniquename\".", "create_unique_directorynames"); }
190
191        # Creating assignment from long to short directory names
192        $shortdirhash{$originaluniquename} = $uniquename;
193        $shortdirhashreverse{$uniquename} = $originaluniquename;
194
195        # Important: The unique parent is generated from the string $originaluniquename (with the use of underlines).
196
197        my $uniqueparentname = $originaluniquename;
198        my $keepparent = 1;
199
200        if ( $uniqueparentname =~ /^\s*(.*)\_(.*?)\s*$/ )   # the underline is now the separator
201        {
202            $uniqueparentname = $1;
203            $keepparent = 0;
204        }
205        else
206        {
207            $uniqueparentname = $installer::globals::programfilesfolder;
208            $keepparent = 1;
209        }
210
211        if ( $styles =~ /\bPROGRAMFILESFOLDER\b/ )
212        {
213            $uniqueparentname = $installer::globals::programfilesfolder;
214            $keepparent = 1;
215        }
216        if ( $styles =~ /\bCOMMONFILESFOLDER\b/ )
217        {
218            $uniqueparentname = $installer::globals::commonfilesfolder;
219            $keepparent = 1;
220        }
221        if ( $styles =~ /\bCOMMONAPPDATAFOLDER\b/ )
222        {
223            $uniqueparentname = $installer::globals::commonappdatafolder;
224            $keepparent = 1;
225        }
226        if ( $styles =~ /\bLOCALAPPDATAFOLDER\b/ )
227        {
228            $uniqueparentname = $installer::globals::localappdatafolder;
229            $keepparent = 1;
230        }
231
232        if ( $styles =~ /\bSHAREPOINTPATH\b/ )
233        {
234            $uniqueparentname = "SHAREPOINTPATH";
235            $installer::globals::usesharepointpath = 1;
236            $keepparent = 1;
237        }
238
239        # also setting short directory name for the parent
240
241        my $originaluniqueparentname = $uniqueparentname;
242
243        if ( ! $keepparent )
244        {
245            $uniqueparentname = make_short_dir_version($uniqueparentname);
246        }
247
248        # Again checking if the same directory already exists, but has another short version.
249        if (( exists($shortdirhash{$originaluniqueparentname}) ) && ( $shortdirhash{$originaluniqueparentname} ne $uniqueparentname )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 3A): \"$uniqueparentname\".", "create_unique_directorynames"); }
250
251        # Also checking vice versa
252        # Checking if the same short directory already exists, but has another long version.
253        if (( exists($shortdirhashreverse{$uniqueparentname}) ) && ( $shortdirhashreverse{$uniqueparentname} ne $originaluniqueparentname )) { installer::exiter::exit_program("ERROR: Error in packaging process. Unallowed modification of directory name, not unique (step 3B): \"$uniqueparentname\".", "create_unique_directorynames"); }
254
255        $shortdirhash{$originaluniqueparentname} = $uniqueparentname;
256        $shortdirhashreverse{$uniqueparentname} = $originaluniqueparentname;
257
258        # Hyphen not allowed in database
259        $uniquename =~ s/\-/\_/g;           # making "-" to "_"
260        $uniqueparentname =~ s/\-/\_/g;     # making "-" to "_"
261
262        # And finally setting the values for the directories
263        $onedir->{'uniquename'} = $uniquename;
264        $onedir->{'uniqueparentname'} = $uniqueparentname;
265
266        # setting the installlocation directory
267        if ( $styles =~ /\bISINSTALLLOCATION\b/ )
268        {
269            if ( $installer::globals::installlocationdirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag ISINSTALLLOCATION alread set: \"$installer::globals::installlocationdirectory\".", "create_unique_directorynames"); }
270            $installer::globals::installlocationdirectory = $uniquename;
271            $installer::globals::installlocationdirectoryset = 1;
272            if ( $installer::globals::installlocationdirectory =~ /oracle_/i ) { $installer::globals::sundirexists = 1; }
273        }
274
275        # setting the sundirectory
276        if ( $styles =~ /\bSUNDIRECTORY\b/ )
277        {
278            if ( $installer::globals::vendordirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag SUNDIRECTORY alread set: \"$installer::globals::vendordirectory\".", "create_unique_directorynames"); }
279            $installer::globals::vendordirectory = $uniquename;
280            $installer::globals::vendordirectoryset = 1;
281        }
282    }
283}
284
285#####################################################
286# Adding ":." to selected default directory names
287#####################################################
288
289sub check_sourcedir_addon
290{
291    my ( $onedir, $allvariableshashref ) = @_;
292
293    if (($installer::globals::addchildprojects) ||
294        ($installer::globals::patch) ||
295        ($installer::globals::languagepack) ||
296        ($allvariableshashref->{'CHANGETARGETDIR'}))
297    {
298        my $sourcediraddon = "\:\.";
299        $onedir->{'defaultdir'} = $onedir->{'defaultdir'} . $sourcediraddon;
300    }
301
302}
303
304#####################################################
305# The directory with the style ISINSTALLLOCATION
306# will be replaced by INSTALLLOCATION
307#####################################################
308
309sub set_installlocation_directory
310{
311    my ( $directoryref, $allvariableshashref ) = @_;
312
313    if ( ! $installer::globals::installlocationdirectoryset ) { installer::exiter::exit_program("ERROR: Directory with flag ISINSTALLLOCATION not set!", "set_installlocation_directory"); }
314
315    for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
316    {
317        my $onedir = ${$directoryref}[$i];
318
319        if ( $onedir->{'uniquename'} eq $installer::globals::installlocationdirectory )
320        {
321            $onedir->{'uniquename'} = "INSTALLLOCATION";
322            check_sourcedir_addon($onedir, $allvariableshashref);
323        }
324
325        if ( $onedir->{'uniquename'} eq $installer::globals::vendordirectory )
326        {
327            check_sourcedir_addon($onedir, $allvariableshashref);
328        }
329
330        if ( $onedir->{'uniqueparentname'} eq $installer::globals::installlocationdirectory )
331        {
332            $onedir->{'uniqueparentname'} = "INSTALLLOCATION";
333        }
334    }
335}
336
337#####################################################
338# Getting the name of the top level directory. This
339# can have only one letter
340#####################################################
341
342sub get_last_directory_name
343{
344    my ($completepathref) = @_;
345
346    if ( $$completepathref =~ /^.*[\/\\](.+?)\s*$/ )
347    {
348        $$completepathref = $1;
349    }
350}
351
352#####################################################
353# Creating the defaultdir for the file Director.idt
354#####################################################
355
356sub create_defaultdir_directorynames
357{
358    my ($directoryref, $shortdirnamehashref) = @_;
359
360    my @shortnames = ();
361    if ( $installer::globals::updatedatabase ) { @shortnames = values(%{$shortdirnamehashref}); }
362    elsif ( $installer::globals::prepare_winpatch ) { @shortnames = values(%installer::globals::saved83dirmapping); }
363
364    for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
365    {
366        my $onedir = ${$directoryref}[$i];
367        my $hostname = $onedir->{'HostName'};
368
369        $hostname =~ s/\Q$installer::globals::separator\E\s*$//;
370        get_last_directory_name(\$hostname);
371        # installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$hostname); # making program/classes to classes
372        my $uniquename = $onedir->{'uniquename'};
373        my $shortstring;
374        if (( $installer::globals::updatedatabase ) && ( exists($shortdirnamehashref->{$uniquename}) ))
375        {
376            $shortstring = $shortdirnamehashref->{$uniquename};
377        }
378        elsif (( $installer::globals::prepare_winpatch ) && ( exists($installer::globals::saved83dirmapping{$uniquename}) ))
379        {
380            $shortstring = $installer::globals::saved83dirmapping{$uniquename};
381        }
382        else
383        {
384            $shortstring = installer::windows::idtglobal::make_eight_three_conform($hostname, "dir", \@shortnames);
385        }
386
387        my $defaultdir;
388
389        if ( $shortstring eq $hostname )
390        {
391            $defaultdir = $hostname;
392        }
393        else
394        {
395            $defaultdir = $shortstring . "|" . $hostname;
396        }
397
398        $onedir->{'defaultdir'} = $defaultdir;
399
400        my $fontdir = "";
401        if ( $onedir->{'Dir'} ) { $fontdir = $onedir->{'Dir'}; }
402
403        my $fontdefaultdir = "";
404        if ( $onedir->{'defaultdir'} ) { $fontdefaultdir = $onedir->{'defaultdir'}; }
405
406        if (( $fontdir eq "PREDEFINED_OSSYSTEMFONTDIR" ) && ( $fontdefaultdir eq $installer::globals::fontsdirhostname ))
407        {
408            $installer::globals::fontsdirname = $onedir->{'defaultdir'};
409            $installer::globals::fontsdirparent = $onedir->{'uniqueparentname'};
410        }
411    }
412}
413
414###############################################
415# Fill content into the directory table
416###############################################
417
418sub create_directorytable_from_collection
419{
420    my ($directorytableref, $directoryref) = @_;
421
422    for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
423    {
424        my $onedir = ${$directoryref}[$i];
425        my $hostname = $onedir->{'HostName'};
426        my $dir = "";
427
428        if ( $onedir->{'Dir'} ) { $dir = $onedir->{'Dir'}; }
429
430        if (( $dir eq "PREDEFINED_PROGDIR" ) && ( $hostname eq "" )) { next; }  # removing files from root directory
431
432        my $oneline = $onedir->{'uniquename'} . "\t" . $onedir->{'uniqueparentname'} . "\t" . $onedir->{'defaultdir'} . "\n";
433
434        push(@{$directorytableref}, $oneline);
435    }
436}
437
438###############################################
439# Defining the root installation structure
440###############################################
441
442sub add_root_directories
443{
444    my ($directorytableref, $allvariableshashref) = @_;
445
446#   my $sourcediraddon = "";
447#   if (($installer::globals::addchildprojects) ||
448#       ($installer::globals::patch) ||
449#       ($installer::globals::languagepack) ||
450#       ($allvariableshashref->{'CHANGETARGETDIR'}))
451#   {
452#       $sourcediraddon = "\:\.";
453#   }
454
455    my $oneline = "";
456
457    if (( ! $installer::globals::patch ) && ( ! $installer::globals::languagepack ) && ( ! $allvariableshashref->{'DONTUSESTARTMENUFOLDER'} ))
458    {
459        my $productname = $allvariableshashref->{'PRODUCTNAME'};
460        my $productversion = $allvariableshashref->{'PRODUCTVERSION'};
461        my $baseproductversion = $productversion;
462
463        if (( $installer::globals::prepare_winpatch ) && ( $allvariableshashref->{'BASEPRODUCTVERSION'} ))
464        {
465            $baseproductversion = $allvariableshashref->{'BASEPRODUCTVERSION'};  # for example "2.0" for OOo
466        }
467
468        my $realproductkey = $productname . " " . $productversion;
469        my $productkey = $productname . " " . $baseproductversion;
470
471        if (( $allvariableshashref->{'POSTVERSIONEXTENSION'} ) && ( ! $allvariableshashref->{'DONTUSEEXTENSIONINDEFAULTDIR'} ))
472        {
473            $productkey = $productkey . " " . $allvariableshashref->{'POSTVERSIONEXTENSION'};
474            $realproductkey = $realproductkey . " " . $allvariableshashref->{'POSTVERSIONEXTENSION'};
475        }
476        if ( $allvariableshashref->{'NOVERSIONINDIRNAME'} )
477        {
478            $productkey = $productname;
479            $realproductkey = $realproductname;
480        }
481        if ( $allvariableshashref->{'NOSPACEINDIRECTORYNAME'} )
482        {
483            $productkey =~ s/\ /\_/g;
484            $realproductkey =~ s/\ /\_/g;
485        }
486
487        my $shortproductkey = installer::windows::idtglobal::make_eight_three_conform($productkey, "dir");      # third parameter not used
488        $shortproductkey =~ s/\s/\_/g;                                  # changing empty space to underline
489
490        $oneline = "$installer::globals::officemenufolder\t$installer::globals::programmenufolder\t$shortproductkey|$realproductkey\n";
491        push(@{$directorytableref}, $oneline);
492    }
493
494    $oneline = "TARGETDIR\t\tSourceDir\n";
495    push(@{$directorytableref}, $oneline);
496
497    $oneline = "$installer::globals::programfilesfolder\tTARGETDIR\t.\n";
498    push(@{$directorytableref}, $oneline);
499
500    $oneline = "$installer::globals::programmenufolder\tTARGETDIR\t.\n";
501    push(@{$directorytableref}, $oneline);
502
503    $oneline = "$installer::globals::startupfolder\tTARGETDIR\t.\n";
504    push(@{$directorytableref}, $oneline);
505
506    $oneline = "$installer::globals::desktopfolder\tTARGETDIR\t.\n";
507    push(@{$directorytableref}, $oneline);
508
509    $oneline = "$installer::globals::startmenufolder\tTARGETDIR\t.\n";
510    push(@{$directorytableref}, $oneline);
511
512    $oneline = "$installer::globals::commonfilesfolder\tTARGETDIR\t.\n";
513    push(@{$directorytableref}, $oneline);
514
515    $oneline = "$installer::globals::commonappdatafolder\tTARGETDIR\t.\n";
516    push(@{$directorytableref}, $oneline);
517
518    $oneline = "$installer::globals::localappdatafolder\tTARGETDIR\t.\n";
519    push(@{$directorytableref}, $oneline);
520
521    if ( $installer::globals::usesharepointpath )
522    {
523        $oneline = "SHAREPOINTPATH\tTARGETDIR\t.\n";
524        push(@{$directorytableref}, $oneline);
525    }
526
527    $oneline = "$installer::globals::systemfolder\tTARGETDIR\t.\n";
528    push(@{$directorytableref}, $oneline);
529
530    my $localtemplatefoldername = $installer::globals::templatefoldername;
531    my $directorytableentry = $localtemplatefoldername;
532    my $shorttemplatefoldername = installer::windows::idtglobal::make_eight_three_conform($localtemplatefoldername, "dir");
533    if ( $shorttemplatefoldername ne $localtemplatefoldername ) { $directorytableentry = "$shorttemplatefoldername|$localtemplatefoldername"; }
534    $oneline = "$installer::globals::templatefolder\tTARGETDIR\t$directorytableentry\n";
535    push(@{$directorytableref}, $oneline);
536
537    if ( $installer::globals::fontsdirname )
538    {
539        $oneline = "$installer::globals::fontsfolder\t$installer::globals::fontsdirparent\t$installer::globals::fontsfoldername\:$installer::globals::fontsdirname\n";
540    }
541    else
542    {
543        $oneline = "$installer::globals::fontsfolder\tTARGETDIR\t$installer::globals::fontsfoldername\n";
544    }
545
546    push(@{$directorytableref}, $oneline);
547
548}
549
550###############################################
551# Creating the file Director.idt dynamically
552###############################################
553
554sub create_directory_table
555{
556    my ($directoryref, $basedir, $allvariableshashref, $shortdirnamehashref, $loggingdir) = @_;
557
558    # Structure of the directory table:
559    # Directory Directory_Parent DefaultDir
560    # Directory is a unique identifier
561    # Directory_Parent is the unique identifier of the parent
562    # DefaultDir is .:APPLIC~1|Application Data with
563    # Before ":" : [sourcedir]:[destdir] (not programmed yet)
564    # After ":" : 8+3 and not 8+3 the destination directory name
565
566    installer::logger::include_timestamp_into_logfile("Performance Info: Directory Table start");
567
568    my @directorytable = ();
569    my $infoline;
570
571    overwrite_programfilesfolder($allvariableshashref);
572    if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_1.log", $directoryref); }
573    create_unique_directorynames($directoryref, $allvariableshashref);
574    if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_1a.log", $directoryref); }
575    create_defaultdir_directorynames($directoryref, $shortdirnamehashref);  # only destdir!
576    if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_2.log", $directoryref); }
577    set_installlocation_directory($directoryref, $allvariableshashref);
578    if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_3.log", $directoryref); }
579    installer::windows::idtglobal::write_idt_header(\@directorytable, "directory");
580    add_root_directories(\@directorytable, $allvariableshashref);
581    create_directorytable_from_collection(\@directorytable, $directoryref);
582
583    # Saving the file
584
585    my $directorytablename = $basedir . $installer::globals::separator . "Director.idt";
586    installer::files::save_file($directorytablename ,\@directorytable);
587    $infoline = "Created idt file: $directorytablename\n";
588    push(@installer::globals::logfileinfo, $infoline);
589
590    installer::logger::include_timestamp_into_logfile("Performance Info: Directory Table end");
591
592}
593
5941;
595