xref: /trunk/main/setup_native/scripts/admin.pl (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir#*************************************************************************
2*cdf0e10cSrcweir#
3*cdf0e10cSrcweir# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir#
5*cdf0e10cSrcweir# Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir#
7*cdf0e10cSrcweir# OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir#
9*cdf0e10cSrcweir# This file is part of OpenOffice.org.
10*cdf0e10cSrcweir#
11*cdf0e10cSrcweir# OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir# it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir# only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir#
15*cdf0e10cSrcweir# OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir# but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir# GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir# (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir#
21*cdf0e10cSrcweir# You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir# version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir# <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir# for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir#
26*cdf0e10cSrcweir#*************************************************************************
27*cdf0e10cSrcweir
28*cdf0e10cSrcweiruse Cwd;
29*cdf0e10cSrcweiruse File::Copy;
30*cdf0e10cSrcweir
31*cdf0e10cSrcweir#################################################################################
32*cdf0e10cSrcweir# Global settings
33*cdf0e10cSrcweir#################################################################################
34*cdf0e10cSrcweir
35*cdf0e10cSrcweirBEGIN
36*cdf0e10cSrcweir{
37*cdf0e10cSrcweir    $prog = "msi installer";
38*cdf0e10cSrcweir    $targetdir = "";
39*cdf0e10cSrcweir    $databasepath = "";
40*cdf0e10cSrcweir    $starttime = "";
41*cdf0e10cSrcweir    $globaltempdirname = "ooopackaging";
42*cdf0e10cSrcweir    $savetemppath = "";
43*cdf0e10cSrcweir    $msiinfo_available = 0;
44*cdf0e10cSrcweir    $path_displayed = 0;
45*cdf0e10cSrcweir    $localmsidbpath = "";
46*cdf0e10cSrcweir
47*cdf0e10cSrcweir    $plat = $^O;
48*cdf0e10cSrcweir
49*cdf0e10cSrcweir    if ( $plat =~ /cygwin/i )
50*cdf0e10cSrcweir    {
51*cdf0e10cSrcweir        $separator = "/";
52*cdf0e10cSrcweir        $pathseparator = "\:";
53*cdf0e10cSrcweir    }
54*cdf0e10cSrcweir    else
55*cdf0e10cSrcweir    {
56*cdf0e10cSrcweir        $separator = "\\";
57*cdf0e10cSrcweir        $pathseparator = "\;";
58*cdf0e10cSrcweir    }
59*cdf0e10cSrcweir}
60*cdf0e10cSrcweir
61*cdf0e10cSrcweir#################################################################################
62*cdf0e10cSrcweir# Program information
63*cdf0e10cSrcweir#################################################################################
64*cdf0e10cSrcweir
65*cdf0e10cSrcweirsub usage
66*cdf0e10cSrcweir{
67*cdf0e10cSrcweir    print <<Ende;
68*cdf0e10cSrcweir----------------------------------------------------------------------
69*cdf0e10cSrcweirThis program installs a Windows Installer installation set
70*cdf0e10cSrcweirwithout using msiexec.exe. The installation is comparable
71*cdf0e10cSrcweirwith an administrative installation using the Windows Installer
72*cdf0e10cSrcweirservice.
73*cdf0e10cSrcweirRequired parameter:
74*cdf0e10cSrcweir-d Path to installation set or msi database
75*cdf0e10cSrcweir-t Target directory
76*cdf0e10cSrcweir---------------------------------------------------------------------
77*cdf0e10cSrcweirEnde
78*cdf0e10cSrcweir    exit(-1);
79*cdf0e10cSrcweir}
80*cdf0e10cSrcweir
81*cdf0e10cSrcweir#################################################################################
82*cdf0e10cSrcweir# Collecting parameter
83*cdf0e10cSrcweir#################################################################################
84*cdf0e10cSrcweir
85*cdf0e10cSrcweirsub getparameter
86*cdf0e10cSrcweir{
87*cdf0e10cSrcweir    if (( $#ARGV < 3 ) || ( $#ARGV > 3 )) { usage(); }
88*cdf0e10cSrcweir
89*cdf0e10cSrcweir    while ( $#ARGV >= 0 )
90*cdf0e10cSrcweir    {
91*cdf0e10cSrcweir        my $param = shift(@ARGV);
92*cdf0e10cSrcweir
93*cdf0e10cSrcweir        if ($param eq "-t") { $targetdir = shift(@ARGV); }
94*cdf0e10cSrcweir        elsif ($param eq "-d") { $databasepath = shift(@ARGV); }
95*cdf0e10cSrcweir        else
96*cdf0e10cSrcweir        {
97*cdf0e10cSrcweir            print "\n**********************************************\n";
98*cdf0e10cSrcweir            print "Error: Unknows parameter: $param";
99*cdf0e10cSrcweir            print "\n**********************************************\n";
100*cdf0e10cSrcweir            usage();
101*cdf0e10cSrcweir            exit(-1);
102*cdf0e10cSrcweir        }
103*cdf0e10cSrcweir    }
104*cdf0e10cSrcweir}
105*cdf0e10cSrcweir
106*cdf0e10cSrcweir#################################################################################
107*cdf0e10cSrcweir# Checking content of parameter
108*cdf0e10cSrcweir#################################################################################
109*cdf0e10cSrcweir
110*cdf0e10cSrcweirsub controlparameter
111*cdf0e10cSrcweir{
112*cdf0e10cSrcweir    if ( $targetdir eq "" )
113*cdf0e10cSrcweir    {
114*cdf0e10cSrcweir        print "\n******************************************************\n";
115*cdf0e10cSrcweir        print "Error: Target directory not defined (parameter -t)!";
116*cdf0e10cSrcweir        print "\n******************************************************\n";
117*cdf0e10cSrcweir        usage();
118*cdf0e10cSrcweir        exit(-1);
119*cdf0e10cSrcweir    }
120*cdf0e10cSrcweir
121*cdf0e10cSrcweir    if ( $databasepath eq "" )
122*cdf0e10cSrcweir    {
123*cdf0e10cSrcweir        print "\n******************************************************\n";
124*cdf0e10cSrcweir        print "Error: Path to msi database not defined (parameter -d)!";
125*cdf0e10cSrcweir        print "\n******************************************************\n";
126*cdf0e10cSrcweir        usage();
127*cdf0e10cSrcweir        exit(-1);
128*cdf0e10cSrcweir    }
129*cdf0e10cSrcweir
130*cdf0e10cSrcweir    if ( -d $databasepath )
131*cdf0e10cSrcweir    {
132*cdf0e10cSrcweir        $databasepath =~ s/\\\s*$//;
133*cdf0e10cSrcweir        $databasepath =~ s/\/\s*$//;
134*cdf0e10cSrcweir
135*cdf0e10cSrcweir        my $msifiles = find_file_with_file_extension("msi", $databasepath);
136*cdf0e10cSrcweir
137*cdf0e10cSrcweir        if ( $#{$msifiles} < 0 ) { exit_program("ERROR: Did not find msi database in directory $installationdir"); }
138*cdf0e10cSrcweir        if ( $#{$msifiles} > 0 ) { exit_program("ERROR: Did find more than one msi database in directory $installationdir"); }
139*cdf0e10cSrcweir
140*cdf0e10cSrcweir        $databasepath = $databasepath . $separator . ${$msifiles}[0];
141*cdf0e10cSrcweir    }
142*cdf0e10cSrcweir
143*cdf0e10cSrcweir    if ( ! -f $databasepath ) { exit_program("ERROR: Did not find msi database in directory $databasepath."); }
144*cdf0e10cSrcweir
145*cdf0e10cSrcweir    if ( ! -d $targetdir ) { create_directories($targetdir); }
146*cdf0e10cSrcweir}
147*cdf0e10cSrcweir
148*cdf0e10cSrcweir#############################################################################
149*cdf0e10cSrcweir# The program msidb.exe can be located next to the Perl program. Then it is
150*cdf0e10cSrcweir# not neccessary to find it in the PATH variable.
151*cdf0e10cSrcweir#############################################################################
152*cdf0e10cSrcweir
153*cdf0e10cSrcweirsub check_local_msidb
154*cdf0e10cSrcweir{
155*cdf0e10cSrcweir    my $msidbname = "msidb.exe";
156*cdf0e10cSrcweir    my $perlprogramm = $0;
157*cdf0e10cSrcweir    my $path = $perlprogramm;
158*cdf0e10cSrcweir
159*cdf0e10cSrcweir    get_path_from_fullqualifiedname(\$path);
160*cdf0e10cSrcweir
161*cdf0e10cSrcweir    $path =~ s/\\\s*$//;
162*cdf0e10cSrcweir    $path =~ s/\/\s*$//;
163*cdf0e10cSrcweir
164*cdf0e10cSrcweir    my $msidbpath = "";
165*cdf0e10cSrcweir    if ( $path =~ /^\s*$/ ) { $msidbpath = $msidbname; }
166*cdf0e10cSrcweir    else { $msidbpath = $path . $separator . $msidbname; }
167*cdf0e10cSrcweir
168*cdf0e10cSrcweir    if ( -f $msidbpath )
169*cdf0e10cSrcweir    {
170*cdf0e10cSrcweir        $localmsidbpath = $msidbpath;
171*cdf0e10cSrcweir        print "Using $msidbpath (next to \"admin.pl\")\n";
172*cdf0e10cSrcweir    }
173*cdf0e10cSrcweir}
174*cdf0e10cSrcweir
175*cdf0e10cSrcweir#############################################################################
176*cdf0e10cSrcweir# Converting a string list with separator $listseparator
177*cdf0e10cSrcweir# into an array
178*cdf0e10cSrcweir#############################################################################
179*cdf0e10cSrcweir
180*cdf0e10cSrcweirsub convert_stringlist_into_array
181*cdf0e10cSrcweir{
182*cdf0e10cSrcweir    my ( $includestringref, $listseparator ) = @_;
183*cdf0e10cSrcweir
184*cdf0e10cSrcweir    my @newarray = ();
185*cdf0e10cSrcweir    my $first;
186*cdf0e10cSrcweir    my $last = ${$includestringref};
187*cdf0e10cSrcweir
188*cdf0e10cSrcweir    while ( $last =~ /^\s*(.+?)\Q$listseparator\E(.+)\s*$/) # "$" for minimal matching
189*cdf0e10cSrcweir    {
190*cdf0e10cSrcweir        $first = $1;
191*cdf0e10cSrcweir        $last = $2;
192*cdf0e10cSrcweir        # Problem with two directly following listseparators. For example a path with two ";;" directly behind each other
193*cdf0e10cSrcweir        $first =~ s/^$listseparator//;
194*cdf0e10cSrcweir        push(@newarray, "$first\n");
195*cdf0e10cSrcweir    }
196*cdf0e10cSrcweir
197*cdf0e10cSrcweir    push(@newarray, "$last\n");
198*cdf0e10cSrcweir
199*cdf0e10cSrcweir    return \@newarray;
200*cdf0e10cSrcweir}
201*cdf0e10cSrcweir
202*cdf0e10cSrcweir#########################################################
203*cdf0e10cSrcweir# Checking the local system
204*cdf0e10cSrcweir# Checking existence of needed files in include path
205*cdf0e10cSrcweir#########################################################
206*cdf0e10cSrcweir
207*cdf0e10cSrcweirsub check_system_path
208*cdf0e10cSrcweir{
209*cdf0e10cSrcweir    my $onefile;
210*cdf0e10cSrcweir    my $error = 0;
211*cdf0e10cSrcweir    my $pathvariable = $ENV{'PATH'};
212*cdf0e10cSrcweir    my $local_pathseparator = $pathseparator;
213*cdf0e10cSrcweir
214*cdf0e10cSrcweir    if( $^O =~ /cygwin/i )
215*cdf0e10cSrcweir    {   # When using cygwin's perl the PATH variable is POSIX style and ...
216*cdf0e10cSrcweir        $pathvariable = qx{cygpath -mp "$pathvariable"} ;
217*cdf0e10cSrcweir        # has to be converted to DOS style for further use.
218*cdf0e10cSrcweir        $local_pathseparator = ';';
219*cdf0e10cSrcweir    }
220*cdf0e10cSrcweir    my $patharrayref = convert_stringlist_into_array(\$pathvariable, $local_pathseparator);
221*cdf0e10cSrcweir
222*cdf0e10cSrcweir    my @needed_files_in_path = ("expand.exe");
223*cdf0e10cSrcweir    if ( $localmsidbpath eq "" ) { push(@needed_files_in_path, "msidb.exe"); } # not found locally -> search in path
224*cdf0e10cSrcweir    my @optional_files_in_path = ("msiinfo.exe");
225*cdf0e10cSrcweir
226*cdf0e10cSrcweir    print("\nChecking required files:\n");
227*cdf0e10cSrcweir
228*cdf0e10cSrcweir    foreach $onefile ( @needed_files_in_path )
229*cdf0e10cSrcweir    {
230*cdf0e10cSrcweir        print("...... searching $onefile ...");
231*cdf0e10cSrcweir
232*cdf0e10cSrcweir        my $fileref = get_sourcepath_from_filename_and_includepath(\$onefile, $patharrayref);
233*cdf0e10cSrcweir
234*cdf0e10cSrcweir        if ( $$fileref eq "" )
235*cdf0e10cSrcweir        {
236*cdf0e10cSrcweir            $error = 1;
237*cdf0e10cSrcweir            print( "$onefile not found\n" );
238*cdf0e10cSrcweir        }
239*cdf0e10cSrcweir        else
240*cdf0e10cSrcweir        {
241*cdf0e10cSrcweir            print( "\tFound: $$fileref\n" );
242*cdf0e10cSrcweir        }
243*cdf0e10cSrcweir    }
244*cdf0e10cSrcweir
245*cdf0e10cSrcweir    if ( $error ) { exit_program("ERROR: Could not find all needed files in path (using setsolar should help)!"); }
246*cdf0e10cSrcweir
247*cdf0e10cSrcweir    print("\nChecking optional files:\n");
248*cdf0e10cSrcweir
249*cdf0e10cSrcweir    foreach $onefile ( @optional_files_in_path )
250*cdf0e10cSrcweir    {
251*cdf0e10cSrcweir        print("...... searching $onefile ...");
252*cdf0e10cSrcweir
253*cdf0e10cSrcweir        my $fileref = get_sourcepath_from_filename_and_includepath(\$onefile, $patharrayref);
254*cdf0e10cSrcweir
255*cdf0e10cSrcweir        if ( $$fileref eq "" )
256*cdf0e10cSrcweir        {
257*cdf0e10cSrcweir            print( "$onefile not found\n" );
258*cdf0e10cSrcweir            if ( $onefile eq "msiinfo.exe" ) { $msiinfo_available = 0; }
259*cdf0e10cSrcweir        }
260*cdf0e10cSrcweir        else
261*cdf0e10cSrcweir        {
262*cdf0e10cSrcweir            print( "\tFound: $$fileref\n" );
263*cdf0e10cSrcweir            if ( $onefile eq "msiinfo.exe" ) { $msiinfo_available = 1; }
264*cdf0e10cSrcweir        }
265*cdf0e10cSrcweir    }
266*cdf0e10cSrcweir
267*cdf0e10cSrcweir}
268*cdf0e10cSrcweir
269*cdf0e10cSrcweir##########################################################################
270*cdf0e10cSrcweir# Searching a file in a list of pathes
271*cdf0e10cSrcweir##########################################################################
272*cdf0e10cSrcweir
273*cdf0e10cSrcweirsub get_sourcepath_from_filename_and_includepath
274*cdf0e10cSrcweir{
275*cdf0e10cSrcweir    my ($searchfilenameref, $includepatharrayref) = @_;
276*cdf0e10cSrcweir
277*cdf0e10cSrcweir    my $onefile = "";
278*cdf0e10cSrcweir    my $foundsourcefile = 0;
279*cdf0e10cSrcweir
280*cdf0e10cSrcweir    for ( my $j = 0; $j <= $#{$includepatharrayref}; $j++ )
281*cdf0e10cSrcweir    {
282*cdf0e10cSrcweir        my $includepath = ${$includepatharrayref}[$j];
283*cdf0e10cSrcweir        $includepath =~ s/^\s*//;
284*cdf0e10cSrcweir        $includepath =~ s/\s*$//;
285*cdf0e10cSrcweir
286*cdf0e10cSrcweir        $onefile = $includepath . $separator . $$searchfilenameref;
287*cdf0e10cSrcweir
288*cdf0e10cSrcweir        if ( -f $onefile )
289*cdf0e10cSrcweir        {
290*cdf0e10cSrcweir            $foundsourcefile = 1;
291*cdf0e10cSrcweir            last;
292*cdf0e10cSrcweir        }
293*cdf0e10cSrcweir    }
294*cdf0e10cSrcweir
295*cdf0e10cSrcweir    if (!($foundsourcefile)) { $onefile = ""; }
296*cdf0e10cSrcweir
297*cdf0e10cSrcweir    return \$onefile;
298*cdf0e10cSrcweir}
299*cdf0e10cSrcweir
300*cdf0e10cSrcweir##############################################################
301*cdf0e10cSrcweir# Removing all empty directories below a specified directory
302*cdf0e10cSrcweir##############################################################
303*cdf0e10cSrcweir
304*cdf0e10cSrcweirsub remove_empty_dirs_in_folder
305*cdf0e10cSrcweir{
306*cdf0e10cSrcweir    my ( $dir, $firstrun ) = @_;
307*cdf0e10cSrcweir
308*cdf0e10cSrcweir    if ( $firstrun )
309*cdf0e10cSrcweir    {
310*cdf0e10cSrcweir        print "Removing superfluous directories\n";
311*cdf0e10cSrcweir    }
312*cdf0e10cSrcweir
313*cdf0e10cSrcweir    my @content = ();
314*cdf0e10cSrcweir
315*cdf0e10cSrcweir    $dir =~ s/\Q$separator\E\s*$//;
316*cdf0e10cSrcweir
317*cdf0e10cSrcweir    if ( -d $dir )
318*cdf0e10cSrcweir    {
319*cdf0e10cSrcweir        opendir(DIR, $dir);
320*cdf0e10cSrcweir        @content = readdir(DIR);
321*cdf0e10cSrcweir        closedir(DIR);
322*cdf0e10cSrcweir
323*cdf0e10cSrcweir        my $oneitem;
324*cdf0e10cSrcweir
325*cdf0e10cSrcweir        foreach $oneitem (@content)
326*cdf0e10cSrcweir        {
327*cdf0e10cSrcweir            if ((!($oneitem eq ".")) && (!($oneitem eq "..")))
328*cdf0e10cSrcweir            {
329*cdf0e10cSrcweir                my $item = $dir . $separator . $oneitem;
330*cdf0e10cSrcweir
331*cdf0e10cSrcweir                if ( -d $item ) # recursive
332*cdf0e10cSrcweir                {
333*cdf0e10cSrcweir                    remove_empty_dirs_in_folder($item, 0);
334*cdf0e10cSrcweir                }
335*cdf0e10cSrcweir            }
336*cdf0e10cSrcweir        }
337*cdf0e10cSrcweir
338*cdf0e10cSrcweir        # try to remove empty directory
339*cdf0e10cSrcweir        my $returnvalue = rmdir $dir;
340*cdf0e10cSrcweir
341*cdf0e10cSrcweir        # if ( $returnvalue ) { print "Successfully removed empty dir $dir\n"; }
342*cdf0e10cSrcweir    }
343*cdf0e10cSrcweir}
344*cdf0e10cSrcweir
345*cdf0e10cSrcweir####################################################
346*cdf0e10cSrcweir# Detecting the directory with extensions
347*cdf0e10cSrcweir####################################################
348*cdf0e10cSrcweir
349*cdf0e10cSrcweirsub get_extensions_dir
350*cdf0e10cSrcweir{
351*cdf0e10cSrcweir    my ( $unopkgfile ) = @_;
352*cdf0e10cSrcweir
353*cdf0e10cSrcweir    my $localbranddir = $unopkgfile;
354*cdf0e10cSrcweir    get_path_from_fullqualifiedname(\$localbranddir); # "program" dir in brand layer
355*cdf0e10cSrcweir    get_path_from_fullqualifiedname(\$localbranddir); # root dir in brand layer
356*cdf0e10cSrcweir    $localbranddir =~ s/\Q$separator\E\s*$//;
357*cdf0e10cSrcweir    my $extensiondir = $localbranddir . $separator . "share" . $separator . "extensions";
358*cdf0e10cSrcweir    my $preregdir = $localbranddir . $separator . "share" . $separator . "prereg" . $separator . "bundled";
359*cdf0e10cSrcweir
360*cdf0e10cSrcweir    return ($extensiondir, $preregdir);
361*cdf0e10cSrcweir}
362*cdf0e10cSrcweir
363*cdf0e10cSrcweir########################################################
364*cdf0e10cSrcweir# Finding all files with a specified file extension
365*cdf0e10cSrcweir# in a specified directory.
366*cdf0e10cSrcweir########################################################
367*cdf0e10cSrcweir
368*cdf0e10cSrcweirsub find_file_with_file_extension
369*cdf0e10cSrcweir{
370*cdf0e10cSrcweir    my ($extension, $dir) = @_;
371*cdf0e10cSrcweir
372*cdf0e10cSrcweir    my @allfiles = ();
373*cdf0e10cSrcweir    my @sourcefiles = ();
374*cdf0e10cSrcweir
375*cdf0e10cSrcweir    $dir =~ s/\Q$separator\E\s*$//;
376*cdf0e10cSrcweir
377*cdf0e10cSrcweir    opendir(DIR, $dir);
378*cdf0e10cSrcweir    @sourcefiles = readdir(DIR);
379*cdf0e10cSrcweir    closedir(DIR);
380*cdf0e10cSrcweir
381*cdf0e10cSrcweir    my $onefile;
382*cdf0e10cSrcweir
383*cdf0e10cSrcweir    foreach $onefile (@sourcefiles)
384*cdf0e10cSrcweir    {
385*cdf0e10cSrcweir        if ((!($onefile eq ".")) && (!($onefile eq "..")))
386*cdf0e10cSrcweir        {
387*cdf0e10cSrcweir            if ( $onefile =~ /^\s*(\S.*?)\.$extension\s*$/ )
388*cdf0e10cSrcweir            {
389*cdf0e10cSrcweir                push(@allfiles, $onefile)
390*cdf0e10cSrcweir            }
391*cdf0e10cSrcweir        }
392*cdf0e10cSrcweir    }
393*cdf0e10cSrcweir
394*cdf0e10cSrcweir    return \@allfiles;
395*cdf0e10cSrcweir}
396*cdf0e10cSrcweir
397*cdf0e10cSrcweir##############################################################
398*cdf0e10cSrcweir# Creating a directory with all parent directories
399*cdf0e10cSrcweir##############################################################
400*cdf0e10cSrcweir
401*cdf0e10cSrcweirsub create_directories
402*cdf0e10cSrcweir{
403*cdf0e10cSrcweir    my ($directory) = @_;
404*cdf0e10cSrcweir
405*cdf0e10cSrcweir    if ( ! try_to_create_directory($directory) )
406*cdf0e10cSrcweir    {
407*cdf0e10cSrcweir        my $parentdir = $directory;
408*cdf0e10cSrcweir        get_path_from_fullqualifiedname(\$parentdir);
409*cdf0e10cSrcweir        create_directories($parentdir);   # recursive
410*cdf0e10cSrcweir    }
411*cdf0e10cSrcweir
412*cdf0e10cSrcweir    create_directory($directory);   # now it has to succeed
413*cdf0e10cSrcweir}
414*cdf0e10cSrcweir
415*cdf0e10cSrcweir##############################################################
416*cdf0e10cSrcweir# Creating one directory
417*cdf0e10cSrcweir##############################################################
418*cdf0e10cSrcweir
419*cdf0e10cSrcweirsub create_directory
420*cdf0e10cSrcweir{
421*cdf0e10cSrcweir    my ($directory) = @_;
422*cdf0e10cSrcweir
423*cdf0e10cSrcweir    if ( ! -d $directory ) { mkdir($directory, 0775); }
424*cdf0e10cSrcweir}
425*cdf0e10cSrcweir
426*cdf0e10cSrcweir##############################################################
427*cdf0e10cSrcweir# Trying to create a directory, no error if this fails
428*cdf0e10cSrcweir##############################################################
429*cdf0e10cSrcweir
430*cdf0e10cSrcweirsub try_to_create_directory
431*cdf0e10cSrcweir{
432*cdf0e10cSrcweir    my ($directory) = @_;
433*cdf0e10cSrcweir
434*cdf0e10cSrcweir    my $returnvalue = 1;
435*cdf0e10cSrcweir    my $created_directory = 0;
436*cdf0e10cSrcweir
437*cdf0e10cSrcweir    if (!(-d $directory))
438*cdf0e10cSrcweir    {
439*cdf0e10cSrcweir        $returnvalue = mkdir($directory, 0775);
440*cdf0e10cSrcweir
441*cdf0e10cSrcweir        if ($returnvalue)
442*cdf0e10cSrcweir        {
443*cdf0e10cSrcweir            $created_directory = 1;
444*cdf0e10cSrcweir
445*cdf0e10cSrcweir            my $localcall = "chmod 775 $directory \>\/dev\/null 2\>\&1";
446*cdf0e10cSrcweir            system($localcall);
447*cdf0e10cSrcweir        }
448*cdf0e10cSrcweir        else
449*cdf0e10cSrcweir        {
450*cdf0e10cSrcweir            $created_directory = 0;
451*cdf0e10cSrcweir        }
452*cdf0e10cSrcweir    }
453*cdf0e10cSrcweir    else
454*cdf0e10cSrcweir    {
455*cdf0e10cSrcweir        $created_directory = 1;
456*cdf0e10cSrcweir    }
457*cdf0e10cSrcweir
458*cdf0e10cSrcweir    return $created_directory;
459*cdf0e10cSrcweir}
460*cdf0e10cSrcweir
461*cdf0e10cSrcweir###########################################
462*cdf0e10cSrcweir# Getting path from full file name
463*cdf0e10cSrcweir###########################################
464*cdf0e10cSrcweir
465*cdf0e10cSrcweirsub get_path_from_fullqualifiedname
466*cdf0e10cSrcweir{
467*cdf0e10cSrcweir    my ($longfilenameref) = @_;
468*cdf0e10cSrcweir
469*cdf0e10cSrcweir    if ( $$longfilenameref =~ /\Q$separator\E/ )    # Is there a separator in the path? Otherwise the path is empty.
470*cdf0e10cSrcweir    {
471*cdf0e10cSrcweir        if ( $$longfilenameref =~ /^\s*(\S.*\Q$separator\E)(\S.+\S?)/ )
472*cdf0e10cSrcweir        {
473*cdf0e10cSrcweir            $$longfilenameref = $1;
474*cdf0e10cSrcweir        }
475*cdf0e10cSrcweir    }
476*cdf0e10cSrcweir    else
477*cdf0e10cSrcweir    {
478*cdf0e10cSrcweir        $$longfilenameref = ""; # there is no path
479*cdf0e10cSrcweir    }
480*cdf0e10cSrcweir}
481*cdf0e10cSrcweir
482*cdf0e10cSrcweir##############################################################
483*cdf0e10cSrcweir# Getting file name from full file name
484*cdf0e10cSrcweir##############################################################
485*cdf0e10cSrcweir
486*cdf0e10cSrcweirsub make_absolute_filename_to_relative_filename
487*cdf0e10cSrcweir{
488*cdf0e10cSrcweir    my ($longfilenameref) = @_;
489*cdf0e10cSrcweir
490*cdf0e10cSrcweir    # Either '/' or '\'.
491*cdf0e10cSrcweir    if ( $$longfilenameref =~ /^.*[\/\\](\S.+\S?)/ )
492*cdf0e10cSrcweir    {
493*cdf0e10cSrcweir        $$longfilenameref = $1;
494*cdf0e10cSrcweir    }
495*cdf0e10cSrcweir}
496*cdf0e10cSrcweir
497*cdf0e10cSrcweir############################################
498*cdf0e10cSrcweir# Exiting the program with an error
499*cdf0e10cSrcweir# This function is used instead of "die"
500*cdf0e10cSrcweir############################################
501*cdf0e10cSrcweir
502*cdf0e10cSrcweirsub exit_program
503*cdf0e10cSrcweir{
504*cdf0e10cSrcweir    my ($message) = @_;
505*cdf0e10cSrcweir
506*cdf0e10cSrcweir    print "\n***************************************************************\n";
507*cdf0e10cSrcweir    print "$message\n";
508*cdf0e10cSrcweir    print "***************************************************************\n";
509*cdf0e10cSrcweir    remove_complete_directory($savetemppath, 1);
510*cdf0e10cSrcweir    print "\n" . get_time_string();
511*cdf0e10cSrcweir    exit(-1);
512*cdf0e10cSrcweir}
513*cdf0e10cSrcweir
514*cdf0e10cSrcweir#################################################################################
515*cdf0e10cSrcweir# Unpacking cabinet files with expand
516*cdf0e10cSrcweir#################################################################################
517*cdf0e10cSrcweir
518*cdf0e10cSrcweirsub unpack_cabinet_file
519*cdf0e10cSrcweir{
520*cdf0e10cSrcweir    my ($cabfilename, $unpackdir) = @_;
521*cdf0e10cSrcweir
522*cdf0e10cSrcweir    my $expandfile = "expand.exe"; # has to be in the PATH
523*cdf0e10cSrcweir
524*cdf0e10cSrcweir    # expand.exe has to be located in the system directory.
525*cdf0e10cSrcweir    # Cygwin has another tool expand.exe, that converts tabs to spaces. This cannot be used of course.
526*cdf0e10cSrcweir    # But this wrong expand.exe is typically in the PATH before this expand.exe, to unpack
527*cdf0e10cSrcweir    # cabinet files.
528*cdf0e10cSrcweir
529*cdf0e10cSrcweir    if ( $^O =~ /cygwin/i )
530*cdf0e10cSrcweir    {
531*cdf0e10cSrcweir        $expandfile = $ENV{'SYSTEMROOT'} . "/system32/expand.exe"; # Has to be located in the systemdirectory
532*cdf0e10cSrcweir        $expandfile =~ s/\\/\//;
533*cdf0e10cSrcweir        if ( ! -f $expandfile ) { exit_program("ERROR: Did not find file $expandfile in the Windows system folder!"); }
534*cdf0e10cSrcweir    }
535*cdf0e10cSrcweir
536*cdf0e10cSrcweir    my $expandlogfile = $unpackdir . $separator . "expand.log";
537*cdf0e10cSrcweir
538*cdf0e10cSrcweir    # exclude cabinet file
539*cdf0e10cSrcweir    # my $systemcall = $cabarc . " -o X " . $mergemodulehash->{'cabinetfile'};
540*cdf0e10cSrcweir
541*cdf0e10cSrcweir    my $systemcall = "";
542*cdf0e10cSrcweir    if ( $^O =~ /cygwin/i ) {
543*cdf0e10cSrcweir        my $localunpackdir = qx{cygpath -w "$unpackdir"};
544*cdf0e10cSrcweir        $localunpackdir =~ s/\\/\\\\/g;
545*cdf0e10cSrcweir
546*cdf0e10cSrcweir        my $localcabfilename = qx{cygpath -w "$cabfilename"};
547*cdf0e10cSrcweir        $localcabfilename =~ s/\\/\\\\/g;
548*cdf0e10cSrcweir        $localcabfilename =~ s/\s*$//g;
549*cdf0e10cSrcweir
550*cdf0e10cSrcweir        $systemcall = $expandfile . " " . $localcabfilename . " -F:\* " . $localunpackdir . " \>\/dev\/null 2\>\&1";
551*cdf0e10cSrcweir    }
552*cdf0e10cSrcweir    else
553*cdf0e10cSrcweir    {
554*cdf0e10cSrcweir        $systemcall = $expandfile . " " . $cabfilename . " -F:\* " . $unpackdir . " \> " . $expandlogfile;
555*cdf0e10cSrcweir    }
556*cdf0e10cSrcweir
557*cdf0e10cSrcweir    my $returnvalue = system($systemcall);
558*cdf0e10cSrcweir
559*cdf0e10cSrcweir    if ($returnvalue) { exit_program("ERROR: Could not execute $systemcall !"); }
560*cdf0e10cSrcweir}
561*cdf0e10cSrcweir
562*cdf0e10cSrcweir#################################################################################
563*cdf0e10cSrcweir# Extracting tables from msi database
564*cdf0e10cSrcweir#################################################################################
565*cdf0e10cSrcweir
566*cdf0e10cSrcweirsub extract_tables_from_database
567*cdf0e10cSrcweir{
568*cdf0e10cSrcweir    my ($fullmsidatabasepath, $workdir, $tablelist) = @_;
569*cdf0e10cSrcweir
570*cdf0e10cSrcweir    my $msidb = "msidb.exe";    # Has to be in the path
571*cdf0e10cSrcweir    if ( $localmsidbpath ) { $msidb = $localmsidbpath; }
572*cdf0e10cSrcweir    my $infoline = "";
573*cdf0e10cSrcweir    my $systemcall = "";
574*cdf0e10cSrcweir    my $returnvalue = "";
575*cdf0e10cSrcweir
576*cdf0e10cSrcweir    if ( $^O =~ /cygwin/i ) {
577*cdf0e10cSrcweir        chomp( $fullmsidatabasepath = qx{cygpath -w "$fullmsidatabasepath"} );
578*cdf0e10cSrcweir        # msidb.exe really wants backslashes. (And double escaping because system() expands the string.)
579*cdf0e10cSrcweir        $fullmsidatabasepath =~ s/\\/\\\\/g;
580*cdf0e10cSrcweir        $workdir =~ s/\\/\\\\/g;
581*cdf0e10cSrcweir        # and if there are still slashes, they also need to be double backslash
582*cdf0e10cSrcweir        $fullmsidatabasepath =~ s/\//\\\\/g;
583*cdf0e10cSrcweir        $workdir =~ s/\//\\\\/g;
584*cdf0e10cSrcweir    }
585*cdf0e10cSrcweir
586*cdf0e10cSrcweir    # Export of all tables by using "*"
587*cdf0e10cSrcweir
588*cdf0e10cSrcweir    $systemcall = $msidb . " -d " . $fullmsidatabasepath . " -f " . $workdir . " -e $tablelist";
589*cdf0e10cSrcweir    print "\nAnalyzing msi database\n";
590*cdf0e10cSrcweir    $returnvalue = system($systemcall);
591*cdf0e10cSrcweir
592*cdf0e10cSrcweir    if ($returnvalue)
593*cdf0e10cSrcweir    {
594*cdf0e10cSrcweir        $infoline = "ERROR: Could not execute $systemcall !\n";
595*cdf0e10cSrcweir        exit_program($infoline);
596*cdf0e10cSrcweir    }
597*cdf0e10cSrcweir}
598*cdf0e10cSrcweir
599*cdf0e10cSrcweir########################################################
600*cdf0e10cSrcweir# Check, if this installation set contains
601*cdf0e10cSrcweir# internal cabinet files included into the msi
602*cdf0e10cSrcweir# database.
603*cdf0e10cSrcweir########################################################
604*cdf0e10cSrcweir
605*cdf0e10cSrcweirsub check_for_internal_cabfiles
606*cdf0e10cSrcweir{
607*cdf0e10cSrcweir    my ($cabfilehash) = @_;
608*cdf0e10cSrcweir
609*cdf0e10cSrcweir    my $contains_internal_cabfiles = 0;
610*cdf0e10cSrcweir    my %allcabfileshash = ();
611*cdf0e10cSrcweir
612*cdf0e10cSrcweir    foreach my $filename ( keys %{$cabfilehash} )
613*cdf0e10cSrcweir    {
614*cdf0e10cSrcweir        if ( $filename =~ /^\s*\#/ )     # starting with a hash
615*cdf0e10cSrcweir        {
616*cdf0e10cSrcweir            $contains_internal_cabfiles = 1;
617*cdf0e10cSrcweir            # setting real filename without hash as key and name with hash as value
618*cdf0e10cSrcweir            my $realfilename = $filename;
619*cdf0e10cSrcweir            $realfilename =~ s/^\s*\#//;
620*cdf0e10cSrcweir            $allcabfileshash{$realfilename} = $filename;
621*cdf0e10cSrcweir        }
622*cdf0e10cSrcweir    }
623*cdf0e10cSrcweir
624*cdf0e10cSrcweir    return ( $contains_internal_cabfiles, \%allcabfileshash );
625*cdf0e10cSrcweir}
626*cdf0e10cSrcweir
627*cdf0e10cSrcweir#################################################################
628*cdf0e10cSrcweir# Exclude all cab files from the msi database.
629*cdf0e10cSrcweir#################################################################
630*cdf0e10cSrcweir
631*cdf0e10cSrcweirsub extract_cabs_from_database
632*cdf0e10cSrcweir{
633*cdf0e10cSrcweir    my ($msidatabase, $allcabfiles) = @_;
634*cdf0e10cSrcweir
635*cdf0e10cSrcweir    my $infoline = "";
636*cdf0e10cSrcweir    my $fullsuccess = 1;
637*cdf0e10cSrcweir    my $msidb = "msidb.exe";    # Has to be in the path
638*cdf0e10cSrcweir    if ( $localmsidbpath ) { $msidb = $localmsidbpath; }
639*cdf0e10cSrcweir
640*cdf0e10cSrcweir    my @all_excluded_cabfiles = ();
641*cdf0e10cSrcweir
642*cdf0e10cSrcweir    if( $^O =~ /cygwin/i )
643*cdf0e10cSrcweir    {
644*cdf0e10cSrcweir        $msidatabase = qx{cygpath -w "$msidatabase"};
645*cdf0e10cSrcweir        $msidatabase =~ s/\\/\\\\/g;
646*cdf0e10cSrcweir        $msidatabase =~ s/\s*$//g;
647*cdf0e10cSrcweir    }
648*cdf0e10cSrcweir    else
649*cdf0e10cSrcweir    {
650*cdf0e10cSrcweir        # msidb.exe really wants backslashes. (And double escaping because system() expands the string.)
651*cdf0e10cSrcweir        $msidatabase =~ s/\//\\\\/g;
652*cdf0e10cSrcweir    }
653*cdf0e10cSrcweir
654*cdf0e10cSrcweir    foreach my $onefile ( keys %{$allcabfiles} )
655*cdf0e10cSrcweir    {
656*cdf0e10cSrcweir        my $systemcall = $msidb . " -d " . $msidatabase . " -x " . $onefile;
657*cdf0e10cSrcweir        system($systemcall);
658*cdf0e10cSrcweir        push(@all_excluded_cabfiles, $onefile);
659*cdf0e10cSrcweir    }
660*cdf0e10cSrcweir
661*cdf0e10cSrcweir    \@all_excluded_cabfiles;
662*cdf0e10cSrcweir}
663*cdf0e10cSrcweir
664*cdf0e10cSrcweir################################################################################
665*cdf0e10cSrcweir# Collect all DiskIds to the corresponding cabinet files from Media.idt.
666*cdf0e10cSrcweir################################################################################
667*cdf0e10cSrcweir
668*cdf0e10cSrcweirsub analyze_media_file
669*cdf0e10cSrcweir{
670*cdf0e10cSrcweir    my ($filecontent) = @_;
671*cdf0e10cSrcweir
672*cdf0e10cSrcweir    my %diskidhash = ();
673*cdf0e10cSrcweir
674*cdf0e10cSrcweir    for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
675*cdf0e10cSrcweir    {
676*cdf0e10cSrcweir        if ( $i < 3 ) { next; }
677*cdf0e10cSrcweir
678*cdf0e10cSrcweir        if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ )
679*cdf0e10cSrcweir        {
680*cdf0e10cSrcweir            my $diskid = $1;
681*cdf0e10cSrcweir            my $cabfile = $4;
682*cdf0e10cSrcweir
683*cdf0e10cSrcweir            $diskidhash{$cabfile} = $diskid;
684*cdf0e10cSrcweir        }
685*cdf0e10cSrcweir    }
686*cdf0e10cSrcweir
687*cdf0e10cSrcweir    return \%diskidhash;
688*cdf0e10cSrcweir}
689*cdf0e10cSrcweir
690*cdf0e10cSrcweirsub analyze_customaction_file
691*cdf0e10cSrcweir{
692*cdf0e10cSrcweir    my ($filecontent) = @_;
693*cdf0e10cSrcweir
694*cdf0e10cSrcweir    my $register_extensions_exists = 0;
695*cdf0e10cSrcweir
696*cdf0e10cSrcweir    my %table = ();
697*cdf0e10cSrcweir
698*cdf0e10cSrcweir    for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
699*cdf0e10cSrcweir    {
700*cdf0e10cSrcweir        if ( ${$filecontent}[$i] =~ /^\s*RegisterExtensions\s+/ )
701*cdf0e10cSrcweir        {
702*cdf0e10cSrcweir            $register_extensions_exists = 1;
703*cdf0e10cSrcweir            last;
704*cdf0e10cSrcweir        }
705*cdf0e10cSrcweir    }
706*cdf0e10cSrcweir
707*cdf0e10cSrcweir    return $register_extensions_exists;
708*cdf0e10cSrcweir}
709*cdf0e10cSrcweir
710*cdf0e10cSrcweir################################################################################
711*cdf0e10cSrcweir# Analyzing the content of Directory.idt
712*cdf0e10cSrcweir#################################################################################
713*cdf0e10cSrcweir
714*cdf0e10cSrcweirsub analyze_directory_file
715*cdf0e10cSrcweir{
716*cdf0e10cSrcweir    my ($filecontent) = @_;
717*cdf0e10cSrcweir
718*cdf0e10cSrcweir    my %table = ();
719*cdf0e10cSrcweir
720*cdf0e10cSrcweir    for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
721*cdf0e10cSrcweir    {
722*cdf0e10cSrcweir        if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; }
723*cdf0e10cSrcweir
724*cdf0e10cSrcweir        if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\s*$/ )
725*cdf0e10cSrcweir        {
726*cdf0e10cSrcweir            my $dir = $1;
727*cdf0e10cSrcweir            my $parent = $2;
728*cdf0e10cSrcweir            my $name = $3;
729*cdf0e10cSrcweir
730*cdf0e10cSrcweir            if ( $name =~ /^\s*(.*?)\s*\:\s*(.*?)\s*$/ ) { $name = $2; }
731*cdf0e10cSrcweir            if ( $name =~ /^\s*(.*?)\s*\|\s*(.*?)\s*$/ ) { $name = $2; }
732*cdf0e10cSrcweir
733*cdf0e10cSrcweir            my %helphash = ();
734*cdf0e10cSrcweir            $helphash{'Directory_Parent'} = $parent;
735*cdf0e10cSrcweir            $helphash{'DefaultDir'} = $name;
736*cdf0e10cSrcweir            $table{$dir} = \%helphash;
737*cdf0e10cSrcweir        }
738*cdf0e10cSrcweir    }
739*cdf0e10cSrcweir
740*cdf0e10cSrcweir    return \%table;
741*cdf0e10cSrcweir}
742*cdf0e10cSrcweir
743*cdf0e10cSrcweir#################################################################################
744*cdf0e10cSrcweir# Analyzing the content of Component.idt
745*cdf0e10cSrcweir#################################################################################
746*cdf0e10cSrcweir
747*cdf0e10cSrcweirsub analyze_component_file
748*cdf0e10cSrcweir{
749*cdf0e10cSrcweir    my ($filecontent) = @_;
750*cdf0e10cSrcweir
751*cdf0e10cSrcweir    my %table = ();
752*cdf0e10cSrcweir
753*cdf0e10cSrcweir    for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
754*cdf0e10cSrcweir    {
755*cdf0e10cSrcweir        if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; }
756*cdf0e10cSrcweir
757*cdf0e10cSrcweir        if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ )
758*cdf0e10cSrcweir        {
759*cdf0e10cSrcweir            my $component = $1;
760*cdf0e10cSrcweir            my $dir = $3;
761*cdf0e10cSrcweir
762*cdf0e10cSrcweir            $table{$component} = $dir;
763*cdf0e10cSrcweir        }
764*cdf0e10cSrcweir    }
765*cdf0e10cSrcweir
766*cdf0e10cSrcweir    return \%table;
767*cdf0e10cSrcweir}
768*cdf0e10cSrcweir
769*cdf0e10cSrcweir#################################################################################
770*cdf0e10cSrcweir# Analyzing the content of File.idt
771*cdf0e10cSrcweir#################################################################################
772*cdf0e10cSrcweir
773*cdf0e10cSrcweirsub analyze_file_file
774*cdf0e10cSrcweir{
775*cdf0e10cSrcweir    my ($filecontent) = @_;
776*cdf0e10cSrcweir
777*cdf0e10cSrcweir    my %table = ();
778*cdf0e10cSrcweir    my %fileorder = ();
779*cdf0e10cSrcweir    my $maxsequence = 0;
780*cdf0e10cSrcweir
781*cdf0e10cSrcweir    for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
782*cdf0e10cSrcweir    {
783*cdf0e10cSrcweir        if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; }
784*cdf0e10cSrcweir
785*cdf0e10cSrcweir        if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ )
786*cdf0e10cSrcweir        {
787*cdf0e10cSrcweir            my $file = $1;
788*cdf0e10cSrcweir            my $comp = $2;
789*cdf0e10cSrcweir            my $filename = $3;
790*cdf0e10cSrcweir            my $sequence = $8;
791*cdf0e10cSrcweir
792*cdf0e10cSrcweir            if ( $filename =~ /^\s*(.*?)\s*\|\s*(.*?)\s*$/ ) { $filename = $2; }
793*cdf0e10cSrcweir
794*cdf0e10cSrcweir            my %helphash = ();
795*cdf0e10cSrcweir            $helphash{'Component'} = $comp;
796*cdf0e10cSrcweir            $helphash{'FileName'} = $filename;
797*cdf0e10cSrcweir            $helphash{'Sequence'} = $sequence;
798*cdf0e10cSrcweir
799*cdf0e10cSrcweir            $table{$file} = \%helphash;
800*cdf0e10cSrcweir
801*cdf0e10cSrcweir            $fileorder{$sequence} = $file;
802*cdf0e10cSrcweir
803*cdf0e10cSrcweir            if ( $sequence > $maxsequence ) { $maxsequence = $sequence; }
804*cdf0e10cSrcweir        }
805*cdf0e10cSrcweir    }
806*cdf0e10cSrcweir
807*cdf0e10cSrcweir    return (\%table, \%fileorder, $maxsequence);
808*cdf0e10cSrcweir}
809*cdf0e10cSrcweir
810*cdf0e10cSrcweir####################################################################################
811*cdf0e10cSrcweir# Recursively creating the directory tree
812*cdf0e10cSrcweir####################################################################################
813*cdf0e10cSrcweir
814*cdf0e10cSrcweirsub create_directory_tree
815*cdf0e10cSrcweir{
816*cdf0e10cSrcweir    my ($parent, $pathcollector, $fulldir, $dirhash) = @_;
817*cdf0e10cSrcweir
818*cdf0e10cSrcweir    foreach my $dir ( keys %{$dirhash} )
819*cdf0e10cSrcweir    {
820*cdf0e10cSrcweir        if (( $dirhash->{$dir}->{'Directory_Parent'} eq $parent ) && ( $dirhash->{$dir}->{'DefaultDir'} ne "." ))
821*cdf0e10cSrcweir        {
822*cdf0e10cSrcweir            my $dirname = $dirhash->{$dir}->{'DefaultDir'};
823*cdf0e10cSrcweir            # Create the directory
824*cdf0e10cSrcweir            my $newdir = $fulldir . $separator . $dirname;
825*cdf0e10cSrcweir            if ( ! -f $newdir ) { mkdir $newdir; }
826*cdf0e10cSrcweir            # Saving in collector
827*cdf0e10cSrcweir            $pathcollector->{$dir} = $newdir;
828*cdf0e10cSrcweir            # Iteration
829*cdf0e10cSrcweir            create_directory_tree($dir, $pathcollector, $newdir, $dirhash);
830*cdf0e10cSrcweir        }
831*cdf0e10cSrcweir    }
832*cdf0e10cSrcweir}
833*cdf0e10cSrcweir
834*cdf0e10cSrcweir####################################################################################
835*cdf0e10cSrcweir# Creating the directory tree
836*cdf0e10cSrcweir####################################################################################
837*cdf0e10cSrcweir
838*cdf0e10cSrcweirsub create_directory_structure
839*cdf0e10cSrcweir{
840*cdf0e10cSrcweir    my ($dirhash, $targetdir) = @_;
841*cdf0e10cSrcweir
842*cdf0e10cSrcweir    print "Creating directories\n";
843*cdf0e10cSrcweir
844*cdf0e10cSrcweir    my %fullpathhash = ();
845*cdf0e10cSrcweir
846*cdf0e10cSrcweir    my @startparents = ("TARGETDIR", "INSTALLLOCATION");
847*cdf0e10cSrcweir
848*cdf0e10cSrcweir    foreach $dir (@startparents) { create_directory_tree($dir, \%fullpathhash, $targetdir, $dirhash); }
849*cdf0e10cSrcweir
850*cdf0e10cSrcweir    # Also adding the pathes of the startparents
851*cdf0e10cSrcweir    foreach $dir (@startparents)
852*cdf0e10cSrcweir    {
853*cdf0e10cSrcweir        if ( ! exists($fullpathhash{$dir}) ) { $fullpathhash{$dir} = $targetdir; }
854*cdf0e10cSrcweir    }
855*cdf0e10cSrcweir
856*cdf0e10cSrcweir    return \%fullpathhash;
857*cdf0e10cSrcweir}
858*cdf0e10cSrcweir
859*cdf0e10cSrcweir####################################################################################
860*cdf0e10cSrcweir# Cygwin: Setting privileges for files
861*cdf0e10cSrcweir####################################################################################
862*cdf0e10cSrcweir
863*cdf0e10cSrcweirsub change_privileges
864*cdf0e10cSrcweir{
865*cdf0e10cSrcweir    my ($destfile, $privileges) = @_;
866*cdf0e10cSrcweir
867*cdf0e10cSrcweir    my $localcall = "chmod $privileges " . "\"" . $destfile . "\"";
868*cdf0e10cSrcweir    system($localcall);
869*cdf0e10cSrcweir}
870*cdf0e10cSrcweir
871*cdf0e10cSrcweir####################################################################################
872*cdf0e10cSrcweir# Cygwin: Setting privileges for files recursively
873*cdf0e10cSrcweir####################################################################################
874*cdf0e10cSrcweir
875*cdf0e10cSrcweirsub change_privileges_full
876*cdf0e10cSrcweir{
877*cdf0e10cSrcweir    my ($target) = @_;
878*cdf0e10cSrcweir
879*cdf0e10cSrcweir    print "Changing privileges\n";
880*cdf0e10cSrcweir
881*cdf0e10cSrcweir    my $localcall = "chmod -R 755 " . "\"" . $target . "\"";
882*cdf0e10cSrcweir    system($localcall);
883*cdf0e10cSrcweir}
884*cdf0e10cSrcweir
885*cdf0e10cSrcweir######################################################
886*cdf0e10cSrcweir# Creating a new directory with defined privileges
887*cdf0e10cSrcweir######################################################
888*cdf0e10cSrcweir
889*cdf0e10cSrcweirsub create_directory_with_privileges
890*cdf0e10cSrcweir{
891*cdf0e10cSrcweir    my ($directory, $privileges) = @_;
892*cdf0e10cSrcweir
893*cdf0e10cSrcweir    my $returnvalue = 1;
894*cdf0e10cSrcweir    my $infoline = "";
895*cdf0e10cSrcweir
896*cdf0e10cSrcweir    if (!(-d $directory))
897*cdf0e10cSrcweir    {
898*cdf0e10cSrcweir        my $localprivileges = oct("0".$privileges); # changes "777" to 0777
899*cdf0e10cSrcweir        $returnvalue = mkdir($directory, $localprivileges);
900*cdf0e10cSrcweir
901*cdf0e10cSrcweir        if ($returnvalue)
902*cdf0e10cSrcweir        {
903*cdf0e10cSrcweir            my $localcall = "chmod $privileges $directory \>\/dev\/null 2\>\&1";
904*cdf0e10cSrcweir            system($localcall);
905*cdf0e10cSrcweir        }
906*cdf0e10cSrcweir    }
907*cdf0e10cSrcweir    else
908*cdf0e10cSrcweir    {
909*cdf0e10cSrcweir        my $localcall = "chmod $privileges $directory \>\/dev\/null 2\>\&1";
910*cdf0e10cSrcweir        system($localcall);
911*cdf0e10cSrcweir    }
912*cdf0e10cSrcweir}
913*cdf0e10cSrcweir
914*cdf0e10cSrcweir######################################################
915*cdf0e10cSrcweir# Creating a unique directory with pid extension
916*cdf0e10cSrcweir######################################################
917*cdf0e10cSrcweir
918*cdf0e10cSrcweirsub create_pid_directory
919*cdf0e10cSrcweir{
920*cdf0e10cSrcweir    my ($directory) = @_;
921*cdf0e10cSrcweir
922*cdf0e10cSrcweir    $directory =~ s/\Q$separator\E\s*$//;
923*cdf0e10cSrcweir    my $pid = $$;           # process id
924*cdf0e10cSrcweir    my $time = time();      # time
925*cdf0e10cSrcweir
926*cdf0e10cSrcweir    $directory = $directory . "_" . $pid . $time;
927*cdf0e10cSrcweir
928*cdf0e10cSrcweir    if ( ! -d $directory ) { create_directory($directory); }
929*cdf0e10cSrcweir    else { exit_program("ERROR: Directory $directory already exists!"); }
930*cdf0e10cSrcweir
931*cdf0e10cSrcweir    return $directory;
932*cdf0e10cSrcweir}
933*cdf0e10cSrcweir
934*cdf0e10cSrcweir####################################################################################
935*cdf0e10cSrcweir# Copying files into installation set
936*cdf0e10cSrcweir####################################################################################
937*cdf0e10cSrcweir
938*cdf0e10cSrcweirsub copy_files_into_directory_structure
939*cdf0e10cSrcweir{
940*cdf0e10cSrcweir    my ($fileorder, $filehash, $componenthash, $fullpathhash, $maxsequence, $unpackdir, $installdir, $dirhash) = @_;
941*cdf0e10cSrcweir
942*cdf0e10cSrcweir    print "Copying files\n";
943*cdf0e10cSrcweir
944*cdf0e10cSrcweir    my $unopkgfile = "";
945*cdf0e10cSrcweir
946*cdf0e10cSrcweir    for ( my $i = 1; $i <= $maxsequence; $i++ )
947*cdf0e10cSrcweir    {
948*cdf0e10cSrcweir        if ( exists($fileorder->{$i}) )
949*cdf0e10cSrcweir        {
950*cdf0e10cSrcweir            my $file = $fileorder->{$i};
951*cdf0e10cSrcweir            if ( ! exists($filehash->{$file}->{'Component'}) ) { exit_program("ERROR: Did not find component for file: \"$file\"."); }
952*cdf0e10cSrcweir            my $component = $filehash->{$file}->{'Component'};
953*cdf0e10cSrcweir            if ( ! exists($componenthash->{$component}) ) { exit_program("ERROR: Did not find directory for component: \"$component\"."); }
954*cdf0e10cSrcweir            my $dirname = $componenthash->{$component};
955*cdf0e10cSrcweir            if ( ! exists($fullpathhash->{$dirname}) ) { exit_program("ERROR: Did not find full directory path for dir: \"$dirname\"."); }
956*cdf0e10cSrcweir            my $destdir = $fullpathhash->{$dirname};
957*cdf0e10cSrcweir            if ( ! exists($filehash->{$file}->{'FileName'}) ) { exit_program("ERROR: Did not find \"FileName\" for file: \"$file\"."); }
958*cdf0e10cSrcweir            my $destfile = $filehash->{$file}->{'FileName'};
959*cdf0e10cSrcweir
960*cdf0e10cSrcweir            $destfile = $destdir . $separator . $destfile;
961*cdf0e10cSrcweir            my $sourcefile = $unpackdir . $separator . $file;
962*cdf0e10cSrcweir
963*cdf0e10cSrcweir            if ( ! -f $sourcefile )
964*cdf0e10cSrcweir            {
965*cdf0e10cSrcweir                # It is possible, that this was an unpacked file
966*cdf0e10cSrcweir                # Looking in the dirhash, to find the subdirectory in the installation set (the id is $dirname)
967*cdf0e10cSrcweir                # subdir is not recursively analyzed, only one directory.
968*cdf0e10cSrcweir
969*cdf0e10cSrcweir                my $oldsourcefile = $sourcefile;
970*cdf0e10cSrcweir                my $subdir = "";
971*cdf0e10cSrcweir                if ( exists($dirhash->{$dirname}->{'DefaultDir'}) ) { $subdir = $dirhash->{$dirname}->{'DefaultDir'} . $separator; }
972*cdf0e10cSrcweir                my $realfilename = $filehash->{$file}->{'FileName'};
973*cdf0e10cSrcweir                my $localinstalldir = $installdir;
974*cdf0e10cSrcweir
975*cdf0e10cSrcweir                $localinstalldir =~ s/\\\s*$//;
976*cdf0e10cSrcweir                $localinstalldir =~ s/\/\s*$//;
977*cdf0e10cSrcweir
978*cdf0e10cSrcweir                $sourcefile = $localinstalldir . $separator . $subdir . $realfilename;
979*cdf0e10cSrcweir
980*cdf0e10cSrcweir                if ( ! -f $sourcefile ) { exit_program("ERROR: File not found: \"$oldsourcefile\" (or \"$sourcefile\")."); }
981*cdf0e10cSrcweir            }
982*cdf0e10cSrcweir
983*cdf0e10cSrcweir            my $copyreturn = copy($sourcefile, $destfile);
984*cdf0e10cSrcweir
985*cdf0e10cSrcweir            if ( ! $copyreturn) { exit_program("ERROR: Could not copy $source to $dest\n"); }
986*cdf0e10cSrcweir
987*cdf0e10cSrcweir            # Searching unopkg.exe
988*cdf0e10cSrcweir            if ( $destfile =~ /unopkg\.exe\s*$/ ) { $unopkgfile = $destfile; }
989*cdf0e10cSrcweir            # if (( $^O =~ /cygwin/i ) && ( $destfile =~ /\.exe\s*$/ )) { change_privileges($destfile, "775"); }
990*cdf0e10cSrcweir        }
991*cdf0e10cSrcweir        # else  # allowing missing sequence numbers ?
992*cdf0e10cSrcweir        # {
993*cdf0e10cSrcweir        #   exit_program("ERROR: No file assigned to sequence $i");
994*cdf0e10cSrcweir        # }
995*cdf0e10cSrcweir    }
996*cdf0e10cSrcweir
997*cdf0e10cSrcweir    return ($unopkgfile);
998*cdf0e10cSrcweir}
999*cdf0e10cSrcweir
1000*cdf0e10cSrcweir######################################################
1001*cdf0e10cSrcweir# Removing a complete directory with subdirectories
1002*cdf0e10cSrcweir######################################################
1003*cdf0e10cSrcweir
1004*cdf0e10cSrcweirsub remove_complete_directory
1005*cdf0e10cSrcweir{
1006*cdf0e10cSrcweir    my ($directory, $start) = @_;
1007*cdf0e10cSrcweir
1008*cdf0e10cSrcweir    my @content = ();
1009*cdf0e10cSrcweir    my $infoline = "";
1010*cdf0e10cSrcweir
1011*cdf0e10cSrcweir    $directory =~ s/\Q$separator\E\s*$//;
1012*cdf0e10cSrcweir
1013*cdf0e10cSrcweir    if ( -d $directory )
1014*cdf0e10cSrcweir    {
1015*cdf0e10cSrcweir        if ( $start ) { print "Removing directory $directory\n"; }
1016*cdf0e10cSrcweir
1017*cdf0e10cSrcweir        opendir(DIR, $directory);
1018*cdf0e10cSrcweir        @content = readdir(DIR);
1019*cdf0e10cSrcweir        closedir(DIR);
1020*cdf0e10cSrcweir
1021*cdf0e10cSrcweir        my $oneitem;
1022*cdf0e10cSrcweir
1023*cdf0e10cSrcweir        foreach $oneitem (@content)
1024*cdf0e10cSrcweir        {
1025*cdf0e10cSrcweir            if ((!($oneitem eq ".")) && (!($oneitem eq "..")))
1026*cdf0e10cSrcweir            {
1027*cdf0e10cSrcweir                my $item = $directory . $separator . $oneitem;
1028*cdf0e10cSrcweir
1029*cdf0e10cSrcweir                if ( -f $item || -l $item )     # deleting files or links
1030*cdf0e10cSrcweir                {
1031*cdf0e10cSrcweir                    unlink($item);
1032*cdf0e10cSrcweir                }
1033*cdf0e10cSrcweir
1034*cdf0e10cSrcweir                if ( -d $item )     # recursive
1035*cdf0e10cSrcweir                {
1036*cdf0e10cSrcweir                    remove_complete_directory($item, 0);
1037*cdf0e10cSrcweir                }
1038*cdf0e10cSrcweir            }
1039*cdf0e10cSrcweir        }
1040*cdf0e10cSrcweir
1041*cdf0e10cSrcweir        # try to remove empty directory
1042*cdf0e10cSrcweir        my $returnvalue = rmdir $directory;
1043*cdf0e10cSrcweir        if ( ! $returnvalue ) { print "Warning: Problem with removing empty dir $directory\n"; }
1044*cdf0e10cSrcweir    }
1045*cdf0e10cSrcweir}
1046*cdf0e10cSrcweir
1047*cdf0e10cSrcweir####################################################################################
1048*cdf0e10cSrcweir# Defining a temporary path
1049*cdf0e10cSrcweir####################################################################################
1050*cdf0e10cSrcweir
1051*cdf0e10cSrcweirsub get_temppath
1052*cdf0e10cSrcweir{
1053*cdf0e10cSrcweir    my $temppath = "";
1054*cdf0e10cSrcweir
1055*cdf0e10cSrcweir    if (( $ENV{'TMP'} ) || ( $ENV{'TEMP'} ))
1056*cdf0e10cSrcweir    {
1057*cdf0e10cSrcweir        if ( $ENV{'TMP'} ) { $temppath = $ENV{'TMP'}; }
1058*cdf0e10cSrcweir        elsif ( $ENV{'TEMP'} )  { $temppath = $ENV{'TEMP'}; }
1059*cdf0e10cSrcweir
1060*cdf0e10cSrcweir        $temppath =~ s/\Q$separator\E\s*$//;    # removing ending slashes and backslashes
1061*cdf0e10cSrcweir        $temppath = $temppath . $separator . $globaltempdirname;
1062*cdf0e10cSrcweir        create_directory_with_privileges($temppath, "777");
1063*cdf0e10cSrcweir
1064*cdf0e10cSrcweir        my $dirsave = $temppath;
1065*cdf0e10cSrcweir
1066*cdf0e10cSrcweir        $temppath = $temppath . $separator . "a";
1067*cdf0e10cSrcweir        $temppath = create_pid_directory($temppath);
1068*cdf0e10cSrcweir
1069*cdf0e10cSrcweir        if ( ! -d $temppath ) { exit_program("ERROR: Failed to create directory $temppath ! Possible reason: Wrong privileges in directory $dirsave."); }
1070*cdf0e10cSrcweir
1071*cdf0e10cSrcweir        if ( $^O =~ /cygwin/i )
1072*cdf0e10cSrcweir        {
1073*cdf0e10cSrcweir            $temppath =~ s/\\/\\\\/g;
1074*cdf0e10cSrcweir            chomp( $temppath = qx{cygpath -w "$temppath"} );
1075*cdf0e10cSrcweir        }
1076*cdf0e10cSrcweir
1077*cdf0e10cSrcweir        $savetemppath = $temppath;
1078*cdf0e10cSrcweir    }
1079*cdf0e10cSrcweir    else
1080*cdf0e10cSrcweir    {
1081*cdf0e10cSrcweir        exit_program("ERROR: Could not set temporary directory (TMP and TEMP not set!).");
1082*cdf0e10cSrcweir    }
1083*cdf0e10cSrcweir
1084*cdf0e10cSrcweir    return $temppath;
1085*cdf0e10cSrcweir}
1086*cdf0e10cSrcweir
1087*cdf0e10cSrcweir####################################################################################
1088*cdf0e10cSrcweir# Registering extensions
1089*cdf0e10cSrcweir####################################################################################
1090*cdf0e10cSrcweir
1091*cdf0e10cSrcweirsub register_extensions_sync
1092*cdf0e10cSrcweir{
1093*cdf0e10cSrcweir    my ($unopkgfile, $localtemppath, $preregdir) = @_;
1094*cdf0e10cSrcweir
1095*cdf0e10cSrcweir    if ( $preregdir eq "" )
1096*cdf0e10cSrcweir    {
1097*cdf0e10cSrcweir        my $logtext = "ERROR: Failed to determine \"prereg\" folder for extension registration! Please check your installation set.";
1098*cdf0e10cSrcweir        print $logtext . "\n";
1099*cdf0e10cSrcweir        exit_program($logtext);
1100*cdf0e10cSrcweir    }
1101*cdf0e10cSrcweir
1102*cdf0e10cSrcweir    my $from = cwd();
1103*cdf0e10cSrcweir
1104*cdf0e10cSrcweir    my $path = $unopkgfile;
1105*cdf0e10cSrcweir    get_path_from_fullqualifiedname(\$path);
1106*cdf0e10cSrcweir    $path =~ s/\\\s*$//;
1107*cdf0e10cSrcweir    $path =~ s/\/\s*$//;
1108*cdf0e10cSrcweir
1109*cdf0e10cSrcweir    my $executable = $unopkgfile;
1110*cdf0e10cSrcweir    make_absolute_filename_to_relative_filename(\$executable);
1111*cdf0e10cSrcweir
1112*cdf0e10cSrcweir    chdir($path);
1113*cdf0e10cSrcweir
1114*cdf0e10cSrcweir    if ( ! $path_displayed )
1115*cdf0e10cSrcweir    {
1116*cdf0e10cSrcweir        print "... current dir: $path ...\n";
1117*cdf0e10cSrcweir        $path_displayed = 1;
1118*cdf0e10cSrcweir    }
1119*cdf0e10cSrcweir
1120*cdf0e10cSrcweir    $localtemppath =~ s/\\/\//g;
1121*cdf0e10cSrcweir
1122*cdf0e10cSrcweir    if ( $^O =~ /cygwin/i ) {
1123*cdf0e10cSrcweir        $executable = "./" . $executable;
1124*cdf0e10cSrcweir        $preregdir = qx{cygpath -m "$preregdir"};
1125*cdf0e10cSrcweir        chomp($preregdir);
1126*cdf0e10cSrcweir    }
1127*cdf0e10cSrcweir
1128*cdf0e10cSrcweir    $preregdir =~ s/\/\s*$//g;
1129*cdf0e10cSrcweir
1130*cdf0e10cSrcweir    my $systemcall = $executable . " sync --verbose 2\>\&1 |";
1131*cdf0e10cSrcweir
1132*cdf0e10cSrcweir    print "... $systemcall\n";
1133*cdf0e10cSrcweir
1134*cdf0e10cSrcweir    my @unopkgoutput = ();
1135*cdf0e10cSrcweir
1136*cdf0e10cSrcweir    open (UNOPKG, $systemcall);
1137*cdf0e10cSrcweir    while (<UNOPKG>) {push(@unopkgoutput, $_); }
1138*cdf0e10cSrcweir    close (UNOPKG);
1139*cdf0e10cSrcweir
1140*cdf0e10cSrcweir    my $returnvalue = $?;   # $? contains the return value of the systemcall
1141*cdf0e10cSrcweir
1142*cdf0e10cSrcweir    if ($returnvalue)
1143*cdf0e10cSrcweir    {
1144*cdf0e10cSrcweir        print "ERROR: Could not execute \"$systemcall\"!\nExitcode: '$returnvalue'\n";
1145*cdf0e10cSrcweir        for ( my $j = 0; $j <= $#unopkgoutput; $j++ ) { print "$unopkgoutput[$j]"; }
1146*cdf0e10cSrcweir        exit_program("ERROR: $systemcall failed!");
1147*cdf0e10cSrcweir    }
1148*cdf0e10cSrcweir
1149*cdf0e10cSrcweir    chdir($from);
1150*cdf0e10cSrcweir}
1151*cdf0e10cSrcweir
1152*cdf0e10cSrcweir####################################################################################
1153*cdf0e10cSrcweir# Registering all extensions located in /share/extension/install
1154*cdf0e10cSrcweir####################################################################################
1155*cdf0e10cSrcweir
1156*cdf0e10cSrcweirsub register_extensions
1157*cdf0e10cSrcweir{
1158*cdf0e10cSrcweir    my ($unopkgfile, $temppath, $preregdir) = @_;
1159*cdf0e10cSrcweir
1160*cdf0e10cSrcweir    print "Registering extensions:\n";
1161*cdf0e10cSrcweir
1162*cdf0e10cSrcweir    if (( ! -f $unopkgfile ) || ( $unopkgfile eq "" ))
1163*cdf0e10cSrcweir    {
1164*cdf0e10cSrcweir        print("WARNING: Could not find unopkg.exe (Language Pack?)!\n");
1165*cdf0e10cSrcweir    }
1166*cdf0e10cSrcweir    else
1167*cdf0e10cSrcweir    {
1168*cdf0e10cSrcweir        register_extensions_sync($unopkgfile, $temppath, $preregdir);
1169*cdf0e10cSrcweir        remove_complete_directory($temppath, 1);
1170*cdf0e10cSrcweir    }
1171*cdf0e10cSrcweir
1172*cdf0e10cSrcweir}
1173*cdf0e10cSrcweir
1174*cdf0e10cSrcweir####################################################################################
1175*cdf0e10cSrcweir# Reading one file
1176*cdf0e10cSrcweir####################################################################################
1177*cdf0e10cSrcweir
1178*cdf0e10cSrcweirsub read_file
1179*cdf0e10cSrcweir{
1180*cdf0e10cSrcweir    my ($localfile) = @_;
1181*cdf0e10cSrcweir
1182*cdf0e10cSrcweir    my @localfile = ();
1183*cdf0e10cSrcweir
1184*cdf0e10cSrcweir    open( IN, "<$localfile" ) || exit_program("ERROR: Cannot open file $localfile for reading");
1185*cdf0e10cSrcweir
1186*cdf0e10cSrcweir    #   Don't use "my @localfile = <IN>" here, because
1187*cdf0e10cSrcweir    #   perl has a problem with the internal "large_and_huge_malloc" function
1188*cdf0e10cSrcweir    #   when calling perl using MacOS 10.5 with a perl built with MacOS 10.4
1189*cdf0e10cSrcweir    while ( $line = <IN> ) {
1190*cdf0e10cSrcweir        push @localfile, $line;
1191*cdf0e10cSrcweir    }
1192*cdf0e10cSrcweir
1193*cdf0e10cSrcweir    close( IN );
1194*cdf0e10cSrcweir
1195*cdf0e10cSrcweir    return \@localfile;
1196*cdf0e10cSrcweir}
1197*cdf0e10cSrcweir
1198*cdf0e10cSrcweir###############################################################
1199*cdf0e10cSrcweir# Setting the time string for the
1200*cdf0e10cSrcweir# Summary Information stream in the
1201*cdf0e10cSrcweir# msi database of the admin installations.
1202*cdf0e10cSrcweir###############################################################
1203*cdf0e10cSrcweir
1204*cdf0e10cSrcweirsub get_sis_time_string
1205*cdf0e10cSrcweir{
1206*cdf0e10cSrcweir    # Syntax: <yyyy/mm/dd hh:mm:ss>
1207*cdf0e10cSrcweir    my $second = (localtime())[0];
1208*cdf0e10cSrcweir    my $minute = (localtime())[1];
1209*cdf0e10cSrcweir    my $hour = (localtime())[2];
1210*cdf0e10cSrcweir    my $day = (localtime())[3];
1211*cdf0e10cSrcweir    my $month = (localtime())[4];
1212*cdf0e10cSrcweir    my $year = 1900 + (localtime())[5];
1213*cdf0e10cSrcweir    $month++;
1214*cdf0e10cSrcweir
1215*cdf0e10cSrcweir    if ( $second < 10 ) { $second = "0" . $second; }
1216*cdf0e10cSrcweir    if ( $minute < 10 ) { $minute = "0" . $minute; }
1217*cdf0e10cSrcweir    if ( $hour < 10 ) { $hour = "0" . $hour; }
1218*cdf0e10cSrcweir    if ( $day < 10 ) { $day = "0" . $day; }
1219*cdf0e10cSrcweir    if ( $month < 10 ) { $month = "0" . $month; }
1220*cdf0e10cSrcweir
1221*cdf0e10cSrcweir    my $timestring = $year . "/" . $month . "/" . $day . " " . $hour . ":" . $minute . ":" . $second;
1222*cdf0e10cSrcweir
1223*cdf0e10cSrcweir    return $timestring;
1224*cdf0e10cSrcweir}
1225*cdf0e10cSrcweir
1226*cdf0e10cSrcweir###############################################################
1227*cdf0e10cSrcweir# Writing content of administrative installations into
1228*cdf0e10cSrcweir# Summary Information Stream of msi database.
1229*cdf0e10cSrcweir# This is required for example for following
1230*cdf0e10cSrcweir# patch processes using Windows Installer service.
1231*cdf0e10cSrcweir###############################################################
1232*cdf0e10cSrcweir
1233*cdf0e10cSrcweirsub write_sis_info
1234*cdf0e10cSrcweir{
1235*cdf0e10cSrcweir    my ($msidatabase) = @_;
1236*cdf0e10cSrcweir
1237*cdf0e10cSrcweir    print "Setting SIS in msi database\n";
1238*cdf0e10cSrcweir
1239*cdf0e10cSrcweir    if ( ! -f $msidatabase ) { exit_program("ERROR: Cannot find file $msidatabase"); }
1240*cdf0e10cSrcweir
1241*cdf0e10cSrcweir    my $msiinfo = "msiinfo.exe";    # Has to be in the path
1242*cdf0e10cSrcweir    my $infoline = "";
1243*cdf0e10cSrcweir    my $systemcall = "";
1244*cdf0e10cSrcweir    my $returnvalue = "";
1245*cdf0e10cSrcweir
1246*cdf0e10cSrcweir    # Required setting for administrative installations:
1247*cdf0e10cSrcweir    # -w 4   (source files are unpacked),  wordcount
1248*cdf0e10cSrcweir    # -s <date of admin installation>, LastPrinted, Syntax: <yyyy/mm/dd hh:mm:ss>
1249*cdf0e10cSrcweir    # -l <person_making_admin_installation>, LastSavedBy
1250*cdf0e10cSrcweir
1251*cdf0e10cSrcweir    my $wordcount = 4;  # Unpacked files
1252*cdf0e10cSrcweir    my $lastprinted = get_sis_time_string();
1253*cdf0e10cSrcweir    my $lastsavedby = "Installer";
1254*cdf0e10cSrcweir
1255*cdf0e10cSrcweir    my $localmsidatabase = $msidatabase;
1256*cdf0e10cSrcweir
1257*cdf0e10cSrcweir    if( $^O =~ /cygwin/i )
1258*cdf0e10cSrcweir    {
1259*cdf0e10cSrcweir        $localmsidatabase = qx{cygpath -w "$localmsidatabase"};
1260*cdf0e10cSrcweir        $localmsidatabase =~ s/\\/\\\\/g;
1261*cdf0e10cSrcweir        $localmsidatabase =~ s/\s*$//g;
1262*cdf0e10cSrcweir    }
1263*cdf0e10cSrcweir
1264*cdf0e10cSrcweir    $systemcall = $msiinfo . " " . "\"" . $localmsidatabase . "\"" . " -w " . $wordcount . " -s " . "\"" . $lastprinted . "\"" . " -l $lastsavedby";
1265*cdf0e10cSrcweir
1266*cdf0e10cSrcweir    $returnvalue = system($systemcall);
1267*cdf0e10cSrcweir
1268*cdf0e10cSrcweir    if ($returnvalue)
1269*cdf0e10cSrcweir    {
1270*cdf0e10cSrcweir        $infoline = "ERROR: Could not execute $systemcall !\n";
1271*cdf0e10cSrcweir        exit_program($infoline);
1272*cdf0e10cSrcweir    }
1273*cdf0e10cSrcweir}
1274*cdf0e10cSrcweir
1275*cdf0e10cSrcweir###############################################################
1276*cdf0e10cSrcweir# Convert time string
1277*cdf0e10cSrcweir###############################################################
1278*cdf0e10cSrcweir
1279*cdf0e10cSrcweirsub convert_timestring
1280*cdf0e10cSrcweir{
1281*cdf0e10cSrcweir    my ($secondstring) = @_;
1282*cdf0e10cSrcweir
1283*cdf0e10cSrcweir    my $timestring = "";
1284*cdf0e10cSrcweir
1285*cdf0e10cSrcweir    if ( $secondstring < 60 )    # less than a minute
1286*cdf0e10cSrcweir    {
1287*cdf0e10cSrcweir        if ( $secondstring < 10 ) { $secondstring = "0" . $secondstring; }
1288*cdf0e10cSrcweir        $timestring = "00\:$secondstring min\.";
1289*cdf0e10cSrcweir    }
1290*cdf0e10cSrcweir    elsif ( $secondstring < 3600 )
1291*cdf0e10cSrcweir    {
1292*cdf0e10cSrcweir        my $minutes = $secondstring / 60;
1293*cdf0e10cSrcweir        my $seconds = $secondstring % 60;
1294*cdf0e10cSrcweir        if ( $minutes =~ /(\d*)\.\d*/ ) { $minutes = $1; }
1295*cdf0e10cSrcweir        if ( $minutes < 10 ) { $minutes = "0" . $minutes; }
1296*cdf0e10cSrcweir        if ( $seconds < 10 ) { $seconds = "0" . $seconds; }
1297*cdf0e10cSrcweir        $timestring = "$minutes\:$seconds min\.";
1298*cdf0e10cSrcweir    }
1299*cdf0e10cSrcweir    else    # more than one hour
1300*cdf0e10cSrcweir    {
1301*cdf0e10cSrcweir        my $hours = $secondstring / 3600;
1302*cdf0e10cSrcweir        my $secondstring = $secondstring % 3600;
1303*cdf0e10cSrcweir        my $minutes = $secondstring / 60;
1304*cdf0e10cSrcweir        my $seconds = $secondstring % 60;
1305*cdf0e10cSrcweir        if ( $hours =~ /(\d*)\.\d*/ ) { $hours = $1; }
1306*cdf0e10cSrcweir        if ( $minutes =~ /(\d*)\.\d*/ ) { $minutes = $1; }
1307*cdf0e10cSrcweir        if ( $hours < 10 ) { $hours = "0" . $hours; }
1308*cdf0e10cSrcweir        if ( $minutes < 10 ) { $minutes = "0" . $minutes; }
1309*cdf0e10cSrcweir        if ( $seconds < 10 ) { $seconds = "0" . $seconds; }
1310*cdf0e10cSrcweir        $timestring = "$hours\:$minutes\:$seconds hours";
1311*cdf0e10cSrcweir    }
1312*cdf0e10cSrcweir
1313*cdf0e10cSrcweir    return $timestring;
1314*cdf0e10cSrcweir}
1315*cdf0e10cSrcweir
1316*cdf0e10cSrcweir###############################################################
1317*cdf0e10cSrcweir# Returning time string for logging
1318*cdf0e10cSrcweir###############################################################
1319*cdf0e10cSrcweir
1320*cdf0e10cSrcweirsub get_time_string
1321*cdf0e10cSrcweir{
1322*cdf0e10cSrcweir    my $currenttime = time();
1323*cdf0e10cSrcweir    $currenttime = $currenttime - $starttime;
1324*cdf0e10cSrcweir    $currenttime = convert_timestring($currenttime);
1325*cdf0e10cSrcweir    $currenttime = localtime() . " \(" . $currenttime . "\)\n";
1326*cdf0e10cSrcweir    return $currenttime;
1327*cdf0e10cSrcweir}
1328*cdf0e10cSrcweir
1329*cdf0e10cSrcweir####################################################################################
1330*cdf0e10cSrcweir# Simulating an administrative installation
1331*cdf0e10cSrcweir####################################################################################
1332*cdf0e10cSrcweir
1333*cdf0e10cSrcweir$starttime = time();
1334*cdf0e10cSrcweir
1335*cdf0e10cSrcweirgetparameter();
1336*cdf0e10cSrcweircontrolparameter();
1337*cdf0e10cSrcweircheck_local_msidb();
1338*cdf0e10cSrcweircheck_system_path();
1339*cdf0e10cSrcweirmy $temppath = get_temppath();
1340*cdf0e10cSrcweir
1341*cdf0e10cSrcweirprint("\nmsi database: $databasepath\n");
1342*cdf0e10cSrcweirprint("Destination directory: $targetdir\n" );
1343*cdf0e10cSrcweir
1344*cdf0e10cSrcweirmy $helperdir = $temppath . $separator . "installhelper";
1345*cdf0e10cSrcweircreate_directory($helperdir);
1346*cdf0e10cSrcweir
1347*cdf0e10cSrcweir# Get File.idt, Component.idt and Directory.idt from database
1348*cdf0e10cSrcweir
1349*cdf0e10cSrcweirmy $tablelist = "File Directory Component Media CustomAction";
1350*cdf0e10cSrcweirextract_tables_from_database($databasepath, $helperdir, $tablelist);
1351*cdf0e10cSrcweir
1352*cdf0e10cSrcweir# Set unpackdir
1353*cdf0e10cSrcweirmy $unpackdir = $helperdir . $separator . "unpack";
1354*cdf0e10cSrcweircreate_directory($unpackdir);
1355*cdf0e10cSrcweir
1356*cdf0e10cSrcweir# Reading media table to check for internal cabinet files
1357*cdf0e10cSrcweirmy $filename = $helperdir . $separator . "Media.idt";
1358*cdf0e10cSrcweirif ( ! -f $filename ) { exit_program("ERROR: Could not find required file: $filename !"); }
1359*cdf0e10cSrcweirmy $filecontent = read_file($filename);
1360*cdf0e10cSrcweirmy $cabfilehash = analyze_media_file($filecontent);
1361*cdf0e10cSrcweir
1362*cdf0e10cSrcweir# Check, if there are internal cab files
1363*cdf0e10cSrcweirmy ( $contains_internal_cabfiles, $all_internal_cab_files) = check_for_internal_cabfiles($cabfilehash);
1364*cdf0e10cSrcweir
1365*cdf0e10cSrcweirif ( $contains_internal_cabfiles )
1366*cdf0e10cSrcweir{
1367*cdf0e10cSrcweir    # Set unpackdir
1368*cdf0e10cSrcweir    my $cabdir = $helperdir . $separator . "internal_cabs";
1369*cdf0e10cSrcweir    create_directory($cabdir);
1370*cdf0e10cSrcweir    my $from = cwd();
1371*cdf0e10cSrcweir    chdir($cabdir);
1372*cdf0e10cSrcweir    # Exclude all cabinet files from database
1373*cdf0e10cSrcweir    my $all_excluded_cabs = extract_cabs_from_database($databasepath, $all_internal_cab_files);
1374*cdf0e10cSrcweir    print "Unpacking files from internal cabinet file(s)\n";
1375*cdf0e10cSrcweir    foreach my $cabfile ( @{$all_excluded_cabs} ) { unpack_cabinet_file($cabfile, $unpackdir); }
1376*cdf0e10cSrcweir    chdir($from);
1377*cdf0e10cSrcweir}
1378*cdf0e10cSrcweir
1379*cdf0e10cSrcweir# Unpack all cab files into $helperdir, cab files must be located next to msi database
1380*cdf0e10cSrcweirmy $installdir = $databasepath;
1381*cdf0e10cSrcweir
1382*cdf0e10cSrcweirget_path_from_fullqualifiedname(\$installdir);
1383*cdf0e10cSrcweir
1384*cdf0e10cSrcweirmy $databasefilename = $databasepath;
1385*cdf0e10cSrcweirmake_absolute_filename_to_relative_filename(\$databasefilename);
1386*cdf0e10cSrcweir
1387*cdf0e10cSrcweirmy $cabfiles = find_file_with_file_extension("cab", $installdir);
1388*cdf0e10cSrcweir
1389*cdf0e10cSrcweirif (( $#{$cabfiles} < 0 ) && ( ! $contains_internal_cabfiles )) { exit_program("ERROR: Did not find any cab file in directory $installdir"); }
1390*cdf0e10cSrcweir
1391*cdf0e10cSrcweirprint "Unpacking files from cabinet file(s)\n";
1392*cdf0e10cSrcweirfor ( my $i = 0; $i <= $#{$cabfiles}; $i++ )
1393*cdf0e10cSrcweir{
1394*cdf0e10cSrcweir    my $cabfile = $installdir . $separator . ${$cabfiles}[$i];
1395*cdf0e10cSrcweir    unpack_cabinet_file($cabfile, $unpackdir);
1396*cdf0e10cSrcweir}
1397*cdf0e10cSrcweir
1398*cdf0e10cSrcweir# Reading tables
1399*cdf0e10cSrcweir$filename = $helperdir . $separator . "Directory.idt";
1400*cdf0e10cSrcweir$filecontent = read_file($filename);
1401*cdf0e10cSrcweirmy $dirhash = analyze_directory_file($filecontent);
1402*cdf0e10cSrcweir
1403*cdf0e10cSrcweir$filename = $helperdir . $separator . "Component.idt";
1404*cdf0e10cSrcweir$filecontent = read_file($filename);
1405*cdf0e10cSrcweirmy $componenthash = analyze_component_file($filecontent);
1406*cdf0e10cSrcweir
1407*cdf0e10cSrcweir$filename = $helperdir . $separator . "File.idt";
1408*cdf0e10cSrcweir$filecontent = read_file($filename);
1409*cdf0e10cSrcweirmy ( $filehash, $fileorder, $maxsequence ) = analyze_file_file($filecontent);
1410*cdf0e10cSrcweir
1411*cdf0e10cSrcweir# Creating the directory structure
1412*cdf0e10cSrcweirmy $fullpathhash = create_directory_structure($dirhash, $targetdir);
1413*cdf0e10cSrcweir
1414*cdf0e10cSrcweir# Copying files
1415*cdf0e10cSrcweirmy ($unopkgfile) = copy_files_into_directory_structure($fileorder, $filehash, $componenthash, $fullpathhash, $maxsequence, $unpackdir, $installdir, $dirhash);
1416*cdf0e10cSrcweirif ( $^O =~ /cygwin/i ) { change_privileges_full($targetdir); }
1417*cdf0e10cSrcweir
1418*cdf0e10cSrcweirmy $msidatabase = $targetdir . $separator . $databasefilename;
1419*cdf0e10cSrcweirmy $copyreturn = copy($databasepath, $msidatabase);
1420*cdf0e10cSrcweirif ( ! $copyreturn) { exit_program("ERROR: Could not copy $source to $dest\n"); }
1421*cdf0e10cSrcweir
1422*cdf0e10cSrcweir# Reading tables
1423*cdf0e10cSrcweir$filename = $helperdir . $separator . "CustomAction.idt";
1424*cdf0e10cSrcweir$filecontent = read_file($filename);
1425*cdf0e10cSrcweirmy $register_extensions_exists = analyze_customaction_file($filecontent);
1426*cdf0e10cSrcweir
1427*cdf0e10cSrcweir# Removing empty dirs in extension folder
1428*cdf0e10cSrcweirmy ( $extensionfolder, $preregdir ) = get_extensions_dir($unopkgfile);
1429*cdf0e10cSrcweirif ( -d $extensionfolder ) { remove_empty_dirs_in_folder($extensionfolder, 1); }
1430*cdf0e10cSrcweir
1431*cdf0e10cSrcweirif ( $register_extensions_exists )
1432*cdf0e10cSrcweir{
1433*cdf0e10cSrcweir    # Registering extensions
1434*cdf0e10cSrcweir    register_extensions($unopkgfile, $temppath, $preregdir);
1435*cdf0e10cSrcweir}
1436*cdf0e10cSrcweir
1437*cdf0e10cSrcweir# Saving info in Summary Information Stream of msi database (required for following patches)
1438*cdf0e10cSrcweirif ( $msiinfo_available ) { write_sis_info($msidatabase); }
1439*cdf0e10cSrcweir
1440*cdf0e10cSrcweir# Removing the helper directory
1441*cdf0e10cSrcweirremove_complete_directory($temppath, 1);
1442*cdf0e10cSrcweir
1443*cdf0e10cSrcweirprint "\nSuccessful installation: " . get_time_string();
1444