bump product version to 4.1.6.2
[LibreOffice.git] / solenv / bin / modules / installer / archivefiles.pm
blob8c569cfe745196bf15094448ed9ce5e426d40eab
2 # This file is part of the LibreOffice project.
4 # This Source Code Form is subject to the terms of the Mozilla Public
5 # License, v. 2.0. If a copy of the MPL was not distributed with this
6 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 # This file incorporates work covered by the following license notice:
10 # Licensed to the Apache Software Foundation (ASF) under one or more
11 # contributor license agreements. See the NOTICE file distributed
12 # with this work for additional information regarding copyright
13 # ownership. The ASF licenses this file to you under the Apache
14 # License, Version 2.0 (the "License"); you may not use this file
15 # except in compliance with the License. You may obtain a copy of
16 # the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 package installer::archivefiles;
21 use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
22 use installer::files;
23 use installer::globals;
24 use installer::logger;
25 use installer::pathanalyzer;
26 use installer::systemactions;
27 use Cwd;
29 #################################################################
30 # Changing the name for files with flag RENAME_TO_LANGUAGE
31 #################################################################
33 sub put_language_into_name
35 my ( $oldname, $onelanguage ) = @_;
37 my $newname = "";
39 my $filename = "";
40 my $extension = "";
42 if ( $oldname =~ /en-US/ ) # files, that contain the language in the file name
44 $newname = $oldname;
45 $newname =~ s/en-US/$onelanguage/;
47 else # files, that do not contain the language in the file name
49 if ( $oldname =~ /^\s*(.*)(\..*?)\s*$/ ) # files with extension
51 $filename = $1;
52 $extension = $2;
54 else
56 $filename = $oldname;
57 $extension = "";
60 $newname = $1 . "_" . $onelanguage . $2;
63 return $newname;
66 #################################################################
67 # Converting patchfiles string into array
68 #################################################################
70 sub get_patch_file_list
72 my ( $patchfilestring ) = @_;
74 $patchfilestring =~ s/^\s*\(?//;
75 $patchfilestring =~ s/\)?\s*$//;
76 $patchfilestring =~ s/^\s*\///;
77 $patchfilestring =~ s/^\s*\\//;
79 my @patchfilesarray = split /,\s*/, $patchfilestring;
81 return \@patchfilesarray;
84 #################################################################
85 # Reading all executables in the "manifest.xml"
86 #################################################################
88 sub get_all_executables_from_manifest
90 my ($unzipdir, $manifestfile, $executable_files_in_extensions) = @_;
92 my $is_executable = 0;
94 for ( my $i = 0; $i <= $#{$manifestfile}; $i++ )
96 my $line = ${$manifestfile}[$i];
98 if ( $line =~ /\"application\/vnd\.sun\.star\.executable\"/ ) { $is_executable = 1; }
100 if (( $line =~ /manifest\:full\-path=\"(.*?)\"/ ) && ( $is_executable ))
102 my $filename = $unzipdir . $installer::globals::separator . $1;
103 # making only slashes for comparison reasons
104 $filename =~ s/\\/\//g;
105 $executable_files_in_extensions->{$filename} = 1;
108 if ( $line =~ /\/\>/ ) { $is_executable = 0; }
112 #################################################################
113 # Reading the "manifest.xml" in extensions and determine, if
114 # there are executable files
115 #################################################################
117 sub collect_all_executable_files_in_extensions
119 my ($unzipdir, $executable_files_in_extensions) = @_;
121 $unzipdir =~ s/\Q$installer::globals::separator\E\s*$//;
123 my $manifestfilename = $unzipdir . $installer::globals::separator . "META-INF" . $installer::globals::separator . "manifest.xml";
125 if ( -f $manifestfilename )
127 my $manifestfile = installer::files::read_file($manifestfilename);
128 get_all_executables_from_manifest($unzipdir, $manifestfile, $executable_files_in_extensions);
132 #################################################################
133 # Analyzing files with flag ARCHIVE
134 #################################################################
136 sub resolving_archive_flag
138 my ($filesarrayref, $additionalpathsref, $languagestringref, $loggingdir) = @_;
140 my @newallfilesarray = ();
142 my ($systemcall, $returnvalue, $infoline);
144 my $unziplistfile = $loggingdir . "unziplist_" . $installer::globals::build . "_" . $installer::globals::compiler . "_" . $$languagestringref . ".txt";
146 my $platformunzipdirbase = installer::systemactions::create_directories("zip", $languagestringref);
147 push(@installer::globals::removedirs, $platformunzipdirbase);
149 installer::logger::include_header_into_logfile("Files with flag ARCHIVE:");
151 my $repeat_unzip = 0;
152 my $maxcounter = 0;
154 for ( my $i = 0; $i <= $#{$filesarrayref}; $i++ )
156 if ( $repeat_unzip ) { $i--; } # decreasing the counter
158 my $onefile = ${$filesarrayref}[$i];
159 my $styles = "";
161 if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; }
163 if ( $styles =~ /\bARCHIVE\b/ ) # copying, unzipping and changing the file list
165 my $iscommonfile = 0;
166 my $sourcepath = $onefile->{'sourcepath'};
168 if ( $sourcepath =~ /\Q$installer::globals::separator\E\bcommon$installer::globals::productextension\Q$installer::globals::separator\E/ ) # /common/ or /common.pro/
170 $iscommonfile = 1;
173 my $use_internal_rights = 0;
174 if ( $styles =~ /\bUSE_INTERNAL_RIGHTS\b/ ) { $use_internal_rights = 1; } # using the rights used inside the zip file
176 my $rename_to_language = 0;
177 if ( $styles =~ /\bRENAME_TO_LANGUAGE\b/ ) { $rename_to_language = 1; } # special handling for renamed files (scriptitems.pm)
179 my %executable_files_in_extensions = ();
180 my $set_executable_privileges = 0; # setting privileges for exectables is required for oxt files
181 if ( $onefile->{'Name'} =~ /\.oxt\s*$/ ) { $set_executable_privileges = 1; }
183 # mechanism to select files from an archive files
184 my $select_files = 0;
185 my $selectlistfiles = "";
186 my @keptfiles = ();
187 if ( $onefile->{'Selectfiles'} )
189 $select_files = 1;
190 $selectlistfiles = get_patch_file_list( $onefile->{'Selectfiles'} );
191 $infoline = "Selected file list defined at file: $onefile->{'Name'} :\n";
192 push( @installer::globals::logfileinfo, $infoline);
193 for ( my $k = 0; $k <= $#{$selectlistfiles}; $k++ )
195 $infoline = "\"${$selectlistfiles}[$k]\"\n";
196 push( @installer::globals::logfileinfo, $infoline);
200 if ( $onefile->{'Selectfiles'} ) { $onefile->{'Selectfiles'} = ""; } # Selected files list no longer required
202 # mechanism to define patch files inside an archive files
203 my $select_patch_files = 0;
204 my $patchlistfiles = "";
205 my @keptpatchflags = ();
207 if ( $onefile->{'Patchfiles'} ) { $onefile->{'Patchfiles'} = ""; } # Patch file list no longer required
209 # creating directories
211 my $onelanguage = $onefile->{'specificlanguage'};
213 # files without language into directory "00"
215 if ($onelanguage eq "") { $onelanguage = "00"; }
217 my $unzipdir;
219 $unzipdir = $platformunzipdirbase . $installer::globals::separator . $onelanguage . $installer::globals::separator;
221 installer::systemactions::create_directory($unzipdir); # creating language specific subdirectories
223 my $onefilename = $onefile->{'Name'};
224 $onefilename =~ s/\./\_/g; # creating new directory name
225 $onefilename =~ s/\//\_/g; # only because of /letter/fontunxpsprint.zip, the only zip file with path
226 $unzipdir = $unzipdir . $onefilename . $installer::globals::separator;
228 if ( $installer::globals::dounzip ) { installer::systemactions::create_directory($unzipdir); } # creating subdirectories with the names of the zipfiles
230 my $zip = Archive::Zip->new();
231 if ( $zip->read($sourcepath) != AZ_OK )
233 $infoline = "ERROR: Could not unzip $sourcepath\n";
234 push( @installer::globals::logfileinfo, $infoline);
237 my $counter = 0;
238 my $contains_dll = 0;
239 my @dllList = ();
240 my @dirs = ();
241 foreach my $member ( $zip->memberNames() )
243 $counter++;
244 if ( $member =~ /.dll\s*$/i ) { $contains_dll = 1; push(@dllList, $member); }
245 if ( $member =~ m/\/$/ ) { push(@dirs, $member); }
248 if (! ( $counter > 0 )) # the zipfile is empty
250 $infoline = "ERROR: Could not unzip $sourcepath\n";
251 push( @installer::globals::logfileinfo, $infoline);
254 else
256 if ( $installer::globals::dounzip ) # really unpacking the files
258 if ( $zip->extractTree("", $unzipdir) != AZ_OK ) { die "Could not unzip: $!"; }
260 if (( $^O =~ /cygwin/i ) && ( $contains_dll ))
262 my $dir = getcwd();
263 chdir($unzipdir);
264 my $changed = chmod(0775, @dllList);
265 $infoline = "Changed mode of $changed files (of ".scalar(@dllList).")\n";
266 push( @installer::globals::logfileinfo, $infoline);
267 chdir($dir);
269 if ($changed != scalar(@dllList))
271 $infoline = "ERROR: Could not chmod all files!\n";
272 push( @installer::globals::logfileinfo, $infoline);
276 if ( ! $installer::globals::iswindowsbuild && scalar(@dirs) > 0 )
278 my $dir = getcwd();
279 chdir($unzipdir);
280 # Setting unix rights to "775" for all created directories inside the package
281 my $changed = chmod(0775, @dirs);
282 $infoline = "Changed mode of : $changed; should be: ".scalar(@dirs)."\n";
283 chdir($dir);
285 push( @installer::globals::logfileinfo, $infoline);
287 if ($changed != scalar(@dirs))
289 $infoline = "ERROR: Could not chmod all files!\n";
290 push( @installer::globals::logfileinfo, $infoline);
294 # Selecting names of executable files in extensions
295 if ( $set_executable_privileges )
297 collect_all_executable_files_in_extensions($unzipdir, \%executable_files_in_extensions);
301 my $zipfileref = \@zipfile;
302 my $unziperror = 0;
304 foreach my $zipname ( $zip->memberNames() )
306 # Format from Archive:::Zip :
307 # dir1/
308 # dir1/so7drawing.desktop
310 # some directories and files (from the help) start with "./simpress.idx"
312 $zipname =~ s/^\s*\.\///;
314 if ($installer::globals::iswin and $^O =~ /MSWin/i) { $zipname =~ s/\//\\/g; }
316 if ( $zipname =~ /\Q$installer::globals::separator\E\s*$/ ) # slash or backslash at the end characterizes a directory
318 $zipname = $zipname . "\n";
319 push(@{$additionalpathsref}, $zipname);
321 # Also needed here:
322 # Name
323 # Language
324 # ismultilingual
325 # Basedirectory
327 # This is not needed, because the list of all directories for the
328 # epm list file is generated from the destination directories of the
329 # files included in the product!
331 else
333 my %newfile = ();
334 %newfile = %{$onefile};
335 $newfile{'Name'} = $zipname;
336 my $destination = $onefile->{'destination'};
337 installer::pathanalyzer::get_path_from_fullqualifiedname(\$destination);
338 $newfile{'destination'} = $destination . $zipname;
339 $newfile{'sourcepath'} = $unzipdir . $zipname;
340 $newfile{'zipfilename'} = $onefile->{'Name'};
341 $newfile{'zipfilesource'} = $onefile->{'sourcepath'};
342 $newfile{'zipfiledestination'} = $onefile->{'destination'};
344 if (( $use_internal_rights ) && ( ! $installer::globals::iswin ))
346 $newfile{'UnixRights'} = sprintf("%o", ($zip->memberNamed($zipname)->unixFileAttributes() & 07777));
347 $infoline = "Setting unix rights for \"$newfile{'sourcepath'}\" to \"$newfile{'UnixRights'}\"\n";
348 push( @installer::globals::logfileinfo, $infoline);
351 if ( $set_executable_privileges )
353 # All paths to executables are saved in the hash %executable_files_in_extensions
354 my $compare_path = $newfile{'sourcepath'};
355 $compare_path =~ s/\\/\//g; # contains only slashes for comparison reasons
356 if ( exists($executable_files_in_extensions{$compare_path}) )
358 $newfile{'UnixRights'} = "775";
359 $infoline = "Executable in Extension: Setting unix rights for \"$newfile{'sourcepath'}\" to \"$newfile{'UnixRights'}\"\n";
360 push( @installer::globals::logfileinfo, $infoline);
364 if ( $select_files )
366 if ( ! grep {$_ eq $zipname} @{$selectlistfiles} )
368 $infoline = "Removing from ARCHIVE file $onefilename: $zipname\n";
369 push( @installer::globals::logfileinfo, $infoline);
370 next; # ignoring files, that are not included in $selectlistfiles
372 else
374 $infoline = "Keeping from ARCHIVE file $onefilename: $zipname\n";
375 push( @installer::globals::logfileinfo, $infoline);
376 push( @keptfiles, $zipname); # collecting all kept files
380 if ( $rename_to_language )
382 my $newzipname = put_language_into_name($zipname, $onelanguage);
383 my $oldfilename = $unzipdir . $zipname;
384 my $newfilename = $unzipdir . $newzipname;
386 installer::systemactions::copy_one_file($oldfilename, $newfilename);
388 $newfile{'Name'} = $newzipname;
389 $newfile{'destination'} = $destination . $newzipname;
390 $newfile{'sourcepath'} = $unzipdir . $newzipname;
392 $infoline = "RENAME_TO_LANGUAGE: Using $newzipname instead of $zipname!\n";
393 push( @installer::globals::logfileinfo, $infoline);
396 my $sourcefiletest = $unzipdir . $zipname;
397 if ( ! -f $sourcefiletest )
399 $infoline = "ATTENTION: Unzip failed for $sourcefiletest!\n";
400 push( @installer::globals::logfileinfo, $infoline);
401 $unziperror = 1;
404 # only adding the new line into the files array, if not in repeat modus
406 if ( ! $repeat_unzip ) { push(@newallfilesarray, \%newfile); }
410 # Comparing the content of @keptfiles and $selectlistfiles
411 # Do all files from the list of selected files are stored in @keptfiles ?
412 # @keptfiles contains only files included in $selectlistfiles. But are all
413 # files from $selectlistfiles included in @keptfiles?
415 if ( $select_files )
417 my $number = $#{$selectlistfiles} + 1;
418 $infoline = "SELECTLIST: Number of files in file selection list: $number\n";
419 push( @installer::globals::logfileinfo, $infoline);
420 $number = $#keptfiles + 1;
421 $infoline = "SELECTLIST: Number of kept files: $number\n";
422 push( @installer::globals::logfileinfo, $infoline);
424 for ( my $k = 0; $k <= $#keptfiles; $k++ )
426 $infoline = "KEPT FILES: $keptfiles[$k]\n";
427 push( @installer::globals::logfileinfo, $infoline);
430 my @warningfiles = ();
432 for ( my $k = 0; $k <= $#{$selectlistfiles}; $k++ )
434 if ( ! grep {$_ eq ${$selectlistfiles}[$k]} @keptfiles )
436 push(@warningfiles, ${$selectlistfiles}[$k]);
440 for ( my $k = 0; $k <= $#warningfiles; $k++ )
442 $infoline = "WARNING: $warningfiles[$k] not included in install set (does not exist in zip file)!\n";
443 push( @installer::globals::logfileinfo, $infoline);
448 if ( $unziperror )
450 installer::logger::print_warning( "Repeating to unpack $sourcepath! \n" );
451 $infoline = "ATTENTION: Repeating to unpack $sourcepath !\n";
452 push( @installer::globals::logfileinfo, $infoline);
453 $repeat_unzip = 1;
454 $maxcounter++;
456 if ( $maxcounter == 5 ) # exiting the program
458 die "Failed to unzip $sourcepath !";
461 else
463 $infoline = "Info: $sourcepath unpacked without problems !\n";
464 push( @installer::globals::logfileinfo, $infoline);
465 $repeat_unzip = 0;
466 $maxcounter = 0;
470 else # nothing to do here, no zipped file (no ARCHIVE flag)
472 push(@newallfilesarray, $onefile);
476 $infoline = "\n";
477 push( @installer::globals::logfileinfo, $infoline);
479 return \@newallfilesarray;