1# 2# This file is part of the LibreOffice project. 3# 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/. 7# 8# This file incorporates work covered by the following license notice: 9# 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 . 17# 18 19package installer::control; 20 21use Cwd; 22use installer::converter; 23use installer::exiter; 24use installer::files; 25use installer::globals; 26use installer::pathanalyzer; 27use installer::scriptitems; 28use installer::systemactions; 29 30######################################################### 31# Function that can be used for additional controls. 32# Search happens in $installer::globals::patharray. 33######################################################### 34 35sub check_needed_files_in_path 36{ 37 my ( $filesref ) = @_; 38 39 foreach $onefile ( @{$filesref} ) 40 { 41 installer::logger::print_message( "... searching $onefile ..." ); 42 43 my $fileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath_classic(\$onefile, $installer::globals::patharray , 0); 44 45 if ( $$fileref eq "" ) 46 { 47 $error = 1; 48 installer::logger::print_error( "$onefile not found\n" ); 49 } 50 else 51 { 52 installer::logger::print_message( "\tFound: $$fileref\n" ); 53 } 54 } 55 56 if ( $error ) 57 { 58 installer::exiter::exit_program("ERROR: Could not find all needed files in path!", "check_needed_files_in_path"); 59 } 60} 61 62######################################################### 63# Checking the local system 64# Checking existence of needed files in include path 65######################################################### 66 67sub check_system_path 68{ 69 # The following files have to be found in the environment variable PATH 70 # All platforms: zip 71 # Windows only: "msiinfo.exe", "msidb.exe", "uuidgen.exe", "makecab.exe", "msitran.exe", "expand.exe" for msi database and packaging 72 73 my $onefile; 74 my $error = 0; 75 my $pathvariable = $ENV{'PATH'}; 76 my $local_pathseparator = $installer::globals::pathseparator; 77 78 if( $^O =~ /cygwin/i ) 79 { 80 # When using cygwin's perl the PATH variable is POSIX style and 81 # has to be converted to DOS style for further use. 82 $pathvariable = join ';', 83 map { $dir = qx{cygpath -m "$_"}; chomp($dir); $dir } 84 split /\Q$local_pathseparator\E\s*/, $pathvariable; 85 $local_pathseparator = ';'; 86 } 87 my $patharrayref = installer::converter::convert_stringlist_into_array(\$pathvariable, $local_pathseparator); 88 89 $installer::globals::patharray = $patharrayref; 90 91 my @needed_files_in_path = (); 92 93 if (($installer::globals::iswin) && ($installer::globals::iswindowsbuild)) 94 { 95 @needed_files_in_path = ("zip.exe", "msiinfo.exe", "msidb.exe", "uuidgen", "makecab.exe", "msitran.exe", "expand.exe"); 96 } 97 elsif ($installer::globals::iswin) 98 { 99 @needed_files_in_path = ("zip.exe"); 100 } 101 else 102 { 103 @needed_files_in_path = ("zip"); 104 } 105 106 foreach $onefile ( @needed_files_in_path ) 107 { 108 installer::logger::print_message( "... searching $onefile ..." ); 109 110 my $fileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath_classic(\$onefile, $patharrayref , 0); 111 112 if ( $$fileref eq "" ) 113 { 114 $error = 1; 115 installer::logger::print_error( "$onefile not found\n" ); 116 } 117 else 118 { 119 installer::logger::print_message( "\tFound: $$fileref\n" ); 120 # Saving the absolute path for msitran.exe. This is required for the determination of the checksum. 121 if ( $onefile eq "msitran.exe" ) { $installer::globals::msitranpath = $$fileref; } 122 } 123 } 124 125 if ( $error ) 126 { 127 installer::exiter::exit_program("ERROR: Could not find all needed files in path!", "check_system_path"); 128 } 129 130 # checking for epm, which has to be in the path or in the solver 131 132 if (( $installer::globals::call_epm ) && (!($installer::globals::iswindowsbuild))) 133 { 134 my $onefile = "epm"; 135 my $fileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$onefile, $patharrayref , 0); 136 if (!( $$fileref eq "" )) 137 { 138 $installer::globals::epm_in_path = 1; 139 140 if ( $$fileref =~ /^\s*\.\/epm\s*$/ ) 141 { 142 my $currentdir = cwd(); 143 $$fileref =~ s/\./$currentdir/; 144 } 145 146 $installer::globals::epm_path = $$fileref; 147 } 148 } 149} 150 151###################################################################### 152# Determining the version of file makecab.exe 153###################################################################### 154 155sub get_makecab_version 156{ 157 my $makecabversion = -1; 158 159 my $systemcall = "makecab.exe |"; 160 my @makecaboutput = (); 161 162 open (CAB, $systemcall); 163 while (<CAB>) { push(@makecaboutput, $_); } 164 close (CAB); 165 166 my $returnvalue = $?; # $? contains the return value of the systemcall 167 168 if ($returnvalue) 169 { 170 $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; 171 push( @installer::globals::globallogfileinfo, $infoline); 172 } 173 else 174 { 175 $infoline = "Success: Executed \"$systemcall\" successfully!\n"; 176 push( @installer::globals::globallogfileinfo, $infoline); 177 178 my $versionline = ""; 179 180 for ( my $i = 0; $i <= $#makecaboutput; $i++ ) 181 { 182 if ( $makecaboutput[$i] =~ /\bVersion\b/i ) 183 { 184 $versionline = $makecaboutput[$i]; 185 last; 186 } 187 } 188 189 $infoline = $versionline; 190 push( @installer::globals::globallogfileinfo, $infoline); 191 192 if ( $versionline =~ /\bVersion\b\s+(\d+[\d\.]+\d+)\s+/ ) 193 { 194 $makecabversion = $1; 195 } 196 197 # Only using the first number 198 199 if ( $makecabversion =~ /^\s*(\d+?)\D*/ ) 200 { 201 $makecabversion = $1; 202 } 203 204 $infoline = "Using version: " . $makecabversion . "\n"; 205 push( @installer::globals::globallogfileinfo, $infoline); 206 } 207 208 return $makecabversion; 209} 210 211###################################################################### 212# Checking the version of file makecab.exe 213###################################################################### 214 215sub check_makecab_version 216{ 217 # checking version of makecab.exe 218 # Now it is guaranteed, that makecab.exe is in the path 219 220 my $do_check = 1; 221 222 my $makecabversion = get_makecab_version(); 223 224 my $infoline = "Tested version: " . $installer::globals::controlledmakecabversion . "\n"; 225 push( @installer::globals::globallogfileinfo, $infoline); 226 227 if ( $makecabversion < 0 ) { $do_check = 0; } # version could not be determined 228 229 if ( $do_check ) 230 { 231 if ( $makecabversion < $installer::globals::controlledmakecabversion ) 232 { 233 installer::exiter::exit_program("makecab.exe too old. Found version: \"$makecabversion\", required version: \"$installer::globals::controlledmakecabversion\"!", "check_makecab_version"); 234 } 235 } 236 else 237 { 238 $infoline = "Warning: No version check of makecab.exe\n"; 239 push( @installer::globals::globallogfileinfo, $infoline); 240 } 241} 242 243###################################################################### 244# Reading the environment variables for the paths in ziplist. 245# solarenvpath, os, pmiscpath 246###################################################################### 247 248sub check_system_environment 249{ 250 my %variables = (); 251 my $error = 0; 252 253 my @environmentvariables = qw( 254 LIBO_VERSION_MAJOR 255 LIBO_VERSION_MINOR 256 CPUNAME 257 OS 258 COM 259 PLATFORMID 260 LOCAL_OUT 261 LOCAL_COMMON_OUT 262 WORKDIR 263 SRCDIR 264 ); 265 266 for my $key ( @environmentvariables ) 267 { 268 $variables{$key} = defined($ENV{$key}) ? $ENV{$key} : ""; 269 270 if ( $variables{$key} eq "" ) 271 { 272 installer::logger::print_error( "$key not set in environment\n" ); 273 $error = 1; 274 } 275 } 276 277 if ( $error ) 278 { 279 installer::exiter::exit_program("ERROR: Environment variable not set!", "check_system_environment"); 280 } 281 282 return \%variables; 283} 284 285############################################################# 286# Controlling the log file at the end of the 287# packaging process 288############################################################# 289 290sub check_logfile 291{ 292 my ($logfile) = @_; 293 294 my @errors = (); 295 my @output = (); 296 my $contains_error = 0; 297 298 my $ignore_error = 0; 299 my $make_error_to_warning = 0; 300 301 for ( my $i = 0; $i <= $#{$logfile}; $i++ ) 302 { 303 my $line = ${$logfile}[$i]; 304 305 # Errors are all errors, but not the Windows installer table "Error.idt" 306 307 my $compareline = $line; 308 $compareline =~ s/Error\.idt//g; # removing all occurrences of "Error.idt" 309 $compareline =~ s/Error\.ulf//g; # removing all occurrences of "Error.ulf" 310 $compareline =~ s/Error\.idl//g; # removing all occurrences of "Error.idl" 311 $compareline =~ s/Error\.html//g; # removing all occurrences of "Error.html" 312 $compareline =~ s/error\.py//g; # removing all occurrences of "error.py" 313 $compareline =~ s/error\.cpython\-3.(\.opt\-.|)\.py[co]//g; # removing all occurrences of "error-cpython" 314 $compareline =~ s/libgpg-error//g; 315 $compareline =~ s/Error-xref\.html//g; 316 317 if ( $compareline =~ /\bError\b/i ) 318 { 319 $contains_error = 1; 320 push(@errors, $line); 321 322 if ( $ignore_error ) 323 { 324 $contains_error = 0; 325 $make_error_to_warning = 1; 326 } 327 } 328 } 329 330 if ($contains_error) 331 { 332 my $line = "\n*********************************************************************\n"; 333 push(@output, $line); 334 $line = "ERROR: The following errors occurred in packaging process:\n\n"; 335 push(@output, $line); 336 337 for ( my $i = 0; $i <= $#errors; $i++ ) 338 { 339 $line = "$errors[$i]"; 340 push(@output, $line); 341 } 342 343 $line = "*********************************************************************\n"; 344 push(@output, $line); 345 } 346 else 347 { 348 my $line = ""; 349 350 if ( $make_error_to_warning ) 351 { 352 $line = "\n*********************************************************************\n"; 353 push(@output, $line); 354 $line = "The following errors in the log file were ignored:\n\n"; 355 push(@output, $line); 356 357 for ( my $i = 0; $i <= $#errors; $i++ ) 358 { 359 $line = "$errors[$i]"; 360 push(@output, $line); 361 } 362 363 $line = "*********************************************************************\n"; 364 push(@output, $line); 365 } 366 367 $line = "\n***********************************************************\n"; 368 push(@output, $line); 369 $line = "Successful packaging process!\n"; 370 push(@output, $line); 371 $line = "***********************************************************\n"; 372 push(@output, $line); 373 } 374 375 # printing the output file and adding it to the logfile 376 377 installer::logger::include_header_into_logfile("Summary:"); 378 379 my $force = 1; # print this message even in 'quiet' mode 380 for ( my $i = 0; $i <= $#output; $i++ ) 381 { 382 my $line = "$output[$i]"; 383 installer::logger::print_message( "$line", $force ); 384 push( @installer::globals::logfileinfo, $line); 385 push( @installer::globals::errorlogfileinfo, $line); 386 } 387 388 return $contains_error; 389} 390 391############################################################# 392# Reading the Windows list file for Windows language codes 393# Encoding field is no longer used. We use UTF-8 everywhere. 394############################################################# 395 396sub read_lcidlist 397{ 398 my ($patharrayref) = @_; 399 400 if ( ! -f $installer::globals::lcidlistname ) { installer::exiter::exit_program("ERROR: Did not find Windows LCID list $installer::globals::lcidlistname!", "read_lcidlist"); } 401 402 my $infoline = "Found LCID file: $installer::globals::lcidlistname\n"; 403 push(@installer::globals::globallogfileinfo, $infoline); 404 405 my $lcidlist = installer::files::read_file($installer::globals::lcidlistname); 406 my %msilanguage = (); 407 408 for ( my $i = 0; $i <= $#{$lcidlist}; $i++ ) 409 { 410 my $line = ${$lcidlist}[$i]; 411 # de-mangle various potential DOS line-ending problems 412 $line =~ s/\r//g; 413 $line =~ s/\n//g; 414 $line =~ s/\s*\#.*$//; # removing comments after "#" 415 if ( $line =~ /^\s*$/ ) { next; } # this is an empty line 416 417 if ( $line =~ /^\s*([\w-]+)\s+(\d+)\s+(\d+)\s*$/ ) 418 { 419 my $onelanguage = $1; 420 my $windowslanguage = $3; 421 $msilanguage{$onelanguage} = $windowslanguage; 422 } 423 else 424 { 425 installer::exiter::exit_program("ERROR: Wrong syntax in Windows LCID list $installer::globals::lcidlistname in line $i: '$line'", "read_lcidlist"); 426 } 427 } 428 $installer::globals::msilanguage = \%msilanguage; 429} 430 431############################################################# 432# Only for Windows and Linux (RPM)there is currently 433# a reliable mechanism to register extensions during 434# installation process. Therefore it is for all other 435# platforms forbidden to install oxt files into that 436# directory, in which they are searched for registration. 437############################################################# 438 439sub check_oxtfiles 440{ 441 my ( $filesarray ) = @_; 442 443 for ( my $i = 0; $i <= $#{$filesarray}; $i++ ) 444 { 445 my $onefile = ${$filesarray}[$i]; 446 447 if (( $onefile->{'Name'} ) && ( $onefile->{'Dir'} )) 448 { 449 if (( $onefile->{'Name'} =~ /\.oxt\s*$/ ) && ( $onefile->{'Dir'} eq $installer::globals::extensioninstalldir )) 450 { 451 installer::exiter::exit_program("There is currently only for Linux (RPM) and Windows a reliable mechanism to register extensions during installation.\nPlease remove file \"$onefile->{'gid'}\" from your installation set!\nYou can use \"\#ifdef _WIN32\" and \"\#ifdef LINUX\" in scp.", "check_oxtfiles"); 452 } 453 } 454 } 455} 456 457####################################################################### 458# Setting global variable "$installer::globals::addsystemintegration" 459####################################################################### 460 461sub set_addsystemintegration 462{ 463 my ($allvariables) = @_; 464 465 if ( $allvariables->{'ADDSYSTEMINTEGRATION'} ) { $installer::globals::addsystemintegration = 1; } 466 467 if ( $installer::globals::languagepack ) { $installer::globals::addsystemintegration = 0; } 468 if ( $installer::globals::helppack ) { $installer::globals::addsystemintegration = 0; } 469 470 my $infoline = "Value of \$installer::globals::addsystemintegration: $installer::globals::addsystemintegration\n"; 471 push( @installer::globals::globallogfileinfo, $infoline); 472} 473 4741; 475