xref: /trunk/main/solenv/bin/modules/installer/windows/directory.pm (revision 8a25ac931fc787de81e5f3df2b9fd16cf4ddb14c)
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;
32use installer::scriptitems;
33
34use strict;
35
36##############################################################
37# Collecting all directory trees in global hash
38##############################################################
39
40sub collectdirectorytrees
41{
42    my ( $directoryref ) = @_;
43
44    for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
45    {
46        my $onedir = ${$directoryref}[$i];
47        my $styles = "";
48        if ( $onedir->{'Styles'} ) { $styles = $onedir->{'Styles'}; }
49
50        if ( $styles ne "" )
51        {
52            foreach my $treestyle ( keys %installer::globals::treestyles )
53            {
54                if ( $styles =~ /\b$treestyle\b/ )
55                {
56                    my $hostname = $onedir->{'HostName'};
57                    # -> hostname is the key, the style the value!
58                    $installer::globals::hostnametreestyles{$hostname} = $treestyle;
59                }
60            }
61        }
62    }
63}
64
65##############################################################
66# Overwriting global programfilesfolder, if required
67##############################################################
68
69sub overwrite_programfilesfolder
70{
71    my ( $allvariables ) = @_;
72
73    if ( $allvariables->{'PROGRAMFILESFOLDERNAME'} )
74    {
75        $installer::globals::programfilesfolder = $allvariables->{'PROGRAMFILESFOLDERNAME'};
76    }
77}
78
79
80
81
82=head2 make_short_dir_version($longstring)
83
84    Transform the given string into one that is at most 70 characters long.
85    That is done in two steps:
86    - Cut all parts separated by '_' or '-' down to a length of 5.
87    - Cut down the result to a length of 60 and fill it up to length 70
88      with the MD5 checksum.
89
90    This transform always returns the same result for the same string.
91    There is no counter and reference to a global set of names to make the string unique.
92
93=cut
94sub make_short_dir_version ($)
95{
96    my ($longstring) = @_;
97
98    my $shortstring = "";
99    my $cutlength = 60;
100    my $length = 5; # So the directory can still be recognized
101    my $longstring_save = $longstring;
102
103    # Splitting the string at each "underline" and allowing only $length characters per directory name.
104    # Checking also uniqueness and length.
105
106    my @outer_parts = split(/_/, $longstring);
107    foreach my $onestring (@outer_parts)
108    {
109        my $partstring = "";
110
111        if ( $onestring =~ /\-/ )
112        {
113            my @inner_parts = split(/-/, $onestring);
114            @inner_parts = map {substr($_,0,$length)} @inner_parts;
115            $partstring = join("-", @inner_parts);
116            $partstring =~ s/^\s*\-//;
117        }
118        else
119        {
120            $partstring = substr($onestring, 0, $length);
121        }
122
123        $shortstring .= "_" . $partstring;
124    }
125
126    $shortstring =~ s/^\s*\_//;
127
128    # Setting unique ID to each directory
129    # No counter allowed, process must be absolute reproducable due to patch creation process.
130
131    my $subid = installer::windows::msiglobal::calculate_id($longstring_save, 9); # taking only the first 9 digits
132    $shortstring = substr($shortstring, 0, $cutlength) . "_" . $subid;
133
134    return $shortstring;
135}
136
137
138
139
140=head2 get_unique_name ($hostname, $unique_map, $shortdirhash, $shortdirhashreverse)
141
142    Return a long and a short unique name for the given $hostname.
143    Despite the function name and unlike the generation of unique
144    names for files, the returned names are not really unique.  Quite
145    the opposite.  The returned names are quaranteed to return the
146    same result for the same input.
147
148    The returned short name has at most length 70.
149
150=cut
151sub get_unique_name ($$)
152{
153    my ($hostname, $hostnamehash) = @_;
154
155    # Make sure that we where not called for this hostname before.  Otherwise the other test would be triggered.
156    if (defined $hostnamehash->{$hostname})
157    {
158        installer::exiter::exit_program(
159            "ERROR: get_unique_name was already called for hostname ".$hostname,
160            "get_unique_name");
161    }
162    $hostnamehash->{$hostname} = 1;
163
164    my $uniquename = $hostname;
165
166    $uniquename =~ s/^\s*//g;               # removing beginning white spaces
167    $uniquename =~ s/\s*$//g;               # removing ending white spaces
168    $uniquename =~ s/\s//g;                 # removing white spaces
169    $uniquename =~ s/\_//g;                 # removing existing underlines
170    $uniquename =~ s/\.//g;                 # removing dots in directoryname
171    $uniquename =~ s/OpenOffice/OO/g;
172
173    $uniquename =~ s/\Q$installer::globals::separator\E/\_/g;   # replacing slash and backslash with underline
174
175    $uniquename =~ s/_registry/_rgy/g;
176    $uniquename =~ s/_registration/_rgn/g;
177    $uniquename =~ s/_extension/_ext/g;
178    $uniquename =~ s/_frame/_frm/g;
179    $uniquename =~ s/_table/_tbl/g;
180    $uniquename =~ s/_chart/_crt/g;
181
182    my $short_uniquename = make_short_dir_version($uniquename);
183
184    return ($uniquename, $short_uniquename);
185}
186
187
188
189
190=head2 check_unique_directorynames($directories)
191
192    The one really important check is made in get_unique_name().  It
193    checks that get_unique_name() is not called twice for the same
194    directory host name.  The tests in this function contain the
195    legacy tests that basically only check if there where a collision
196    of the partial MD5 sum that is used to make the short unique names
197    unique.
198
199    The maps $unique_map, $shortdirhash, $shortdirhashreverse are used
200    only to check that _different_ input names are mapped to different
201    results.  They are not used to influence the result.  That assumes
202    that this function is called only once for every directory
203    hostname.
204=cut
205sub check_unique_directorynames ($)
206{
207    my ($directories) = @_;
208
209    my %completedirhashstep1 = ();
210    my %shortdirhash = ();
211    my %shortdirhashreverse = ();
212
213    # Check unique name of directories.
214    foreach my $directory (@$directories)
215    {
216        my ($long_uniquename, $short_uniquename) = ($directory->{'long_uniquename'}, $directory->{'uniquename'});
217
218        # The names after this small changes must still be unique!
219        if (exists($completedirhashstep1{$long_uniquename}))
220        {
221            installer::exiter::exit_program(
222                sprintf("ERROR: Unallowed modification of directory name, not unique (step 1): \"%s\".",
223                    $short_uniquename),
224                "check_unique_directorynames");
225        }
226        $completedirhashstep1{$long_uniquename} = 1;
227
228
229        # Checking if the same directory already exists, but has another short version.
230        if (exists($shortdirhash{$long_uniquename})
231            && ( $shortdirhash{$long_uniquename} ne $short_uniquename ))
232        {
233            installer::exiter::exit_program(
234                sprintf(
235                    "ERROR: Unallowed modification of directory name, not unique (step 2A): \"%s\".",
236                    $short_uniquename),
237                "check_unique_directorynames");
238        }
239        $shortdirhash{$long_uniquename} = $short_uniquename;
240
241        # Also checking vice versa
242        # Checking if the same short directory already exists, but has another long version.
243        if (exists($shortdirhashreverse{$short_uniquename})
244            && ( $shortdirhashreverse{$short_uniquename} ne $long_uniquename ))
245        {
246            installer::exiter::exit_program(
247                sprintf(
248                    "ERROR: Unallowed modification of directory name, not unique (step 2B): \"%s\".",
249                    $short_uniquename),
250                "check_unique_directorynames");
251        }
252        $shortdirhashreverse{$short_uniquename} = $long_uniquename;
253    }
254
255    # Check unique name of parents
256    foreach my $directory (@$directories)
257    {
258        my ($long_uniquename, $short_uniquename)
259            = ($directory->{'long_uniqueparentname'}, $directory->{'uniqueparentname'});
260
261        # Again checking if the same directory already exists, but has another short version.
262        if (exists($shortdirhash{$long_uniquename})
263            && ( $shortdirhash{$long_uniquename} ne $short_uniquename ))
264        {
265            installer::exiter::exit_program(
266                sprintf(
267                    "ERROR: Unallowed modification of directory name, not unique (step 3A): \"%s\".",
268                    $short_uniquename),
269                "check_unique_directorynames");
270        }
271        $shortdirhash{$long_uniquename} = $short_uniquename;
272
273        # Also checking vice versa
274        # Checking if the same short directory already exists, but has another long version.
275        if (exists($shortdirhashreverse{$short_uniquename})
276            && ( $shortdirhashreverse{$short_uniquename} ne $long_uniquename ))
277        {
278            installer::exiter::exit_program(
279                sprintf(
280                    "ERROR: Unallowed modification of directory name, not unique (step 3B): \"%s\".",
281                    $short_uniquename),
282                "check_unique_directorynames");
283        }
284        $shortdirhashreverse{$short_uniquename} = $long_uniquename;
285    }
286}
287
288
289
290
291sub get_unique_parent_name ($$)
292{
293    my ($uniqueparentname, $styles) = @_;
294
295    my $keepparent = 1;
296
297    if ( $uniqueparentname =~ /^\s*(.*)\_(.*?)\s*$/ )   # the underline is now the separator
298    {
299        $uniqueparentname = $1;
300        $keepparent = 0;
301    }
302    else
303    {
304        $uniqueparentname = $installer::globals::programfilesfolder;
305        $keepparent = 1;
306    }
307
308    if ( $styles =~ /\bPROGRAMFILESFOLDER\b/ )
309    {
310        $uniqueparentname = $installer::globals::programfilesfolder;
311        $keepparent = 1;
312    }
313    if ( $styles =~ /\bCOMMONFILESFOLDER\b/ )
314    {
315        $uniqueparentname = $installer::globals::commonfilesfolder;
316        $keepparent = 1;
317    }
318    if ( $styles =~ /\bCOMMONAPPDATAFOLDER\b/ )
319    {
320        $uniqueparentname = $installer::globals::commonappdatafolder;
321        $keepparent = 1;
322    }
323    if ( $styles =~ /\bLOCALAPPDATAFOLDER\b/ )
324    {
325        $uniqueparentname = $installer::globals::localappdatafolder;
326        $keepparent = 1;
327    }
328
329    if ( $styles =~ /\bSHAREPOINTPATH\b/ )
330    {
331        $uniqueparentname = "SHAREPOINTPATH";
332        $installer::globals::usesharepointpath = 1;
333        $keepparent = 1;
334    }
335
336    # also setting short directory name for the parent
337
338    my $originaluniqueparentname = $uniqueparentname;
339
340    if ( ! $keepparent )
341    {
342        $uniqueparentname = make_short_dir_version($uniqueparentname);
343    }
344
345    return ($originaluniqueparentname, $uniqueparentname);
346}
347
348
349
350
351##############################################################
352# Adding unique directory names to the directory collection
353##############################################################
354
355sub create_unique_directorynames ($)
356{
357    my ($directories) = @_;
358
359    $installer::globals::officeinstalldirectoryset = 0;
360
361    my %hostnamehash = ();
362    my $infoline = "";
363    my $errorcount = 0;
364
365    foreach my $directory (@$directories)
366    {
367        next if defined $directory->{'uniquename'};
368
369        my $styles = $directory->{'Styles'};
370        $styles = "" unless defined $styles;
371
372        my ($originaluniquename, $uniquename) = get_unique_name(
373            $directory->{'HostName'},
374            \%hostnamehash);
375
376        my ($originaluniqueparentname, $uniqueparentname) = get_unique_parent_name(
377            $originaluniquename,
378            $styles);
379
380
381        # Hyphen not allowed in database
382        $uniquename =~ s/\-/\_/g;           # making "-" to "_"
383        $uniqueparentname =~ s/\-/\_/g;     # making "-" to "_"
384
385        # And finally setting the values for the directories
386        $directory->{'uniquename'} = $uniquename;
387        $directory->{'uniqueparentname'} = $uniqueparentname;
388        $directory->{'long_uniquename'} = $originaluniquename;
389        $directory->{'long_uniqueparentname'} = $originaluniqueparentname;
390    }
391
392    # Find the installation directory.
393    foreach my $directory (@$directories)
394    {
395        next unless defined $directory->{'Styles'};
396
397        # setting the installlocation directory
398        next unless $directory->{'Styles'} =~ /\bISINSTALLLOCATION\b/;
399
400        if ( $installer::globals::installlocationdirectoryset )
401        {
402            installer::exiter::exit_program(
403                sprintf(
404                    "ERROR: Directory with flag ISINSTALLLOCATION alread set: \"%s\".",
405                    $installer::globals::installlocationdirectory),
406                "create_unique_directorynames");
407        }
408
409        $installer::globals::installlocationdirectory = $directory->{'uniquename'};
410        $installer::globals::installlocationdirectoryset = 1;
411    }
412}
413
414
415
416
417#####################################################
418# Adding ":." to selected default directory names
419#####################################################
420
421sub update_defaultdir ($$)
422{
423    my ( $onedir, $allvariableshashref ) = @_;
424
425    if ($installer::globals::addchildprojects
426        || $installer::globals::patch
427        || $installer::globals::languagepack
428        || $allvariableshashref->{'CHANGETARGETDIR'})
429    {
430        my $sourcediraddon = "\:\.";
431        return $onedir->{'defaultdir'} . $sourcediraddon;
432    }
433    else
434    {
435        return $onedir->{'defaultdir'};
436    }
437}
438
439#####################################################
440# The directory with the style ISINSTALLLOCATION
441# will be replaced by INSTALLLOCATION
442#####################################################
443
444sub set_installlocation_directory
445{
446    my ( $directoryref, $allvariableshashref ) = @_;
447
448    if ( ! $installer::globals::installlocationdirectoryset )
449    {
450        installer::exiter::exit_program(
451            "ERROR: Directory with flag ISINSTALLLOCATION not set!",
452            "set_installlocation_directory");
453    }
454
455    for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
456    {
457        my $onedir = ${$directoryref}[$i];
458
459        if ( $onedir->{'uniquename'} eq $installer::globals::installlocationdirectory )
460        {
461            $onedir->{'uniquename'} = "INSTALLLOCATION";
462            $onedir->{'defaultdir'} = update_defaultdir($onedir, $allvariableshashref);
463        }
464
465        if ( $onedir->{'uniquename'} eq $installer::globals::vendordirectory )
466        {
467            $onedir->{'defaultdir'} = update_defaultdir($onedir, $allvariableshashref);
468        }
469
470        if ( $onedir->{'uniqueparentname'} eq $installer::globals::installlocationdirectory )
471        {
472            $onedir->{'uniqueparentname'} = "INSTALLLOCATION";
473        }
474    }
475}
476
477#####################################################
478# Getting the name of the top level directory. This
479# can have only one letter
480#####################################################
481
482sub get_last_directory_name
483{
484    my ($completepathref) = @_;
485
486    if ( $$completepathref =~ /^.*[\/\\](.+?)\s*$/ )
487    {
488        $$completepathref = $1;
489    }
490}
491
492sub setup_global_font_directory_name ($)
493{
494    my ($directories) = @_;
495
496    foreach my $directory (@$directories)
497    {
498        next unless defined $directory->{'Dir'};
499        next unless defined $directory->{'defaultdir'};
500
501        next if $directory->{'Dir'} ne "PREDEFINED_OSSYSTEMFONTDIR";
502        next if $directory->{'defaultdir'} ne $installer::globals::fontsdirhostname;
503
504        $installer::globals::fontsdirname = $installer::globals::fontsdirhostname;
505        $installer::globals::fontsdirparent = $directory->{'uniqueparentname'};
506
507        $installer::logger::Info->printf("%s, fdhn %s, dd %s, ipn %s, HN %s\n",
508            "PREDEFINED_OSSYSTEMFONTDIR",
509            $installer::globals::fontsdirhostname,
510            $directory->{'defaultdir'},
511            $directory->{'uniqueparentname'},
512            $directory->{'HostName'});
513        installer::scriptitems::print_script_item($directory);
514    }
515}
516
517#####################################################
518# Creating the defaultdir for the file Director.idt
519#####################################################
520
521sub create_defaultdir_directorynames ($)
522{
523    my ($directoryref) = @_;
524
525    my @shortnames = ();
526    if ( $installer::globals::prepare_winpatch ) { @shortnames = values(%installer::globals::saved83dirmapping); }
527
528    for ( my $i = 0; $i <= $#{$directoryref}; $i++ )
529    {
530        my $onedir = ${$directoryref}[$i];
531        my $hostname = $onedir->{'HostName'};
532
533        $hostname =~ s/\Q$installer::globals::separator\E\s*$//;
534        get_last_directory_name(\$hostname);
535        # installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$hostname); # making program/classes to classes
536        my $uniquename = $onedir->{'uniquename'};
537        my $shortstring;
538        if (( $installer::globals::prepare_winpatch ) && ( exists($installer::globals::saved83dirmapping{$uniquename}) ))
539        {
540            $shortstring = $installer::globals::saved83dirmapping{$uniquename};
541        }
542        else
543        {
544            $shortstring = installer::windows::idtglobal::make_eight_three_conform($hostname, "dir", \@shortnames);
545        }
546
547        my $defaultdir;
548
549        if ( $shortstring eq $hostname )
550        {
551            $defaultdir = $hostname;
552        }
553        else
554        {
555            $defaultdir = $shortstring . "|" . $hostname;
556        }
557
558        $onedir->{'defaultdir'} = $defaultdir;
559    }
560}
561
562###############################################
563# Fill content into the directory table
564###############################################
565
566sub create_directorytable_from_collection ($$)
567{
568    my ($directorytableref, $directoryref) = @_;
569
570    foreach my $onedir (@$directoryref)
571    {
572        # Remove entries for special directories.
573        if (defined $onedir->{'HostName'}
574            && $onedir->{'HostName'} eq ""
575            && defined $onedir->{'Dir'}
576            && $onedir->{'Dir'} eq "PREDEFINED_PROGDIR")
577        {
578            next;
579        }
580
581        my $oneline = sprintf(
582            "%s\t%s\t%s\n",
583            $onedir->{'uniquename'},
584            $onedir->{'uniqueparentname'},
585            $onedir->{'defaultdir'});
586
587        push @{$directorytableref}, $oneline;
588    }
589}
590
591###############################################
592# Defining the root installation structure
593###############################################
594
595sub process_root_directories ($$)
596{
597    my ($allvariableshashref, $functor) = @_;
598
599    my $oneline = "";
600
601    if (( ! $installer::globals::patch ) && ( ! $installer::globals::languagepack ) && ( ! $allvariableshashref->{'DONTUSESTARTMENUFOLDER'} ))
602    {
603        my $productname = $allvariableshashref->{'PRODUCTNAME'};
604        my $productversion = $allvariableshashref->{'PRODUCTVERSION'};
605        my $baseproductversion = $productversion;
606
607        if (( $installer::globals::prepare_winpatch ) && ( $allvariableshashref->{'BASEPRODUCTVERSION'} ))
608        {
609            $baseproductversion = $allvariableshashref->{'BASEPRODUCTVERSION'};  # for example "2.0" for OOo
610        }
611
612        my $realproductkey = $productname . " " . $productversion;
613        my $productkey = $productname . " " . $baseproductversion;
614
615        if (( $allvariableshashref->{'POSTVERSIONEXTENSION'} ) && ( ! $allvariableshashref->{'DONTUSEEXTENSIONINDEFAULTDIR'} ))
616        {
617            $productkey = $productkey . " " . $allvariableshashref->{'POSTVERSIONEXTENSION'};
618            $realproductkey = $realproductkey . " " . $allvariableshashref->{'POSTVERSIONEXTENSION'};
619        }
620        if ( $allvariableshashref->{'NOSPACEINDIRECTORYNAME'} )
621        {
622            $productkey =~ s/\ /\_/g;
623            $realproductkey =~ s/\ /\_/g;
624        }
625
626        my $shortproductkey = installer::windows::idtglobal::make_eight_three_conform($productkey, "dir", undef);
627        $shortproductkey =~ s/\s/\_/g;                                  # changing empty space to underline
628
629        &$functor(
630            $installer::globals::officemenufolder,
631            $installer::globals::programmenufolder,
632            $shortproductkey . "|". $realproductkey);
633    }
634
635    &$functor("TARGETDIR", "", "SourceDir");
636    &$functor($installer::globals::programfilesfolder, "TARGETDIR", ".");
637    &$functor($installer::globals::programmenufolder, "TARGETDIR", ".");
638    &$functor($installer::globals::startupfolder, "TARGETDIR", ".");
639    &$functor($installer::globals::desktopfolder, "TARGETDIR", ".");
640    &$functor($installer::globals::startmenufolder, "TARGETDIR", ".");
641    &$functor($installer::globals::commonfilesfolder, "TARGETDIR", ".");
642    &$functor($installer::globals::commonappdatafolder, "TARGETDIR", ".");
643    &$functor($installer::globals::localappdatafolder, "TARGETDIR", ".");
644
645    if ( $installer::globals::usesharepointpath )
646    {
647        &$functor("SHAREPOINTPATH", "TARGETDIR", ".");
648    }
649
650    &$functor($installer::globals::systemfolder, "TARGETDIR", ".");
651
652    my $localtemplatefoldername = $installer::globals::templatefoldername;
653    my $directorytableentry = $localtemplatefoldername;
654    my $shorttemplatefoldername = installer::windows::idtglobal::make_eight_three_conform($localtemplatefoldername, "dir");
655    if ( $shorttemplatefoldername ne $localtemplatefoldername )
656    {
657        $directorytableentry = $shorttemplatefoldername . "|" . $localtemplatefoldername;
658    }
659    &$functor($installer::globals::templatefolder, "TARGETDIR", $directorytableentry);
660
661    if ( $installer::globals::fontsdirname )
662    {
663        &$functor(
664             $installer::globals::fontsfolder,
665             $installer::globals::fontsdirparent,
666             $installer::globals::fontsfoldername . ":" . $installer::globals::fontsdirname);
667    }
668    else
669    {
670        &$functor(
671             $installer::globals::fontsfolder,
672             "TARGETDIR",
673             $installer::globals::fontsfoldername);
674    }
675}
676
677
678
679
680sub find_missing_directories ($$)
681{
682    my ($directories, $allvariableshashref) = @_;
683
684    # Set up the list of target directories.
685    my %target_directories = map {$_->{'uniquename'} => 1} @$directories;
686    # Add special directories.
687    process_root_directories(
688        $allvariableshashref,
689        sub($$$){
690            my ($uniquename, $parentname, $defaultdir) = @_;
691            $target_directories{$uniquename} = 1;
692        }
693    );
694
695    # Set up the list of source directories.
696    my $source_directory_map = $installer::globals::source_msi->GetDirectoryMap();
697    my $source_file_map = $installer::globals::source_msi->GetFileMap();
698    my %source_directories = map {$_->{'unique_name'} => $_} values %$source_directory_map;
699
700    # Find the missing source directories.
701    my @missing_directories = ();
702    foreach my $source_uniquename (keys %source_directories)
703    {
704        if ( ! $target_directories{$source_uniquename})
705        {
706            push @missing_directories, $source_directories{$source_uniquename};
707        }
708    }
709
710    # Report the missing directories.
711    $installer::logger::Info->printf("found %d missing directories\n", scalar @missing_directories);
712    my $index = 0;
713    foreach my $directory_item (@missing_directories)
714    {
715        # Print information about the directory.
716        $installer::logger::Info->printf("missing directory %d: %s\n",
717            ++$index,
718            $directory_item->{'full_target_long_name'});
719        while (my($key,$value) = each %$directory_item)
720        {
721            $installer::logger::Info->printf("    %s -> %s\n", $key, $value);
722        }
723
724        # Print the referencing files.
725        my @filenames = ();
726        while (my ($key,$value) = each %$source_file_map)
727        {
728            if ($value->{'directory'}->{'unique_name'} eq $directory_item->{'unique_name'})
729            {
730                push @filenames, $key;
731            }
732        }
733        $installer::logger::Info->printf("  referencing files are %s\n", join(", ", @filenames));
734    }
735
736    foreach my $directory (@$directories)
737    {
738        $installer::logger::Lang->printf("target directory %s -> HN %s\n",
739            $directory->{'uniquename'},
740            $directory->{'HostName'});
741        installer::scriptitems::print_script_item($directory);
742    }
743
744    # Setup a map of directory uniquenames to verify that the new
745    # entries don't use unique names that are already in use.
746    my %unique_names = map {$_->{'uniquename'} => $_} @$directories;
747
748    # Create script items for the missing directories.
749    my @new_source_directories = ();
750    foreach my $source_directory_item (@missing_directories)
751    {
752        my $new_directory_item = {
753            'uniquename' => $source_directory_item->{'unique_name'},
754            'uniqueparentname' => $source_directory_item->{'parent_name'},
755            'defaultdir' => $source_directory_item->{'default_dir'},
756            'HostName' => $source_directory_item->{'full_target_long_name'},
757            'componentname' => $source_directory_item->{'component_name'},
758        };
759
760        if (defined $unique_names{$new_directory_item->{'uniquename'}})
761        {
762            installer::logger::PrintError("newly created directory entry collides with existing directory");
763            last;
764        }
765
766        push @new_source_directories, $new_directory_item;
767    }
768
769    return @new_source_directories;
770}
771
772
773
774
775sub prepare_directory_table_creation ($$)
776{
777    my ($directories, $allvariableshashref) = @_;
778
779    foreach my $directory (@$directories)
780    {
781        delete $directory->{'uniquename'};
782    }
783
784    overwrite_programfilesfolder($allvariableshashref);
785    create_unique_directorynames($directories);
786    check_unique_directorynames($directories);
787    create_defaultdir_directorynames($directories); # only destdir!
788    setup_global_font_directory_name($directories);
789    set_installlocation_directory($directories, $allvariableshashref);
790
791    if ($installer::globals::is_release)
792    {
793        my @new_directories = find_missing_directories($directories, $allvariableshashref);
794        push @$directories, @new_directories;
795    }
796}
797
798
799
800
801###############################################
802# Creating the file Director.idt dynamically
803###############################################
804
805sub create_directory_table ($$$)
806{
807    my ($directoryref, $basedir, $allvariableshashref) = @_;
808
809    # Structure of the directory table:
810    # Directory Directory_Parent DefaultDir
811    # Directory is a unique identifier
812    # Directory_Parent is the unique identifier of the parent
813    # DefaultDir is .:APPLIC~1|Application Data with
814    # Before ":" : [sourcedir]:[destdir] (not programmed yet)
815    # After ":" : 8+3 and not 8+3 the destination directory name
816
817    $installer::logger::Lang->add_timestamp("Performance Info: Directory Table start");
818
819    my @directorytable = ();
820    installer::windows::idtglobal::write_idt_header(\@directorytable, "directory");
821
822    # Add entries for the root directories (and a few special directories like that for fonts).
823    process_root_directories(
824        $allvariableshashref,
825        sub($$$){
826            push(@directorytable, join("\t", @_)."\n");
827        }
828    );
829
830    # Add entries for the non-root directories.
831    create_directorytable_from_collection(\@directorytable, $directoryref);
832
833    # Saving the file
834
835    my $directorytablename = $basedir . $installer::globals::separator . "Director.idt";
836    installer::files::save_file($directorytablename ,\@directorytable);
837    $installer::logger::Lang->printf("Created idt file: %s\n", $directorytablename);
838
839    $installer::logger::Lang->add_timestamp("Performance Info: Directory Table end");
840}
841
842
8431;
844