xref: /AOO41X/main/solenv/bin/modules/installer/patch/InstallationSet.pm (revision 677600b012ebe37b797093a198c8d8edc3d08429)
1c9b362f6SAndre Fischer#**************************************************************
2c9b362f6SAndre Fischer#
3c9b362f6SAndre Fischer#  Licensed to the Apache Software Foundation (ASF) under one
4c9b362f6SAndre Fischer#  or more contributor license agreements.  See the NOTICE file
5c9b362f6SAndre Fischer#  distributed with this work for additional information
6c9b362f6SAndre Fischer#  regarding copyright ownership.  The ASF licenses this file
7c9b362f6SAndre Fischer#  to you under the Apache License, Version 2.0 (the
8c9b362f6SAndre Fischer#  "License"); you may not use this file except in compliance
9c9b362f6SAndre Fischer#  with the License.  You may obtain a copy of the License at
10c9b362f6SAndre Fischer#
11c9b362f6SAndre Fischer#    http://www.apache.org/licenses/LICENSE-2.0
12c9b362f6SAndre Fischer#
13c9b362f6SAndre Fischer#  Unless required by applicable law or agreed to in writing,
14c9b362f6SAndre Fischer#  software distributed under the License is distributed on an
15c9b362f6SAndre Fischer#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16c9b362f6SAndre Fischer#  KIND, either express or implied.  See the License for the
17c9b362f6SAndre Fischer#  specific language governing permissions and limitations
18c9b362f6SAndre Fischer#  under the License.
19c9b362f6SAndre Fischer#
20c9b362f6SAndre Fischer#**************************************************************
21c9b362f6SAndre Fischer
22c9b362f6SAndre Fischerpackage installer::patch::InstallationSet;
23c9b362f6SAndre Fischer
24c9b362f6SAndre Fischeruse installer::patch::Tools;
25c9b362f6SAndre Fischeruse installer::patch::Version;
26c9b362f6SAndre Fischeruse installer::logger;
27c9b362f6SAndre Fischer
289f91b7e3SAndre Fischeruse strict;
29c9b362f6SAndre Fischer
30*677600b0SAndre Fischer# Call Get7Zip() to get access to the filename of the 7z executable.
31*677600b0SAndre Fischermy $SevenZip = undef;
329f91b7e3SAndre Fischer
339f91b7e3SAndre Fischer
34c9b362f6SAndre Fischer=head1 NAME
35c9b362f6SAndre Fischer
36c9b362f6SAndre Fischer    package installer::patch::InstallationSet  -  Functions for handling installation sets
37c9b362f6SAndre Fischer
38c9b362f6SAndre Fischer=head1 DESCRIPTION
39c9b362f6SAndre Fischer
40c9b362f6SAndre Fischer    This package contains functions for unpacking the .exe files that
41c9b362f6SAndre Fischer    are created by the NSIS installer creator and the .cab files in
42c9b362f6SAndre Fischer    the installation sets.
43c9b362f6SAndre Fischer
44c9b362f6SAndre Fischer=cut
45c9b362f6SAndre Fischer
46*677600b0SAndre Fischer
47*677600b0SAndre Fischer
48*677600b0SAndre Fischer
49*677600b0SAndre Fischer=head2 Detect7ZipOnWindows ()
50*677600b0SAndre Fischer
51*677600b0SAndre Fischer    7Zip seems to be the only program able to unpack an NSIS installer.
52*677600b0SAndre Fischer    Search for it.
53*677600b0SAndre Fischer
54*677600b0SAndre Fischer=cut
55*677600b0SAndre Fischer
56*677600b0SAndre Fischersub Detect7ZipOnWindows ()
57*677600b0SAndre Fischer{
58*677600b0SAndre Fischer    # Use 'reg query' to read registry entry from Windows registry.
59*677600b0SAndre Fischer    my $registry_key = "HKEY_CURRENT_USER\\\\Software\\\\7-Zip";
60*677600b0SAndre Fischer    my $registry_value_name = "Path";
61*677600b0SAndre Fischer    my $command = sprintf("reg query %s /v %s", $registry_key, $registry_value_name);
62*677600b0SAndre Fischer    my $response = qx($command);
63*677600b0SAndre Fischer
64*677600b0SAndre Fischer    # Process the response.
65*677600b0SAndre Fischer    my $path_to_7zip = undef;
66*677600b0SAndre Fischer    if ($response =~ /\s+REG_SZ\s+([^\r\n]*)/m)
67*677600b0SAndre Fischer    {
68*677600b0SAndre Fischer        $path_to_7zip = $1;
69*677600b0SAndre Fischer    }
70*677600b0SAndre Fischer
71*677600b0SAndre Fischer    # If that failed, then make an educated guess.
72*677600b0SAndre Fischer    if ( ! defined $path_to_7zip)
73*677600b0SAndre Fischer    {
74*677600b0SAndre Fischer        $path_to_7zip = "c:\\Program Files\\7-Zip\\";
75*677600b0SAndre Fischer    }
76*677600b0SAndre Fischer
77*677600b0SAndre Fischer    # Check if the executable exists and is, well, executable.
78*677600b0SAndre Fischer    return undef unless -d $path_to_7zip;
79*677600b0SAndre Fischer    my $fullname = File::Spec->catfile($path_to_7zip, "7z.exe");
80*677600b0SAndre Fischer    return undef unless -f $fullname;
81*677600b0SAndre Fischer    return undef unless -x $fullname;
82*677600b0SAndre Fischer
83*677600b0SAndre Fischer    return $fullname;
84*677600b0SAndre Fischer}
85*677600b0SAndre Fischer
86*677600b0SAndre Fischer
87*677600b0SAndre Fischer
88*677600b0SAndre Fischer
89*677600b0SAndre Fischersub Get7Zip ()
90*677600b0SAndre Fischer{
91*677600b0SAndre Fischer    if ( ! defined $SevenZip)
92*677600b0SAndre Fischer    {
93*677600b0SAndre Fischer        if ($ENV{'OS'} eq "WNT")
94*677600b0SAndre Fischer        {
95*677600b0SAndre Fischer            $SevenZip = Detect7ZipOnWindows();
96*677600b0SAndre Fischer        }
97*677600b0SAndre Fischer        if ( ! defined $SevenZip)
98*677600b0SAndre Fischer        {
99*677600b0SAndre Fischer            # Use an empty string to avoid repeated (and failing) detections of a missing 7z.
100*677600b0SAndre Fischer            $SevenZip = "";
101*677600b0SAndre Fischer        }
102*677600b0SAndre Fischer    }
103*677600b0SAndre Fischer
104*677600b0SAndre Fischer    return $SevenZip eq "" ? undef : $SevenZip;
105*677600b0SAndre Fischer}
106*677600b0SAndre Fischer
107*677600b0SAndre Fischer
108*677600b0SAndre Fischer
109*677600b0SAndre Fischer
110c9b362f6SAndre Fischersub UnpackExe ($$)
111c9b362f6SAndre Fischer{
112c9b362f6SAndre Fischer    my ($filename, $destination_path) = @_;
113c9b362f6SAndre Fischer
114c9b362f6SAndre Fischer    $installer::logger::Info->printf("unpacking installation set to '%s'\n", $destination_path);
115c9b362f6SAndre Fischer
116c9b362f6SAndre Fischer    # Unpack to a temporary path and change its name to the destination path
117c9b362f6SAndre Fischer    # only when the unpacking has completed successfully.
1189f91b7e3SAndre Fischer    File::Path::make_path($destination_path);
119c9b362f6SAndre Fischer
1209f91b7e3SAndre Fischer    my $windows_filename = installer::patch::Tools::ToEscapedWindowsPath($filename);
1219f91b7e3SAndre Fischer    my $windows_destination_path = installer::patch::Tools::ToEscapedWindowsPath($destination_path);
122c9b362f6SAndre Fischer    my $command = join(" ",
123*677600b0SAndre Fischer        "\"".Get7Zip()."\"",
1249f91b7e3SAndre Fischer        "x",
1259f91b7e3SAndre Fischer        "-y",
1269f91b7e3SAndre Fischer        "-o".$windows_destination_path,
127c9b362f6SAndre Fischer        $windows_filename);
128c9b362f6SAndre Fischer    my $result = qx($command);
129*677600b0SAndre Fischer    if ( ! $result)
130*677600b0SAndre Fischer    {
131*677600b0SAndre Fischer        installer::exiter::exit_program(
132*677600b0SAndre Fischer            "ERROR: can not unpack downloadable installation set: ".$!,
133*677600b0SAndre Fischer            "installer::patch::InstallationSet::UnpackExe");
134*677600b0SAndre Fischer    }
135c9b362f6SAndre Fischer
136c9b362f6SAndre Fischer    # Check the existence of the .cab files.
1379f91b7e3SAndre Fischer    my $cab_filename = File::Spec->catfile($destination_path, "openoffice1.cab");
138c9b362f6SAndre Fischer    if ( ! -f $cab_filename)
139c9b362f6SAndre Fischer    {
140c9b362f6SAndre Fischer        installer::logger::PrintError("cab file '%s' was not extracted from installation set\n", $cab_filename);
141c9b362f6SAndre Fischer        return 0;
142c9b362f6SAndre Fischer    }
143c9b362f6SAndre Fischer    return 1;
144c9b362f6SAndre Fischer}
145c9b362f6SAndre Fischer
146c9b362f6SAndre Fischer
147c9b362f6SAndre Fischer
148c9b362f6SAndre Fischer
149c9b362f6SAndre Fischer=head2 UnpackCab($cab_filename, $destination_path)
150c9b362f6SAndre Fischer
151c9b362f6SAndre Fischer    Unpacking the cabinet file inside an .exe installation set is a
152c9b362f6SAndre Fischer    three step process because there is no directory information stored
153c9b362f6SAndre Fischer    inside the cab file.  This has to be taken from the 'File' and
154c9b362f6SAndre Fischer    'Directory' tables in the .msi file.
155c9b362f6SAndre Fischer
156c9b362f6SAndre Fischer    1. Setup the directory structure of all files in the cab from the 'File' and 'Directory' tables in the msi.
157c9b362f6SAndre Fischer
158c9b362f6SAndre Fischer    2. Unpack the cab file.
159c9b362f6SAndre Fischer
160c9b362f6SAndre Fischer    3. Move the files to their destination directories.
161c9b362f6SAndre Fischer
162c9b362f6SAndre Fischer=cut
163c9b362f6SAndre Fischersub UnpackCab ($$$)
164c9b362f6SAndre Fischer{
165c9b362f6SAndre Fischer    my ($cab_filename, $msi, $destination_path) = @_;
166c9b362f6SAndre Fischer
167c9b362f6SAndre Fischer    # Step 1
168c9b362f6SAndre Fischer    # Extract the directory structure from the 'File' and 'Directory' tables in the given msi.
169c9b362f6SAndre Fischer    $installer::logger::Info->printf("setting up directory tree\n");
170c9b362f6SAndre Fischer    my $file_table = $msi->GetTable("File");
1719f91b7e3SAndre Fischer    my $file_map = $msi->GetFileMap();
172c9b362f6SAndre Fischer
173c9b362f6SAndre Fischer    # Step 2
174c9b362f6SAndre Fischer    # Unpack the .cab file to a temporary path.
175c9b362f6SAndre Fischer    my $temporary_destination_path = $destination_path . ".tmp";
176c9b362f6SAndre Fischer    if ( -d $temporary_destination_path)
177c9b362f6SAndre Fischer    {
178c9b362f6SAndre Fischer        # Temporary directory already exists => cab file has already been unpacked (flat), nothing to do.
179*677600b0SAndre Fischer        printf("%s exists\n", $temporary_destination_path);
180c9b362f6SAndre Fischer        $installer::logger::Info->printf("cab file has already been unpacked to flat structure\n");
181c9b362f6SAndre Fischer    }
182c9b362f6SAndre Fischer    else
183c9b362f6SAndre Fischer    {
184c9b362f6SAndre Fischer        UnpackCabFlat($cab_filename, $temporary_destination_path, $file_table);
185c9b362f6SAndre Fischer    }
186c9b362f6SAndre Fischer
187c9b362f6SAndre Fischer    # Step 3
188c9b362f6SAndre Fischer    # Move the files to their destinations.
189c9b362f6SAndre Fischer    File::Path::make_path($destination_path);
190c9b362f6SAndre Fischer    $installer::logger::Info->printf("moving files to their directories\n");
191*677600b0SAndre Fischer    my $directory_map = $msi->GetDirectoryMap();
192*677600b0SAndre Fischer    my $office_menu_folder_name = $directory_map->{'INSTALLLOCATION'}->{'target_long_name'};
193c9b362f6SAndre Fischer    my $count = 0;
194c9b362f6SAndre Fischer    foreach my $file_row (@{$file_table->GetAllRows()})
195c9b362f6SAndre Fischer    {
196c9b362f6SAndre Fischer        my $unique_name = $file_row->GetValue('File');
197*677600b0SAndre Fischer        my $file_item = $file_map->{$unique_name};
198*677600b0SAndre Fischer        my $directory_item = $file_item->{'directory'};
199*677600b0SAndre Fischer        my $long_file_name = $file_item->{'long_name'};
200*677600b0SAndre Fischer        my $full_name = $directory_item->{'full_source_long_name'};
201*677600b0SAndre Fischer        # Strip away the leading OfficeMenuFolder part.
202*677600b0SAndre Fischer        $full_name =~ s/^$office_menu_folder_name\///;
203c9b362f6SAndre Fischer        my $flat_filename = File::Spec->catfile($temporary_destination_path, $unique_name);
204*677600b0SAndre Fischer        my $dir_path = File::Spec->catfile($destination_path, $full_name);
205*677600b0SAndre Fischer        my $dir_filename = File::Spec->catfile($dir_path, $long_file_name);
206c9b362f6SAndre Fischer
2079f91b7e3SAndre Fischer        if ( ! -d $dir_path)
2089f91b7e3SAndre Fischer        {
209c9b362f6SAndre Fischer            File::Path::make_path($dir_path);
2109f91b7e3SAndre Fischer        }
211*677600b0SAndre Fischer
212*677600b0SAndre Fischer        $installer::logger::Lang->printf("moving %s to %s\n", $flat_filename, $dir_filename);
213*677600b0SAndre Fischer        File::Copy::move($flat_filename, $dir_filename)
214*677600b0SAndre Fischer            || die("can not move file ".$flat_filename.":".$!);
215c9b362f6SAndre Fischer
216c9b362f6SAndre Fischer        ++$count;
217c9b362f6SAndre Fischer    }
218c9b362f6SAndre Fischer
219c9b362f6SAndre Fischer    # Cleanup.  Remove the temporary directory.  It should be empty by now.
220c9b362f6SAndre Fischer    rmdir($temporary_destination_path);
221c9b362f6SAndre Fischer}
222c9b362f6SAndre Fischer
223c9b362f6SAndre Fischer
224c9b362f6SAndre Fischer
225c9b362f6SAndre Fischer
226c9b362f6SAndre Fischer=head2 UnpackCabFlat ($cab_filename, $destination_path, $file_table)
227c9b362f6SAndre Fischer
228c9b362f6SAndre Fischer    Unpack the flat file structure of the $cab_filename to $destination_path.
229c9b362f6SAndre Fischer
230c9b362f6SAndre Fischer    In order to detect and handle an incomplete (arborted) previous
231c9b362f6SAndre Fischer    extraction, the cab file is unpacked to a temprorary directory
232c9b362f6SAndre Fischer    that after successful extraction is renamed to $destination_path.
233c9b362f6SAndre Fischer
234c9b362f6SAndre Fischer=cut
235c9b362f6SAndre Fischersub UnpackCabFlat ($$$)
236c9b362f6SAndre Fischer{
237c9b362f6SAndre Fischer    my ($cab_filename, $destination_path, $file_table) = @_;
238c9b362f6SAndre Fischer
239c9b362f6SAndre Fischer    # Unpack the .cab file to a temporary path (note that
240c9b362f6SAndre Fischer    # $destination_path may alreay bee a temporary path). Using a
241c9b362f6SAndre Fischer    # second one prevents the lengthy flat unpacking to be repeated
242c9b362f6SAndre Fischer    # when another step fails.
243c9b362f6SAndre Fischer
244c9b362f6SAndre Fischer    $installer::logger::Info->printf("unpacking cab file\n");
2459f91b7e3SAndre Fischer    File::Path::make_path($destination_path);
2469f91b7e3SAndre Fischer    my $windows_cab_filename = installer::patch::Tools::ToEscapedWindowsPath($cab_filename);
2479f91b7e3SAndre Fischer    my $windows_destination_path = installer::patch::Tools::ToEscapedWindowsPath($destination_path);
248c9b362f6SAndre Fischer    my $command = join(" ",
249*677600b0SAndre Fischer        "\"".Get7Zip()."\"",
250c9b362f6SAndre Fischer        "x", "-o".$windows_destination_path,
251c9b362f6SAndre Fischer        $windows_cab_filename,
252c9b362f6SAndre Fischer        "-y");
253c9b362f6SAndre Fischer    open my $cmd, $command."|";
254c9b362f6SAndre Fischer    my $extraction_count = 0;
255c9b362f6SAndre Fischer    my $file_count = $file_table->GetRowCount();
256c9b362f6SAndre Fischer    while (<$cmd>)
257c9b362f6SAndre Fischer    {
258c9b362f6SAndre Fischer        my $message = $_;
259c9b362f6SAndre Fischer        chomp($message);
260c9b362f6SAndre Fischer        ++$extraction_count;
261c9b362f6SAndre Fischer        printf("%4d/%4d  %3.2f%%   \r",
262c9b362f6SAndre Fischer            $extraction_count,
263c9b362f6SAndre Fischer            $file_count,
264c9b362f6SAndre Fischer            $extraction_count*100/$file_count);
265c9b362f6SAndre Fischer    }
266c9b362f6SAndre Fischer    close $cmd;
267c9b362f6SAndre Fischer}
268c9b362f6SAndre Fischer
269c9b362f6SAndre Fischer
270c9b362f6SAndre Fischer
271c9b362f6SAndre Fischer
2729f91b7e3SAndre Fischer=head GetUnpackedExePath ($version, $is_current_version, $language, $package_format, $product)
273c9b362f6SAndre Fischer
274c9b362f6SAndre Fischer    Convenience function that returns where a downloadable installation set is extracted to.
275c9b362f6SAndre Fischer
276c9b362f6SAndre Fischer=cut
2779f91b7e3SAndre Fischersub GetUnpackedExePath ($$$$$)
278c9b362f6SAndre Fischer{
2799f91b7e3SAndre Fischer    my ($version, $is_current_version, $language, $package_format, $product) = @_;
280c9b362f6SAndre Fischer
2819f91b7e3SAndre Fischer    my $path = GetUnpackedPath($version, $is_current_version, $language, $package_format, $product);
2829f91b7e3SAndre Fischer    return File::Spec->catfile($path, "unpacked");
283c9b362f6SAndre Fischer}
284c9b362f6SAndre Fischer
285c9b362f6SAndre Fischer
286c9b362f6SAndre Fischer
287c9b362f6SAndre Fischer
2889f91b7e3SAndre Fischer=head GetUnpackedCabPath ($version, $is_current_version, $language, $package_format, $product)
289c9b362f6SAndre Fischer
290c9b362f6SAndre Fischer    Convenience function that returns where a cab file is extracted
291c9b362f6SAndre Fischer    (with injected directory structure from the msi file) to.
292c9b362f6SAndre Fischer
293c9b362f6SAndre Fischer=cut
2949f91b7e3SAndre Fischersub GetUnpackedCabPath ($$$$$)
295c9b362f6SAndre Fischer{
2969f91b7e3SAndre Fischer    my ($version, $is_current_version, $language, $package_format, $product) = @_;
297c9b362f6SAndre Fischer
2989f91b7e3SAndre Fischer    my $path = GetUnpackedPath($version, $is_current_version, $language, $package_format, $product);
2999f91b7e3SAndre Fischer    return File::Spec->catfile($path, "unpacked");
300c9b362f6SAndre Fischer}
301c9b362f6SAndre Fischer
302c9b362f6SAndre Fischer
303c9b362f6SAndre Fischer
304c9b362f6SAndre Fischer
3059f91b7e3SAndre Fischer=head2 GetUnpackedPath($version, $is_current_version, $language, $package_format, $product)
306c9b362f6SAndre Fischer
307c9b362f6SAndre Fischer    Internal function for creating paths to where archives are unpacked.
308c9b362f6SAndre Fischer
309c9b362f6SAndre Fischer=cut
3109f91b7e3SAndre Fischersub GetUnpackedPath ($$$$$)
311c9b362f6SAndre Fischer{
3129f91b7e3SAndre Fischer    my ($version, $is_current_version, $language, $package_format, $product) = @_;
313c9b362f6SAndre Fischer
314c9b362f6SAndre Fischer    return File::Spec->catfile(
315c9b362f6SAndre Fischer        $ENV{'SRC_ROOT'},
316c9b362f6SAndre Fischer        "instsetoo_native",
317c9b362f6SAndre Fischer        $ENV{'INPATH'},
318c9b362f6SAndre Fischer        $product,
319c9b362f6SAndre Fischer        $package_format,
3209f91b7e3SAndre Fischer        installer::patch::Version::ArrayToDirectoryName(
3219f91b7e3SAndre Fischer            installer::patch::Version::StringToNumberArray($version)),
32260b96b8dSAndre Fischer        installer::languages::get_normalized_language($language));
323c9b362f6SAndre Fischer}
324c9b362f6SAndre Fischer
325c9b362f6SAndre Fischer
326c9b362f6SAndre Fischer
327c9b362f6SAndre Fischer
3289f91b7e3SAndre Fischersub GetMsiFilename ($$)
3299f91b7e3SAndre Fischer{
3309f91b7e3SAndre Fischer    my ($path, $version) = @_;
3319f91b7e3SAndre Fischer
3329f91b7e3SAndre Fischer    my $no_dot_version = installer::patch::Version::ArrayToNoDotName(
3339f91b7e3SAndre Fischer        installer::patch::Version::StringToNumberArray(
3349f91b7e3SAndre Fischer            $version));
3359f91b7e3SAndre Fischer    return File::Spec->catfile(
3369f91b7e3SAndre Fischer        $path,
3379f91b7e3SAndre Fischer        "openoffice" . $no_dot_version . ".msi");
3389f91b7e3SAndre Fischer}
3399f91b7e3SAndre Fischer
3409f91b7e3SAndre Fischer
3419f91b7e3SAndre Fischer
3429f91b7e3SAndre Fischer
3439f91b7e3SAndre Fischersub GetCabFilename ($$)
3449f91b7e3SAndre Fischer{
3459f91b7e3SAndre Fischer    my ($path, $version) = @_;
3469f91b7e3SAndre Fischer
3479f91b7e3SAndre Fischer    return File::Spec->catfile(
3489f91b7e3SAndre Fischer        $path,
3499f91b7e3SAndre Fischer        "openoffice1.cab");
3509f91b7e3SAndre Fischer}
3519f91b7e3SAndre Fischer
3529f91b7e3SAndre Fischer
3539f91b7e3SAndre Fischer
3549f91b7e3SAndre Fischer
355c9b362f6SAndre Fischer=head2 Download($language, $release_data, $filename)
356c9b362f6SAndre Fischer
357c9b362f6SAndre Fischer    Download an installation set to $filename.  The URL for the
358c9b362f6SAndre Fischer    download is taken from $release_data, a snippet from the
359c9b362f6SAndre Fischer    instsetoo_native/data/releases.xml file.
360c9b362f6SAndre Fischer
361c9b362f6SAndre Fischer=cut
362c9b362f6SAndre Fischersub Download ($$$)
363c9b362f6SAndre Fischer{
364c9b362f6SAndre Fischer    my ($language, $release_data, $filename) = @_;
365c9b362f6SAndre Fischer
366c9b362f6SAndre Fischer    my $url = $release_data->{'URL'};
367c9b362f6SAndre Fischer    $release_data->{'URL'} =~ /^(.*)\/([^\/]+)$/;
368c9b362f6SAndre Fischer    my ($location, $basename) = ($1,$2);
369c9b362f6SAndre Fischer
370c9b362f6SAndre Fischer    $installer::logger::Info->printf("downloading %s\n", $basename);
371c9b362f6SAndre Fischer    $installer::logger::Info->printf("    from '%s'\n", $location);
372c9b362f6SAndre Fischer    my $filesize = $release_data->{'file-size'};
373d575d58fSAndre Fischer    if (defined $filesize)
374d575d58fSAndre Fischer    {
375c9b362f6SAndre Fischer        $installer::logger::Info->printf("    expected size is %d\n", $filesize);
376d575d58fSAndre Fischer    }
377d575d58fSAndre Fischer    else
378d575d58fSAndre Fischer    {
379d575d58fSAndre Fischer        $installer::logger::Info->printf("    file size is not yet known\n");
380d575d58fSAndre Fischer    }
381c9b362f6SAndre Fischer    my $temporary_filename = $filename . ".part";
382c9b362f6SAndre Fischer    my $resume_size = 0;
383c9b362f6SAndre Fischer
384c9b362f6SAndre Fischer    # Prepare checksum.
385c9b362f6SAndre Fischer    my $checksum = undef;
386c9b362f6SAndre Fischer    my $checksum_type = $release_data->{'checksum-type'};
387c9b362f6SAndre Fischer    my $checksum_value = $release_data->{'checksum-value'};
388c9b362f6SAndre Fischer    my $digest = undef;
389d575d58fSAndre Fischer    if ( ! defined $checksum_value)
390d575d58fSAndre Fischer    {
391d575d58fSAndre Fischer        # No checksum available.  Skip test.
392d575d58fSAndre Fischer    }
393d575d58fSAndre Fischer    elsif ($checksum_type eq "sha256")
394c9b362f6SAndre Fischer    {
395c9b362f6SAndre Fischer        $digest = Digest->new("SHA-256");
396c9b362f6SAndre Fischer    }
397c9b362f6SAndre Fischer    elsif ($checksum_type eq "md5")
398c9b362f6SAndre Fischer    {
399c9b362f6SAndre Fischer        $digest = Digest->new("md5");
400c9b362f6SAndre Fischer    }
401c9b362f6SAndre Fischer    else
402c9b362f6SAndre Fischer    {
403c9b362f6SAndre Fischer        installer::logger::PrintError(
404c9b362f6SAndre Fischer            "checksum type %s is not supported.  Supported checksum types are: sha256,md5\n",
405c9b362f6SAndre Fischer            $checksum_type);
406c9b362f6SAndre Fischer        return 0;
407c9b362f6SAndre Fischer    }
408c9b362f6SAndre Fischer
409c9b362f6SAndre Fischer    # Download the extension.
410d575d58fSAndre Fischer    open my $out, ">$temporary_filename";
411c9b362f6SAndre Fischer    binmode($out);
412c9b362f6SAndre Fischer
413c9b362f6SAndre Fischer    my $mode = $|;
414c9b362f6SAndre Fischer    my $handle = select STDOUT;
415c9b362f6SAndre Fischer    $| = 1;
416c9b362f6SAndre Fischer    select $handle;
417c9b362f6SAndre Fischer
418c9b362f6SAndre Fischer    my $agent = LWP::UserAgent->new();
419c9b362f6SAndre Fischer    $agent->timeout(120);
420c9b362f6SAndre Fischer    $agent->show_progress(0);
421c9b362f6SAndre Fischer    my $last_was_redirect = 0;
422c9b362f6SAndre Fischer    my $bytes_read = 0;
423c9b362f6SAndre Fischer    $agent->add_handler('response_redirect'
424c9b362f6SAndre Fischer        => sub{
425c9b362f6SAndre Fischer            $last_was_redirect = 1;
426c9b362f6SAndre Fischer            return;
427c9b362f6SAndre Fischer        });
428c9b362f6SAndre Fischer    $agent->add_handler('response_data'
429c9b362f6SAndre Fischer        => sub{
430c9b362f6SAndre Fischer            if ($last_was_redirect)
431c9b362f6SAndre Fischer            {
432c9b362f6SAndre Fischer                $last_was_redirect = 0;
433c9b362f6SAndre Fischer                # Throw away the data we got so far.
434d575d58fSAndre Fischer                $digest->reset() if defined $digest;
435c9b362f6SAndre Fischer                close $out;
436c9b362f6SAndre Fischer                open $out, ">$temporary_filename";
437c9b362f6SAndre Fischer                binmode($out);
438c9b362f6SAndre Fischer            }
439c9b362f6SAndre Fischer            my($response,$agent,$h,$data)=@_;
440c9b362f6SAndre Fischer            print $out $data;
441d575d58fSAndre Fischer            $digest->add($data) if defined $digest;
442c9b362f6SAndre Fischer            $bytes_read += length($data);
443d575d58fSAndre Fischer            if (defined $filesize)
444d575d58fSAndre Fischer            {
445c9b362f6SAndre Fischer                printf("read %*d / %d  %d%%  \r",
446c9b362f6SAndre Fischer                    length($filesize),
447c9b362f6SAndre Fischer                    $bytes_read,
448c9b362f6SAndre Fischer                    $filesize,
449c9b362f6SAndre Fischer                    $bytes_read*100/$filesize);
450d575d58fSAndre Fischer            }
451d575d58fSAndre Fischer            else
452d575d58fSAndre Fischer            {
453d575d58fSAndre Fischer                printf("read %6.2f MB\r", $bytes_read/(1024.0*1024.0));
454d575d58fSAndre Fischer            }
455c9b362f6SAndre Fischer            });
456c9b362f6SAndre Fischer    my $response;
457c9b362f6SAndre Fischer    if ($resume_size > 0)
458c9b362f6SAndre Fischer    {
459c9b362f6SAndre Fischer        $response = $agent->get($url, 'Range' => "bytes=$resume_size-");
460c9b362f6SAndre Fischer    }
461c9b362f6SAndre Fischer    else
462c9b362f6SAndre Fischer    {
463c9b362f6SAndre Fischer        $response = $agent->get($url);
464c9b362f6SAndre Fischer    }
465c9b362f6SAndre Fischer    close $out;
466c9b362f6SAndre Fischer
467c9b362f6SAndre Fischer    $handle = select STDOUT;
468c9b362f6SAndre Fischer    $| = $mode;
469c9b362f6SAndre Fischer    select $handle;
470c9b362f6SAndre Fischer
471c9b362f6SAndre Fischer    $installer::logger::Info->print("                                        \r");
472c9b362f6SAndre Fischer
473c9b362f6SAndre Fischer    if ($response->is_success())
474c9b362f6SAndre Fischer    {
475d575d58fSAndre Fischer        if ( ! defined $digest
476d575d58fSAndre Fischer            || $digest->hexdigest() eq $checksum_value)
477c9b362f6SAndre Fischer        {
478d575d58fSAndre Fischer            $installer::logger::Info->print("download was successfull\n");
479c9b362f6SAndre Fischer            if ( ! rename($temporary_filename, $filename))
480c9b362f6SAndre Fischer            {
481c9b362f6SAndre Fischer                installer::logger::PrintError("can not rename '%s' to '%s'\n", $temporary_filename, $filename);
482c9b362f6SAndre Fischer                return 0;
483c9b362f6SAndre Fischer            }
484c9b362f6SAndre Fischer            else
485c9b362f6SAndre Fischer            {
486c9b362f6SAndre Fischer                return 1;
487c9b362f6SAndre Fischer            }
488c9b362f6SAndre Fischer        }
489c9b362f6SAndre Fischer        else
490c9b362f6SAndre Fischer        {
491c9b362f6SAndre Fischer            installer::logger::PrintError("%s checksum is wrong\n", $checksum_type);
492c9b362f6SAndre Fischer            return 0;
493c9b362f6SAndre Fischer        }
494c9b362f6SAndre Fischer    }
495c9b362f6SAndre Fischer    else
496c9b362f6SAndre Fischer    {
497c9b362f6SAndre Fischer        installer::logger::PrintError("there was a download error\n");
498c9b362f6SAndre Fischer        return 0;
499c9b362f6SAndre Fischer    }
500c9b362f6SAndre Fischer}
501c9b362f6SAndre Fischer
502c9b362f6SAndre Fischer
503c9b362f6SAndre Fischer
504c9b362f6SAndre Fischer
505c9b362f6SAndre Fischer=head2 ProvideDownloadSet ($version, $language, $package_format)
506c9b362f6SAndre Fischer
507c9b362f6SAndre Fischer    Download an installation set when it is not yet present to
508c9b362f6SAndre Fischer    $ENV{'TARFILE_LOCATION'}.  Verify the downloaded file with the
509c9b362f6SAndre Fischer    checksum that is extracted from the
510c9b362f6SAndre Fischer    instsetoo_native/data/releases.xml file.
511c9b362f6SAndre Fischer
512c9b362f6SAndre Fischer=cut
513c9b362f6SAndre Fischersub ProvideDownloadSet ($$$)
514c9b362f6SAndre Fischer{
515c9b362f6SAndre Fischer    my ($version, $language, $package_format) = @_;
516c9b362f6SAndre Fischer
517c9b362f6SAndre Fischer    my $release_item = installer::patch::ReleasesList::Instance()->{$version}->{$package_format}->{$language};
518*677600b0SAndre Fischer    return undef unless defined $release_item;
519c9b362f6SAndre Fischer
520c9b362f6SAndre Fischer    # Get basename of installation set from URL.
521c9b362f6SAndre Fischer    $release_item->{'URL'} =~ /^(.*)\/([^\/]+)$/;
522c9b362f6SAndre Fischer    my ($location, $basename) = ($1,$2);
523c9b362f6SAndre Fischer
524c9b362f6SAndre Fischer    # Is the installation set already present in ext_sources/ ?
525c9b362f6SAndre Fischer    my $need_download = 0;
526c9b362f6SAndre Fischer    my $ext_sources_filename = File::Spec->catfile(
527c9b362f6SAndre Fischer        $ENV{'TARFILE_LOCATION'},
528c9b362f6SAndre Fischer        $basename);
529c9b362f6SAndre Fischer    if ( ! -f $ext_sources_filename)
530c9b362f6SAndre Fischer    {
531c9b362f6SAndre Fischer        $installer::logger::Info->printf("download set is not in ext_sources/ (%s)\n", $ext_sources_filename);
532c9b362f6SAndre Fischer        $need_download = 1;
533c9b362f6SAndre Fischer    }
534c9b362f6SAndre Fischer    else
535c9b362f6SAndre Fischer    {
536c9b362f6SAndre Fischer        $installer::logger::Info->printf("download set exists at '%s'\n", $ext_sources_filename);
537d575d58fSAndre Fischer        if (defined $release_item->{'checksum-value'}
538d575d58fSAndre Fischer            && $release_item->{'checksum-type'} eq 'sha256')
539c9b362f6SAndre Fischer        {
540c9b362f6SAndre Fischer            $installer::logger::Info->printf("checking SHA256 checksum\n");
541c9b362f6SAndre Fischer            my $digest = Digest->new("SHA-256");
542c9b362f6SAndre Fischer            open my $in, "<", $ext_sources_filename;
543c9b362f6SAndre Fischer            $digest->addfile($in);
544c9b362f6SAndre Fischer            close $in;
545c9b362f6SAndre Fischer            if ($digest->hexdigest() ne $release_item->{'checksum-value'})
546c9b362f6SAndre Fischer            {
547c9b362f6SAndre Fischer                $installer::logger::Info->printf("    mismatch\n", $ext_sources_filename);
548c9b362f6SAndre Fischer                $need_download = 1;
549c9b362f6SAndre Fischer            }
550c9b362f6SAndre Fischer            else
551c9b362f6SAndre Fischer            {
552c9b362f6SAndre Fischer                $installer::logger::Info->printf("    match\n");
553c9b362f6SAndre Fischer            }
554c9b362f6SAndre Fischer        }
555c9b362f6SAndre Fischer    }
556c9b362f6SAndre Fischer
557c9b362f6SAndre Fischer    if ($need_download)
558c9b362f6SAndre Fischer    {
559c9b362f6SAndre Fischer        if ( ! installer::patch::InstallationSet::Download(
560c9b362f6SAndre Fischer            $language,
561c9b362f6SAndre Fischer            $release_item,
562c9b362f6SAndre Fischer            $ext_sources_filename))
563c9b362f6SAndre Fischer        {
564c9b362f6SAndre Fischer            return 0;
565c9b362f6SAndre Fischer        }
566c9b362f6SAndre Fischer        if ( ! -f $ext_sources_filename)
567c9b362f6SAndre Fischer        {
568c9b362f6SAndre Fischer            $installer::logger::Info->printf("download set could not be downloaded\n");
569c9b362f6SAndre Fischer            return 0;
570c9b362f6SAndre Fischer        }
571c9b362f6SAndre Fischer    }
572c9b362f6SAndre Fischer
573c9b362f6SAndre Fischer    return $ext_sources_filename;
574c9b362f6SAndre Fischer}
575c9b362f6SAndre Fischer
5769f91b7e3SAndre Fischer
5779f91b7e3SAndre Fischer
5789f91b7e3SAndre Fischer
5799f91b7e3SAndre Fischersub ProvideUnpackedExe ($$$$$)
5809f91b7e3SAndre Fischer{
5819f91b7e3SAndre Fischer    my ($version, $is_current_version, $language, $package_format, $product_name) = @_;
5829f91b7e3SAndre Fischer
5839f91b7e3SAndre Fischer    # Check if the exe has already been unpacked.
5849f91b7e3SAndre Fischer    my $unpacked_exe_path = installer::patch::InstallationSet::GetUnpackedExePath(
5859f91b7e3SAndre Fischer        $version,
5869f91b7e3SAndre Fischer        $is_current_version,
5879f91b7e3SAndre Fischer        $language,
5889f91b7e3SAndre Fischer        $package_format,
5899f91b7e3SAndre Fischer        $product_name);
5909f91b7e3SAndre Fischer    my $unpacked_exe_flag_filename = File::Spec->catfile($unpacked_exe_path, "__exe_is_unpacked");
5919f91b7e3SAndre Fischer    my $exe_is_unpacked = -f $unpacked_exe_flag_filename;
5929f91b7e3SAndre Fischer
5939f91b7e3SAndre Fischer    if ($exe_is_unpacked)
5949f91b7e3SAndre Fischer    {
5959f91b7e3SAndre Fischer        # Yes, exe has already been unpacked.  There is nothing more to do.
5969f91b7e3SAndre Fischer        $installer::logger::Info->printf("downloadable installation set has already been unpacked to\n");
5979f91b7e3SAndre Fischer        $installer::logger::Info->printf("    %s\n", $unpacked_exe_path);
5989f91b7e3SAndre Fischer        return 1;
5999f91b7e3SAndre Fischer    }
6009f91b7e3SAndre Fischer    elsif ($is_current_version)
6019f91b7e3SAndre Fischer    {
6029f91b7e3SAndre Fischer        # For the current version the exe is created from the unpacked
6039f91b7e3SAndre Fischer        # content and both are expected to be already present.
6049f91b7e3SAndre Fischer
6059f91b7e3SAndre Fischer        # In order to have the .cab and its unpacked content in one
6069f91b7e3SAndre Fischer        # directory and don't interfere with the creation of regular
6079f91b7e3SAndre Fischer        # installation sets, we copy the unpacked .exe into a separate
6089f91b7e3SAndre Fischer        # directory.
6099f91b7e3SAndre Fischer
6109f91b7e3SAndre Fischer        my $original_path = File::Spec->catfile(
6119f91b7e3SAndre Fischer            $ENV{'SRC_ROOT'},
6129f91b7e3SAndre Fischer            "instsetoo_native",
6139f91b7e3SAndre Fischer            $ENV{'INPATH'},
6149f91b7e3SAndre Fischer            $product_name,
6159f91b7e3SAndre Fischer            $package_format,
6169f91b7e3SAndre Fischer            "install",
6179f91b7e3SAndre Fischer            $language);
6189f91b7e3SAndre Fischer        $installer::logger::Info->printf("creating a copy\n");
6199f91b7e3SAndre Fischer        $installer::logger::Info->printf("    of %s\n", $original_path);
6209f91b7e3SAndre Fischer        $installer::logger::Info->printf("    at %s\n", $unpacked_exe_path);
6219f91b7e3SAndre Fischer        File::Path::make_path($unpacked_exe_path) unless -d $unpacked_exe_path;
6229f91b7e3SAndre Fischer	my ($file_count,$directory_count) = CopyRecursive($original_path, $unpacked_exe_path);
6239f91b7e3SAndre Fischer	return 0 if ( ! defined $file_count);
6249f91b7e3SAndre Fischer        $installer::logger::Info->printf("    copied %d files in %d directories\n",
6259f91b7e3SAndre Fischer	    $file_count,
6269f91b7e3SAndre Fischer	    $directory_count);
6279f91b7e3SAndre Fischer
628*677600b0SAndre Fischer        installer::patch::Tools::touch($unpacked_exe_flag_filename);
6299f91b7e3SAndre Fischer
6309f91b7e3SAndre Fischer        return 1;
6319f91b7e3SAndre Fischer    }
6329f91b7e3SAndre Fischer    else
6339f91b7e3SAndre Fischer    {
6349f91b7e3SAndre Fischer        # No, we have to unpack the exe.
6359f91b7e3SAndre Fischer
6369f91b7e3SAndre Fischer        # Provide the exe.
6379f91b7e3SAndre Fischer        my $filename = installer::patch::InstallationSet::ProvideDownloadSet(
6389f91b7e3SAndre Fischer            $version,
6399f91b7e3SAndre Fischer            $language,
6409f91b7e3SAndre Fischer            $package_format);
6419f91b7e3SAndre Fischer
6429f91b7e3SAndre Fischer        # Unpack it.
6439f91b7e3SAndre Fischer        if (defined $filename)
6449f91b7e3SAndre Fischer        {
6459f91b7e3SAndre Fischer            if (installer::patch::InstallationSet::UnpackExe($filename, $unpacked_exe_path))
6469f91b7e3SAndre Fischer            {
6479f91b7e3SAndre Fischer                $installer::logger::Info->printf("downloadable installation set has been unpacked to\n");
6489f91b7e3SAndre Fischer                $installer::logger::Info->printf("    %s\n", $unpacked_exe_path);
6499f91b7e3SAndre Fischer
650*677600b0SAndre Fischer                installer::patch::Tools::touch($unpacked_exe_flag_filename);
6519f91b7e3SAndre Fischer
6529f91b7e3SAndre Fischer                return 1;
6539f91b7e3SAndre Fischer            }
6549f91b7e3SAndre Fischer        }
6559f91b7e3SAndre Fischer        else
6569f91b7e3SAndre Fischer        {
6579f91b7e3SAndre Fischer            installer::logger::PrintError("could not provide .exe installation set at '%s'\n", $filename);
6589f91b7e3SAndre Fischer        }
6599f91b7e3SAndre Fischer    }
6609f91b7e3SAndre Fischer
6619f91b7e3SAndre Fischer    return 0;
6629f91b7e3SAndre Fischer}
6639f91b7e3SAndre Fischer
6649f91b7e3SAndre Fischer
6659f91b7e3SAndre Fischer
6669f91b7e3SAndre Fischer
6679f91b7e3SAndre Fischersub CopyRecursive ($$)
6689f91b7e3SAndre Fischer{
6699f91b7e3SAndre Fischer    my ($source_path, $destination_path) = @_;
6709f91b7e3SAndre Fischer
6719f91b7e3SAndre Fischer    return (undef,undef) unless -d $source_path;
6729f91b7e3SAndre Fischer
6739f91b7e3SAndre Fischer    my @todo = ([$source_path, $destination_path]);
6749f91b7e3SAndre Fischer    my $file_count = 0;
6759f91b7e3SAndre Fischer    my $directory_count = 0;
6769f91b7e3SAndre Fischer    while (scalar @todo > 0)
6779f91b7e3SAndre Fischer    {
6789f91b7e3SAndre Fischer	my ($source,$destination) = @{shift @todo};
6799f91b7e3SAndre Fischer
6809f91b7e3SAndre Fischer	next if ! -d $source;
6819f91b7e3SAndre Fischer	File::Path::make_path($destination);
6829f91b7e3SAndre Fischer	++$directory_count;
6839f91b7e3SAndre Fischer
6849f91b7e3SAndre Fischer	# Read list of files in the current source directory.
6859f91b7e3SAndre Fischer	opendir( my $dir, $source);
6869f91b7e3SAndre Fischer	my @files = readdir $dir;
6879f91b7e3SAndre Fischer	closedir $dir;
6889f91b7e3SAndre Fischer
6899f91b7e3SAndre Fischer	# Copy all files and push all directories to @todo.
6909f91b7e3SAndre Fischer	foreach my $file (@files)
6919f91b7e3SAndre Fischer	{
6929f91b7e3SAndre Fischer	    next if $file =~ /^\.+$/;
6939f91b7e3SAndre Fischer
6949f91b7e3SAndre Fischer	    my $source_file = File::Spec->catfile($source, $file);
6959f91b7e3SAndre Fischer	    my $destination_file = File::Spec->catfile($destination, $file);
6969f91b7e3SAndre Fischer	    if ( -f $source_file)
6979f91b7e3SAndre Fischer	    {
6989f91b7e3SAndre Fischer		File::Copy::copy($source_file, $destination_file);
6999f91b7e3SAndre Fischer		++$file_count;
7009f91b7e3SAndre Fischer	    }
7019f91b7e3SAndre Fischer	    elsif ( -d $source_file)
7029f91b7e3SAndre Fischer	    {
7039f91b7e3SAndre Fischer		push @todo, [$source_file, $destination_file];
7049f91b7e3SAndre Fischer	    }
7059f91b7e3SAndre Fischer	}
7069f91b7e3SAndre Fischer    }
7079f91b7e3SAndre Fischer
7089f91b7e3SAndre Fischer    return ($file_count, $directory_count);
7099f91b7e3SAndre Fischer}
7109f91b7e3SAndre Fischer
7119f91b7e3SAndre Fischer
7129f91b7e3SAndre Fischer
7139f91b7e3SAndre Fischer
7149f91b7e3SAndre Fischersub CheckLocalCopy ($$$$)
7159f91b7e3SAndre Fischer{
7169f91b7e3SAndre Fischer    my ($version, $language, $package_format, $product_name) = @_;
7179f91b7e3SAndre Fischer
7189f91b7e3SAndre Fischer    # Compare creation times of the original .msi and its copy.
7199f91b7e3SAndre Fischer
7209f91b7e3SAndre Fischer    my $original_path = File::Spec->catfile(
7219f91b7e3SAndre Fischer        $ENV{'SRC_ROOT'},
7229f91b7e3SAndre Fischer        "instsetoo_native",
7239f91b7e3SAndre Fischer        $ENV{'INPATH'},
7249f91b7e3SAndre Fischer        $product_name,
7259f91b7e3SAndre Fischer        $package_format,
7269f91b7e3SAndre Fischer        "install",
7279f91b7e3SAndre Fischer        $language);
7289f91b7e3SAndre Fischer
7299f91b7e3SAndre Fischer    my $copy_path = installer::patch::InstallationSet::GetUnpackedExePath(
7309f91b7e3SAndre Fischer        $version,
7319f91b7e3SAndre Fischer        1,
7329f91b7e3SAndre Fischer        $language,
7339f91b7e3SAndre Fischer        $package_format,
7349f91b7e3SAndre Fischer        $product_name);
7359f91b7e3SAndre Fischer
7369f91b7e3SAndre Fischer    my $msi_basename = "openoffice"
7379f91b7e3SAndre Fischer        . installer::patch::Version::ArrayToNoDotName(
7389f91b7e3SAndre Fischer            installer::patch::Version::StringToNumberArray($version))
7399f91b7e3SAndre Fischer        . ".msi";
7409f91b7e3SAndre Fischer
7419f91b7e3SAndre Fischer    my $original_msi_filename = File::Spec->catfile($original_path, $msi_basename);
7429f91b7e3SAndre Fischer    my $copied_msi_filename = File::Spec->catfile($copy_path, $msi_basename);
7439f91b7e3SAndre Fischer
7449f91b7e3SAndre Fischer    my @original_msi_stats = stat($original_msi_filename);
7459f91b7e3SAndre Fischer    my @copied_msi_stats = stat($copied_msi_filename);
7469f91b7e3SAndre Fischer    my $original_msi_mtime = $original_msi_stats[9];
7479f91b7e3SAndre Fischer    my $copied_msi_mtime = $copied_msi_stats[9];
7489f91b7e3SAndre Fischer
7499f91b7e3SAndre Fischer    if (defined $original_msi_mtime
7509f91b7e3SAndre Fischer        && defined $copied_msi_mtime
7519f91b7e3SAndre Fischer        && $original_msi_mtime > $copied_msi_mtime)
7529f91b7e3SAndre Fischer    {
7539f91b7e3SAndre Fischer        # The installation set is newer than its copy.
7549f91b7e3SAndre Fischer        # Remove the copy.
7559f91b7e3SAndre Fischer        $installer::logger::Info->printf(
7569f91b7e3SAndre Fischer            "removing copy of installation set (version %s) because it is out of date\n",
7579f91b7e3SAndre Fischer            $version);
7589f91b7e3SAndre Fischer        File::Path::remove_tree($copy_path);
7599f91b7e3SAndre Fischer    }
7609f91b7e3SAndre Fischer}
7619f91b7e3SAndre Fischer
7629f91b7e3SAndre Fischer
7639f91b7e3SAndre Fischer
7649f91b7e3SAndre Fischer
7659f91b7e3SAndre Fischer=head2 ProvideUnpackedCab
7669f91b7e3SAndre Fischer
7679f91b7e3SAndre Fischer    1a. Make sure that a downloadable installation set is present.
7689f91b7e3SAndre Fischer    1b. or that a freshly built installation set (packed and unpacked is present)
7699f91b7e3SAndre Fischer    2. Unpack the downloadable installation set
7709f91b7e3SAndre Fischer    3. Unpack the .cab file.
7719f91b7e3SAndre Fischer
7729f91b7e3SAndre Fischer    The 'Provide' in the function name means that any step that has
7739f91b7e3SAndre Fischer    already been made is not made again.
7749f91b7e3SAndre Fischer
7759f91b7e3SAndre Fischer=cut
7769f91b7e3SAndre Fischersub ProvideUnpackedCab ($$$$$)
7779f91b7e3SAndre Fischer{
7789f91b7e3SAndre Fischer    my ($version, $is_current_version, $language, $package_format, $product_name) = @_;
7799f91b7e3SAndre Fischer
7809f91b7e3SAndre Fischer    if ($is_current_version)
7819f91b7e3SAndre Fischer    {
7829f91b7e3SAndre Fischer        # For creating patches we maintain a copy of the unpacked .exe.  Make sure that that is updated when
7839f91b7e3SAndre Fischer        # a new installation set has been built.
7849f91b7e3SAndre Fischer        CheckLocalCopy($version, $language, $package_format, $product_name);
7859f91b7e3SAndre Fischer    }
7869f91b7e3SAndre Fischer
7879f91b7e3SAndre Fischer    # Check if the cab file has already been unpacked.
7889f91b7e3SAndre Fischer    my $unpacked_cab_path = installer::patch::InstallationSet::GetUnpackedCabPath(
7899f91b7e3SAndre Fischer        $version,
7909f91b7e3SAndre Fischer        $is_current_version,
7919f91b7e3SAndre Fischer        $language,
7929f91b7e3SAndre Fischer        $package_format,
7939f91b7e3SAndre Fischer        $product_name);
7949f91b7e3SAndre Fischer    my $unpacked_cab_flag_filename = File::Spec->catfile($unpacked_cab_path, "__cab_is_unpacked");
7959f91b7e3SAndre Fischer    my $cab_is_unpacked = -f $unpacked_cab_flag_filename;
7969f91b7e3SAndre Fischer
7979f91b7e3SAndre Fischer    if ($cab_is_unpacked)
7989f91b7e3SAndre Fischer    {
7999f91b7e3SAndre Fischer        # Yes. Cab was already unpacked. There is nothing more to do.
8009f91b7e3SAndre Fischer        $installer::logger::Info->printf("cab has already been unpacked to\n");
8019f91b7e3SAndre Fischer        $installer::logger::Info->printf("    %s\n", $unpacked_cab_path);
8029f91b7e3SAndre Fischer
8039f91b7e3SAndre Fischer        return 1;
8049f91b7e3SAndre Fischer    }
8059f91b7e3SAndre Fischer    else
8069f91b7e3SAndre Fischer    {
8079f91b7e3SAndre Fischer        # Make sure that the exe is unpacked and the cab file exists.
8089f91b7e3SAndre Fischer        ProvideUnpackedExe($version, $is_current_version, $language, $package_format, $product_name);
8099f91b7e3SAndre Fischer
8109f91b7e3SAndre Fischer        # Unpack the cab file.
8119f91b7e3SAndre Fischer        my $unpacked_exe_path = installer::patch::InstallationSet::GetUnpackedExePath(
8129f91b7e3SAndre Fischer                $version,
8139f91b7e3SAndre Fischer                $is_current_version,
8149f91b7e3SAndre Fischer                $language,
8159f91b7e3SAndre Fischer                $package_format,
8169f91b7e3SAndre Fischer                $product_name);
8179f91b7e3SAndre Fischer        my $msi = new installer::patch::Msi(
8189f91b7e3SAndre Fischer                installer::patch::InstallationSet::GetMsiFilename($unpacked_exe_path, $version),
8199f91b7e3SAndre Fischer                $version,
8209f91b7e3SAndre Fischer                $is_current_version,
8219f91b7e3SAndre Fischer                $language,
8229f91b7e3SAndre Fischer                $product_name);
8239f91b7e3SAndre Fischer
8249f91b7e3SAndre Fischer        my $cab_filename = installer::patch::InstallationSet::GetCabFilename(
8259f91b7e3SAndre Fischer            $unpacked_exe_path,
8269f91b7e3SAndre Fischer            $version);
8279f91b7e3SAndre Fischer        if ( ! -f $cab_filename)
8289f91b7e3SAndre Fischer        {
8299f91b7e3SAndre Fischer             # Cab file does not exist.
8309f91b7e3SAndre Fischer            installer::logger::PrintError(
8319f91b7e3SAndre Fischer                "could not find .cab file at '%s'.  Extraction of .exe seems to have failed.\n",
8329f91b7e3SAndre Fischer                $cab_filename);
8339f91b7e3SAndre Fischer            return 0;
8349f91b7e3SAndre Fischer        }
8359f91b7e3SAndre Fischer
8369f91b7e3SAndre Fischer        if (installer::patch::InstallationSet::UnpackCab(
8379f91b7e3SAndre Fischer            $cab_filename,
8389f91b7e3SAndre Fischer            $msi,
8399f91b7e3SAndre Fischer            $unpacked_cab_path))
8409f91b7e3SAndre Fischer        {
8419f91b7e3SAndre Fischer            $installer::logger::Info->printf("unpacked cab file '%s'\n", $cab_filename);
8429f91b7e3SAndre Fischer            $installer::logger::Info->printf("    to '%s'\n", $unpacked_cab_path);
8439f91b7e3SAndre Fischer
844*677600b0SAndre Fischer            installer::patch::Tools::touch($unpacked_cab_flag_filename);
8459f91b7e3SAndre Fischer
8469f91b7e3SAndre Fischer            return 1;
8479f91b7e3SAndre Fischer        }
8489f91b7e3SAndre Fischer        else
8499f91b7e3SAndre Fischer        {
8509f91b7e3SAndre Fischer            return 0;
8519f91b7e3SAndre Fischer        }
8529f91b7e3SAndre Fischer    }
8539f91b7e3SAndre Fischer}
854c9b362f6SAndre Fischer1;
855