xref: /AOO41X/main/solenv/bin/modules/installer/windows/directory.pm (revision bbb253301ccdaffebe330f798a35d3d1d3a9dd98)
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::prepare_winpatch ) { @shortnames = values(%installer::globals::saved83dirmapping); }
362
363    for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
364    {
365        my $onedir = ${$directoryref}[$i];
366        my $hostname = $onedir->{'HostName'};
367
368        $hostname =~ s/\Q$installer::globals::separator\E\s*$//;
369        get_last_directory_name(\$hostname);
370        # installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$hostname); # making program/classes to classes
371        my $uniquename = $onedir->{'uniquename'};
372        my $shortstring;
373        if (( $installer::globals::prepare_winpatch ) && ( exists($installer::globals::saved83dirmapping{$uniquename}) ))
374        {
375            $shortstring = $installer::globals::saved83dirmapping{$uniquename};
376        }
377        else
378        {
379            $shortstring = installer::windows::idtglobal::make_eight_three_conform($hostname, "dir", \@shortnames);
380        }
381
382        my $defaultdir;
383
384        if ( $shortstring eq $hostname )
385        {
386            $defaultdir = $hostname;
387        }
388        else
389        {
390            $defaultdir = $shortstring . "|" . $hostname;
391        }
392
393        $onedir->{'defaultdir'} = $defaultdir;
394
395        my $fontdir = "";
396        if ( $onedir->{'Dir'} ) { $fontdir = $onedir->{'Dir'}; }
397
398        my $fontdefaultdir = "";
399        if ( $onedir->{'defaultdir'} ) { $fontdefaultdir = $onedir->{'defaultdir'}; }
400
401        if (( $fontdir eq "PREDEFINED_OSSYSTEMFONTDIR" ) && ( $fontdefaultdir eq $installer::globals::fontsdirhostname ))
402        {
403            $installer::globals::fontsdirname = $onedir->{'defaultdir'};
404            $installer::globals::fontsdirparent = $onedir->{'uniqueparentname'};
405        }
406    }
407}
408
409###############################################
410# Fill content into the directory table
411###############################################
412
413sub create_directorytable_from_collection
414{
415    my ($directorytableref, $directoryref) = @_;
416
417    for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
418    {
419        my $onedir = ${$directoryref}[$i];
420        my $hostname = $onedir->{'HostName'};
421        my $dir = "";
422
423        if ( $onedir->{'Dir'} ) { $dir = $onedir->{'Dir'}; }
424
425        if (( $dir eq "PREDEFINED_PROGDIR" ) && ( $hostname eq "" )) { next; }  # removing files from root directory
426
427        my $oneline = $onedir->{'uniquename'} . "\t" . $onedir->{'uniqueparentname'} . "\t" . $onedir->{'defaultdir'} . "\n";
428
429        push(@{$directorytableref}, $oneline);
430    }
431}
432
433###############################################
434# Defining the root installation structure
435###############################################
436
437sub add_root_directories
438{
439    my ($directorytableref, $allvariableshashref) = @_;
440
441#   my $sourcediraddon = "";
442#   if (($installer::globals::addchildprojects) ||
443#       ($installer::globals::patch) ||
444#       ($installer::globals::languagepack) ||
445#       ($allvariableshashref->{'CHANGETARGETDIR'}))
446#   {
447#       $sourcediraddon = "\:\.";
448#   }
449
450    my $oneline = "";
451
452    if (( ! $installer::globals::patch ) && ( ! $installer::globals::languagepack ) && ( ! $allvariableshashref->{'DONTUSESTARTMENUFOLDER'} ))
453    {
454        my $productname = $allvariableshashref->{'PRODUCTNAME'};
455        my $productversion = $allvariableshashref->{'PRODUCTVERSION'};
456        my $baseproductversion = $productversion;
457
458        if (( $installer::globals::prepare_winpatch ) && ( $allvariableshashref->{'BASEPRODUCTVERSION'} ))
459        {
460            $baseproductversion = $allvariableshashref->{'BASEPRODUCTVERSION'};  # for example "2.0" for OOo
461        }
462
463        my $realproductkey = $productname . " " . $productversion;
464        my $productkey = $productname . " " . $baseproductversion;
465
466        if (( $allvariableshashref->{'POSTVERSIONEXTENSION'} ) && ( ! $allvariableshashref->{'DONTUSEEXTENSIONINDEFAULTDIR'} ))
467        {
468            $productkey = $productkey . " " . $allvariableshashref->{'POSTVERSIONEXTENSION'};
469            $realproductkey = $realproductkey . " " . $allvariableshashref->{'POSTVERSIONEXTENSION'};
470        }
471        if ( $allvariableshashref->{'NOVERSIONINDIRNAME'} )
472        {
473            $productkey = $productname;
474            $realproductkey = $realproductname;
475        }
476        if ( $allvariableshashref->{'NOSPACEINDIRECTORYNAME'} )
477        {
478            $productkey =~ s/\ /\_/g;
479            $realproductkey =~ s/\ /\_/g;
480        }
481
482        my $shortproductkey = installer::windows::idtglobal::make_eight_three_conform($productkey, "dir");      # third parameter not used
483        $shortproductkey =~ s/\s/\_/g;                                  # changing empty space to underline
484
485        $oneline = "$installer::globals::officemenufolder\t$installer::globals::programmenufolder\t$shortproductkey|$realproductkey\n";
486        push(@{$directorytableref}, $oneline);
487    }
488
489    $oneline = "TARGETDIR\t\tSourceDir\n";
490    push(@{$directorytableref}, $oneline);
491
492    $oneline = "$installer::globals::programfilesfolder\tTARGETDIR\t.\n";
493    push(@{$directorytableref}, $oneline);
494
495    $oneline = "$installer::globals::programmenufolder\tTARGETDIR\t.\n";
496    push(@{$directorytableref}, $oneline);
497
498    $oneline = "$installer::globals::startupfolder\tTARGETDIR\t.\n";
499    push(@{$directorytableref}, $oneline);
500
501    $oneline = "$installer::globals::desktopfolder\tTARGETDIR\t.\n";
502    push(@{$directorytableref}, $oneline);
503
504    $oneline = "$installer::globals::startmenufolder\tTARGETDIR\t.\n";
505    push(@{$directorytableref}, $oneline);
506
507    $oneline = "$installer::globals::commonfilesfolder\tTARGETDIR\t.\n";
508    push(@{$directorytableref}, $oneline);
509
510    $oneline = "$installer::globals::commonappdatafolder\tTARGETDIR\t.\n";
511    push(@{$directorytableref}, $oneline);
512
513    $oneline = "$installer::globals::localappdatafolder\tTARGETDIR\t.\n";
514    push(@{$directorytableref}, $oneline);
515
516    if ( $installer::globals::usesharepointpath )
517    {
518        $oneline = "SHAREPOINTPATH\tTARGETDIR\t.\n";
519        push(@{$directorytableref}, $oneline);
520    }
521
522    $oneline = "$installer::globals::systemfolder\tTARGETDIR\t.\n";
523    push(@{$directorytableref}, $oneline);
524
525    my $localtemplatefoldername = $installer::globals::templatefoldername;
526    my $directorytableentry = $localtemplatefoldername;
527    my $shorttemplatefoldername = installer::windows::idtglobal::make_eight_three_conform($localtemplatefoldername, "dir");
528    if ( $shorttemplatefoldername ne $localtemplatefoldername ) { $directorytableentry = "$shorttemplatefoldername|$localtemplatefoldername"; }
529    $oneline = "$installer::globals::templatefolder\tTARGETDIR\t$directorytableentry\n";
530    push(@{$directorytableref}, $oneline);
531
532    if ( $installer::globals::fontsdirname )
533    {
534        $oneline = "$installer::globals::fontsfolder\t$installer::globals::fontsdirparent\t$installer::globals::fontsfoldername\:$installer::globals::fontsdirname\n";
535    }
536    else
537    {
538        $oneline = "$installer::globals::fontsfolder\tTARGETDIR\t$installer::globals::fontsfoldername\n";
539    }
540
541    push(@{$directorytableref}, $oneline);
542
543}
544
545###############################################
546# Creating the file Director.idt dynamically
547###############################################
548
549sub create_directory_table
550{
551    my ($directoryref, $basedir, $allvariableshashref, $shortdirnamehashref, $loggingdir) = @_;
552
553    # Structure of the directory table:
554    # Directory Directory_Parent DefaultDir
555    # Directory is a unique identifier
556    # Directory_Parent is the unique identifier of the parent
557    # DefaultDir is .:APPLIC~1|Application Data with
558    # Before ":" : [sourcedir]:[destdir] (not programmed yet)
559    # After ":" : 8+3 and not 8+3 the destination directory name
560
561    $installer::logger::Lang->add_timestamp("Performance Info: Directory Table start");
562
563    my @directorytable = ();
564    my $infoline;
565
566    overwrite_programfilesfolder($allvariableshashref);
567    if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_1.log", $directoryref); }
568    create_unique_directorynames($directoryref, $allvariableshashref);
569    if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_1a.log", $directoryref); }
570    create_defaultdir_directorynames($directoryref, $shortdirnamehashref);  # only destdir!
571    if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_2.log", $directoryref); }
572    set_installlocation_directory($directoryref, $allvariableshashref);
573    if ( $installer::globals::globallogging ) { installer::files::save_array_of_hashes($loggingdir . "directoriesforidt_local_3.log", $directoryref); }
574    installer::windows::idtglobal::write_idt_header(\@directorytable, "directory");
575    add_root_directories(\@directorytable, $allvariableshashref);
576    create_directorytable_from_collection(\@directorytable, $directoryref);
577
578    # Saving the file
579
580    my $directorytablename = $basedir . $installer::globals::separator . "Director.idt";
581    installer::files::save_file($directorytablename ,\@directorytable);
582    $installer::logger::Lang->printf("Created idt file: %s\n", $directorytablename);
583
584    $installer::logger::Lang->add_timestamp("Performance Info: Directory Table end");
585}
586
5871;
588