1#************************************************************** 2# 3# Licensed to the Apache Software Foundation (ASF) under one 4# or more contributor license agreements. See the NOTICE file 5# distributed with this work for additional information 6# regarding copyright ownership. The ASF licenses this file 7# to you under the Apache License, Version 2.0 (the 8# "License"); you may not use this file except in compliance 9# with the License. You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, 14# software distributed under the License is distributed on an 15# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16# KIND, either express or implied. See the License for the 17# specific language governing permissions and limitations 18# under the License. 19# 20#************************************************************** 21 22 23 24package installer::simplepackage; 25 26# use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); 27use Cwd; 28use File::Copy; 29use installer::download; 30use installer::exiter; 31use installer::globals; 32use installer::logger; 33use installer::strip; 34use installer::systemactions; 35use installer::worker; 36 37sub shell_quote 38{ 39 my ( $value ) = @_; 40 $value =~ s/'/'"'"'/g; 41 return "'$value'"; 42} 43 44#################################################### 45# Checking if the simple packager is required. 46# This can be achieved by setting the global 47# variable SIMPLE_PACKAGE in *.lst file or by 48# setting the environment variable SIMPLE_PACKAGE. 49#################################################### 50 51sub check_simple_packager_project 52{ 53 my ( $allvariables ) = @_; 54 55 if (( $installer::globals::packageformat eq "installed" ) || 56 ( $installer::globals::packageformat eq "archive" )) 57 { 58 $installer::globals::is_simple_packager_project = 1; 59 $installer::globals::patch_user_dir = 1; 60 } 61 elsif( $installer::globals::packageformat eq "dmg" ) 62 { 63 $installer::globals::is_simple_packager_project = 1; 64 } 65} 66 67#################################################### 68# Detecting the directory with extensions 69#################################################### 70 71sub get_extensions_dir 72{ 73 my ( $subfolderdir ) = @_; 74 75 my $extensiondir = $subfolderdir . $installer::globals::separator; 76 if ( $installer::globals::officedirhostname ne "" ) { $extensiondir = $extensiondir . $installer::globals::officedirhostname . $installer::globals::separator; } 77 my $extensionsdir = $extensiondir . "share" . $installer::globals::separator . "extensions"; 78 my $preregdir = $extensiondir . "share" . $installer::globals::separator . "prereg" . $installer::globals::separator . "bundled"; 79 80 return ( $extensionsdir, $preregdir ); 81} 82 83#################################################### 84# Registering extensions 85#################################################### 86 87sub register_extensions 88{ 89 my ($officedir, $languagestringref, $preregdir) = @_; 90 91 my $infoline = ""; 92 93 if ( $preregdir eq "" ) 94 { 95 $infoline = "ERROR: Failed to determine directory \"prereg\" for extension registration! Please check your installation set.\n"; 96 $installer::logger::Lang->print($infoline); 97 installer::exiter::exit_program($infoline, "register_extensions"); 98 } 99 100 my $programdir = $officedir . $installer::globals::separator; 101 if ( $installer::globals::officedirhostname ne "" ) { $programdir = $programdir . $installer::globals::officedirhostname . $installer::globals::separator; } 102 $programdir = $programdir . "program"; 103 104 my $from = cwd(); 105 chdir($programdir); 106 107 my $unopkgfile = $installer::globals::unopkgfile; 108 109 my $unopkgexists = 1; 110 if (( $installer::globals::languagepack ) && ( ! -f $unopkgfile )) 111 { 112 $unopkgexists = 0; 113 $infoline = "Language packs do not contain unopkg!\n"; 114 $installer::logger::Lang->print($infoline); 115 } 116 117 if ( ! -f $unopkgfile ) 118 { 119 $unopkgexists = 0; 120 $infoline = "Info: File $unopkgfile does not exist! Extensions cannot be registered.\n"; 121 $installer::logger::Lang->print($infoline); 122 } 123 124 if ( $unopkgexists ) 125 { 126 my $currentdir = cwd(); 127 $installer::logger::Info->printf("... current dir: %s ...\n", $currentdir); 128 $infoline = "Current dir: $currentdir\n"; 129 $installer::logger::Lang->print($infoline); 130 131 if ( ! -f $unopkgfile ) { installer::exiter::exit_program("ERROR: $unopkgfile not found!", "register_extensions"); } 132 133 my $systemcall = $programdir . $installer::globals::separator . $unopkgfile . " sync --verbose" . " -env:UNO_JAVA_JFW_ENV_JREHOME=true 2\>\&1 |"; 134 135 $installer::logger::Info->printf("... %s ...\n", $systemcall); 136 137 $infoline = "Systemcall: $systemcall\n"; 138 $installer::logger::Lang->print($infoline); 139 140 my @unopkgoutput = (); 141 142 open (UNOPKG, $systemcall); 143 while (<UNOPKG>) 144 { 145 my $lastline = $_; 146 push(@unopkgoutput, $lastline); 147 } 148 close (UNOPKG); 149 150 my $returnvalue = $?; # $? contains the return value of the systemcall 151 152 if ($returnvalue) 153 { 154 # Writing content of @unopkgoutput only in the error case into the log file. Sometimes it 155 # contains strings like "Error" even in the case of success. This causes a packaging error 156 # when the log file is analyzed at the end, even if there is no real error. 157 foreach my $line (@unopkgoutput) 158 { 159 $installer::logger::Lang->printf($line); 160 } 161 162 $infoline = "ERROR: Could not execute \"$systemcall\"!\nExitcode: '$returnvalue'\n"; 163 $installer::logger::Lang->print($infoline); 164 installer::exiter::exit_program("ERROR: $systemcall failed!", "register_extensions"); 165 } 166 else 167 { 168 $infoline = "Success: Executed \"$systemcall\" successfully!\n"; 169 $installer::logger::Lang->print($infoline); 170 } 171 } 172 173 chdir($from); 174} 175 176######################################################################## 177# Getting the translation file for the Mac Language Pack installer 178######################################################################## 179 180sub get_mac_translation_file 181{ 182 my $translationfilename = $installer::globals::maclangpackfilename; 183 if ( ! -f $translationfilename ) { installer::exiter::exit_program("ERROR: Could not find language file $translationfilename!", "get_mac_translation_file"); } 184 my $translationfile = installer::files::read_file($translationfilename); 185 186 my $infoline = "Reading translation file: $translationfilename\n"; 187 $installer::logger::Lang->print($infoline); 188 189 return $translationfile; 190} 191 192################################################################## 193# Collecting all identifier from ulf file 194################################################################## 195 196sub get_identifier 197{ 198 my ( $translationfile ) = @_; 199 200 my @identifier = (); 201 202 for ( my $i = 0; $i <= $#{$translationfile}; $i++ ) 203 { 204 my $oneline = ${$translationfile}[$i]; 205 206 if ( $oneline =~ /^\s*\[(.+)\]\s*$/ ) 207 { 208 my $identifier = $1; 209 push(@identifier, $identifier); 210 } 211 } 212 213 return \@identifier; 214} 215 216############################################################## 217# Returning the complete block in all languages 218# for a specified string 219############################################################## 220 221sub get_language_block_from_language_file 222{ 223 my ($searchstring, $languagefile) = @_; 224 225 my @language_block = (); 226 227 for ( my $i = 0; $i <= $#{$languagefile}; $i++ ) 228 { 229 if ( ${$languagefile}[$i] =~ /^\s*\[\s*$searchstring\s*\]\s*$/ ) 230 { 231 my $counter = $i; 232 233 push(@language_block, ${$languagefile}[$counter]); 234 $counter++; 235 236 while (( $counter <= $#{$languagefile} ) && (!( ${$languagefile}[$counter] =~ /^\s*\[/ ))) 237 { 238 push(@language_block, ${$languagefile}[$counter]); 239 $counter++; 240 } 241 242 last; 243 } 244 } 245 246 return \@language_block; 247} 248 249############################################################## 250# Returning a specific language string from the block 251# of all translations 252############################################################## 253 254sub get_language_string_from_language_block 255{ 256 my ($language_block, $language) = @_; 257 258 my $newstring = ""; 259 260 for ( my $i = 0; $i <= $#{$language_block}; $i++ ) 261 { 262 if ( ${$language_block}[$i] =~ /^\s*$language\s*\=\s*\"(.*)\"\s*$/ ) 263 { 264 $newstring = $1; 265 last; 266 } 267 } 268 269 if ( $newstring eq "" ) 270 { 271 $language = "en-US"; # defaulting to english 272 273 for ( my $i = 0; $i <= $#{$language_block}; $i++ ) 274 { 275 if ( ${$language_block}[$i] =~ /^\s*$language\s*\=\s*\"(.*)\"\s*$/ ) 276 { 277 $newstring = $1; 278 last; 279 } 280 } 281 } 282 283 return $newstring; 284} 285 286######################################################################## 287# Localizing the script for the Mac Language Pack installer 288######################################################################## 289 290sub localize_scriptfile 291{ 292 my ($scriptfile, $translationfile, $languagestringref) = @_; 293 294 # my $translationfile = get_mac_translation_file(); 295 296 my $onelanguage = $$languagestringref; 297 if ( $onelanguage =~ /^\s*(.*?)_/ ) { $onelanguage = $1; } 298 299 # Analyzing the ulf file, collecting all Identifier 300 my $allidentifier = get_identifier($translationfile); 301 302 for ( my $i = 0; $i <= $#{$allidentifier}; $i++ ) 303 { 304 my $identifier = ${$allidentifier}[$i]; 305 my $language_block = get_language_block_from_language_file($identifier, $translationfile); 306 my $newstring = get_language_string_from_language_block($language_block, $onelanguage); 307 308 # removing mask 309 $newstring =~ s/\\\'/\'/g; 310 311 replace_one_variable_in_shellscript($scriptfile, $newstring, $identifier); 312 } 313} 314 315################################################################################# 316# Replacing one variable in Mac shell script 317################################################################################# 318 319sub replace_one_variable_in_shellscript 320{ 321 my ($scriptfile, $variable, $searchstring) = @_; 322 323 for ( my $i = 0; $i <= $#{$scriptfile}; $i++ ) 324 { 325 ${$scriptfile}[$i] =~ s/\[$searchstring\]/$variable/g; 326 } 327} 328 329############################################# 330# Replacing variables in Mac shell script 331############################################# 332 333sub replace_variables_in_scriptfile 334{ 335 my ($scriptfile, $volume_name, $volume_name_app, $allvariables) = @_; 336 337 replace_one_variable_in_shellscript($scriptfile, $volume_name, "FULLPRODUCTNAME" ); 338 replace_one_variable_in_shellscript($scriptfile, $volume_name_app, "FULLAPPPRODUCTNAME" ); 339 replace_one_variable_in_shellscript($scriptfile, $allvariables->{'PRODUCTNAME'}, "PRODUCTNAME" ); 340 replace_one_variable_in_shellscript($scriptfile, $allvariables->{'PRODUCTVERSION'}, "PRODUCTVERSION" ); 341 342 my $scriptname = lc($allvariables->{'PRODUCTNAME'}) . "\.script"; 343 if ( $allvariables->{'PRODUCTNAME'} eq "OpenOffice" ) 344 { 345 $scriptname = "org.openoffice.script"; 346 } 347 348 replace_one_variable_in_shellscript($scriptfile, $scriptname, "SEARCHSCRIPTNAME" ); 349} 350 351############################################# 352# Creating the "simple" package. 353# "zip" for Windows 354# "tar.gz" for all other platforms 355# additionally "dmg" on Mac OS X 356############################################# 357 358sub create_package 359{ 360 my ( $installdir, $archivedir, $packagename, $allvariables, $includepatharrayref, $languagestringref, $format ) = @_; 361 362 $installer::logger::Info->printf("... creating %s file ...\n", $installer::globals::packageformat); 363 installer::logger::include_header_into_logfile("Creating $installer::globals::packageformat file:"); 364 365 # moving dir into temporary directory 366 my $pid = $$; # process id 367 my $tempdir = $installdir . "_temp" . "." . $pid; 368 my $systemcall = ""; 369 my $from = ""; 370 my $makesystemcall = 1; 371 my $return_to_start = 0; 372 installer::systemactions::rename_directory($installdir, $tempdir); 373 374 # creating new directory with original name 375 installer::systemactions::create_directory($archivedir); 376 377 my $archive = $archivedir . $installer::globals::separator . $packagename . $format; 378 379 if ( $archive =~ /zip$/ ) 380 { 381 $from = cwd(); 382 $return_to_start = 1; 383 chdir($tempdir); 384 if ( $^O =~ /os2/i ) 385 { 386 my $zip = Cwd::realpath($archive); 387 $systemcall = "$installer::globals::zippath -qr $zip ."; 388 } 389 else 390 { 391 $systemcall = "$installer::globals::zippath -qr $archive ."; 392 } 393 394 # Using Archive::Zip fails because of very long path names below "share/uno_packages/cache" 395 # my $packzip = Archive::Zip->new(); 396 # $packzip->addTree("."); # after changing into $tempdir 397 # $packzip->writeToFileNamed($archive); 398 # $makesystemcall = 0; 399 } 400 elsif ( $archive =~ /dmg$/ ) 401 { 402 my $folder = (( -l "$tempdir/$packagename/Applications" ) or ( -l "$tempdir/$packagename/opt" )) ? $packagename : "\."; 403 404 if ( $allvariables->{'PACK_INSTALLED'} ) { 405 $folder = $packagename; 406 } 407 408 # my $volume_name = $allvariables->{'PRODUCTNAME'} . ' ' . $allvariables->{'PRODUCTVERSION'}; # Adding PRODUCTVERSION makes this difficult to maintain! 409 my $volume_name = $allvariables->{'PRODUCTNAME'}; 410 my $volume_name_classic = $allvariables->{'PRODUCTNAME'} . ' ' . $allvariables->{'PRODUCTVERSION'}; 411 my $volume_name_classic_app = $volume_name; # "app" should not contain version number 412 # $volume_name = $volume_name . ' ' . $allvariables->{'PRODUCTEXTENSION'} if $allvariables->{'PRODUCTEXTENSION'}; # Adding PRODUCTEXTENSION makes this difficult to maintain! 413 $volume_name_classic = $volume_name_classic . ' ' . $allvariables->{'PRODUCTEXTENSION'} if $allvariables->{'PRODUCTEXTENSION'}; 414 $volume_name_classic_app = $volume_name_classic_app . ' ' . $allvariables->{'PRODUCTEXTENSION'} if $allvariables->{'PRODUCTEXTENSION'}; 415 if ( $allvariables->{'DMG_VOLUMEEXTENSION'} ) { 416 $volume_name = $volume_name . ' ' . $allvariables->{'DMG_VOLUMEEXTENSION'}; 417 $volume_name_classic = $volume_name_classic . ' ' . $allvariables->{'DMG_VOLUMEEXTENSION'}; 418 $volume_name_classic_app = $volume_name_classic_app . ' ' . $allvariables->{'DMG_VOLUMEEXTENSION'}; 419 } 420 421 my $sla = 'sla.r'; 422 my $ref = ""; 423 424 if ( ! $allvariables->{'HIDELICENSEDIALOG'} ) 425 { 426 $ref = installer::scriptitems::get_sourcepath_from_filename_and_includepath( \$sla, $includepatharrayref, 0); 427 } 428 429 my $localtempdir = $tempdir; 430 431 if (( $installer::globals::languagepack ) || ( $installer::globals::patch )) 432 { 433 $localtempdir = "$tempdir/$packagename"; 434 if ( $installer::globals::languagepack ) 435 { 436 $volume_name = "$volume_name Language Pack"; 437 $volume_name_classic = "$volume_name_classic Language Pack"; 438 $volume_name_classic_app = "$volume_name_classic_app Language Pack"; 439 } 440 if ( $installer::globals::patch ) 441 { 442 $volume_name = "$volume_name Patch"; 443 $volume_name_classic = "$volume_name_classic Patch"; 444 $volume_name_classic_app = "$volume_name_classic_app Patch"; 445 } 446 447 # Create tar ball named tarball.tar.bz2 448 # my $appfolder = $localtempdir . "/" . $volume_name . "\.app"; 449 my $appfolder = $localtempdir . "/" . $volume_name_classic_app . "\.app"; 450 my $contentsfolder = $appfolder . "/Contents"; 451 my $tarballname = "tarball.tar.bz2"; 452 453 my $localfrom = cwd(); 454 chdir $appfolder; 455 456 $systemcall = "tar -cjf $tarballname Contents/"; 457 458 $installer::logger::Info->printf("... %s ...\n", $systemcall); 459 my $localreturnvalue = system($systemcall); 460 $infoline = "Systemcall: $systemcall\n"; 461 $installer::logger::Lang->print($infoline); 462 463 if ($localreturnvalue) 464 { 465 $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; 466 $installer::logger::Lang->print($infoline); 467 } 468 else 469 { 470 $infoline = "Success: Executed \"$systemcall\" successfully!\n"; 471 $installer::logger::Lang->print($infoline); 472 } 473 474 # codesign treats loose files in Contents as unsigned nested code. 475 my $resourcesfolder = $contentsfolder . "/Resources"; 476 my $sourcefile = $appfolder . "/" . $tarballname; 477 my $destfile = $resourcesfolder . "/" . $tarballname; 478 479 installer::systemactions::remove_complete_directory($contentsfolder); 480 installer::systemactions::create_directory($contentsfolder); 481 installer::systemactions::create_directory($resourcesfolder); 482 483 installer::systemactions::copy_one_file($sourcefile, $destfile); 484 unlink($sourcefile); 485 486 # Copy two files into installation set next to the tar ball 487 # 1. "osx_install.applescript" 488 # 2 "OpenOffice.org Languagepack" 489 490 my $scriptrealfilename = "osx_install.applescript"; 491 my $scriptfilename = ""; 492 if ( $installer::globals::languagepack ) { $scriptfilename = "osx_install_languagepack.applescript"; } 493 if ( $installer::globals::patch ) { $scriptfilename = "osx_install_patch.applescript"; } 494 my $scripthelpersolverfilename = "mac_install.script"; 495 # my $scripthelperrealfilename = $volume_name; 496 my $scripthelperrealfilename = $volume_name_classic_app; 497 my $translationfilename = $installer::globals::macinstallfilename; 498 499 # Finding both files in solver 500 501 my $scriptref = installer::scriptitems::get_sourcepath_from_filename_and_includepath( \$scriptfilename, $includepatharrayref, 0); 502 if ($$scriptref eq "") { installer::exiter::exit_program("ERROR: Could not find Apple script $scriptfilename!", "create_package"); } 503 my $scripthelperref = installer::scriptitems::get_sourcepath_from_filename_and_includepath( \$scripthelpersolverfilename, $includepatharrayref, 0); 504 if ($$scripthelperref eq "") { installer::exiter::exit_program("ERROR: Could not find Apple script $scripthelpersolverfilename!", "create_package"); } 505 my $translationfileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath( \$translationfilename, $includepatharrayref, 0); 506 if ($$translationfileref eq "") { installer::exiter::exit_program("ERROR: Could not find Apple script translation file $translationfilename!", "create_package"); } 507 508 $scriptfilename = $resourcesfolder . "/" . $scriptrealfilename; 509 my $macosfolder = $contentsfolder . "/MacOS"; 510 installer::systemactions::create_directory($macosfolder); 511 $scripthelperrealfilename = $macosfolder . "/" . $scripthelperrealfilename; 512 513 installer::systemactions::copy_one_file($$scriptref, $scriptfilename); 514 installer::systemactions::copy_one_file($$scripthelperref, $scripthelperrealfilename); 515 516 # Replacing variables in script $scriptfilename 517 # Localizing script $scriptfilename 518 my $scriptfilecontent = installer::files::read_file($scriptfilename); 519 my $translationfilecontent = installer::files::read_file($$translationfileref); 520 localize_scriptfile($scriptfilecontent, $translationfilecontent, $languagestringref); 521 # replace_variables_in_scriptfile($scriptfilecontent, $volume_name, $allvariables); 522 replace_variables_in_scriptfile($scriptfilecontent, $volume_name_classic, $volume_name_classic_app, $allvariables); 523 installer::files::save_file($scriptfilename, $scriptfilecontent); 524 525 $systemcall = "chmod 775 " . "\"" . $scriptfilename . "\""; 526 system($systemcall); 527 $systemcall = "chmod 775 " . "\"" . $scripthelperrealfilename . "\""; 528 system($systemcall); 529 530 # Copy also Info.plist and icon file 531 # Finding both files in solver 532 my $iconfile = "ooo3_installer.icns"; 533 my $iconfileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath( \$iconfile, $includepatharrayref, 0); 534 if ($$iconfileref eq "") { installer::exiter::exit_program("ERROR: Could not find Apple script icon file $iconfile!", "create_package"); } 535 $destfile = $resourcesfolder . "/" . $iconfile; 536 installer::systemactions::copy_one_file($$iconfileref, $destfile); 537 538 my $infoplistfile = "Info.plist.langpack"; 539 my $installname = "Info.plist"; 540 my $infoplistfileref = installer::scriptitems::get_sourcepath_from_filename_and_includepath( \$infoplistfile, $includepatharrayref, 0); 541 if ($$infoplistfileref eq "") { installer::exiter::exit_program("ERROR: Could not find Apple script Info.plist: $infoplistfile!", "create_package"); } 542 $destfile = $contentsfolder . "/" . $installname; 543 installer::systemactions::copy_one_file($$infoplistfileref, $destfile); 544 545 # Replacing variables in Info.plist 546 $scriptfilecontent = installer::files::read_file($destfile); 547 # replace_one_variable_in_shellscript($scriptfilecontent, $volume_name, "FULLPRODUCTNAME" ); 548 replace_one_variable_in_shellscript($scriptfilecontent, $volume_name_classic_app, "FULLAPPPRODUCTNAME" ); # OpenOffice.org Language Pack 549 installer::files::save_file($destfile, $scriptfilecontent); 550 551 chdir $localfrom; 552 } 553 554 # A build-time load path left in a shipped Mach-O breaks at runtime, signed or not. 555 # The language-pack app is only scripts and a plist, so it has no Mach-O to check. 556 foreach my $appdir ( $installer::globals::languagepack ? () : glob("$localtempdir/$folder/*.app") ) 557 { 558 my $checkreturn = system($ENV{'SOLARENV'} . "/bin/macosx-check-load-commands.sh", $appdir); 559 if ( $checkreturn ) { installer::exiter::exit_program("ERROR: Unrelocated Mach-O load commands in $appdir!", "create_package"); } 560 } 561 562 # Code-sign the .app before it is sealed into the .dmg. Opt-in: without 563 # MACOSX_CODESIGNING_IDENTITY the installation set is left as it was. 564 if ( $ENV{'MACOSX_CODESIGNING_IDENTITY'} ) 565 { 566 my $signscript = $ENV{'SOLARENV'} . "/bin/macosx-codesign.sh"; 567 foreach my $appdir ( glob("$localtempdir/$folder/*.app") ) 568 { 569 my @signcall = ($signscript, "-i", $ENV{'MACOSX_CODESIGNING_IDENTITY'}); 570 push(@signcall, "-k", $ENV{'MACOSX_CODESIGNING_KEYCHAIN'}) if $ENV{'MACOSX_CODESIGNING_KEYCHAIN'}; 571 push(@signcall, "--notarize", $ENV{'MACOSX_NOTARY_PROFILE'}) if $ENV{'MACOSX_NOTARY_PROFILE'}; 572 push(@signcall, $appdir); 573 my $signreturn = system(@signcall); 574 if ( $signreturn ) { installer::exiter::exit_program("ERROR: Could not code-sign $appdir!", "create_package"); } 575 $installer::logger::Lang->print("Success: Code-signed $appdir\n"); 576 } 577 } 578 579 # "hdiutil makehybrid -hfs" stamps an (empty) com.apple.FinderInfo onto 580 # every file in the image, which makes "codesign --verify --strict" 581 # reject the signed application inside the .dmg and would fail 582 # notarization. "hdiutil create -srcfolder" copies the files as they 583 # are. (The -hfs-openfolder auto-open it also did is not supported on 584 # Apple Silicon any more: bless refuses it.) 585 # "-fs HFS+" is not optional: left to itself "hdiutil create" makes an 586 # APFS image on recent macOS, which will not mount before 10.12. 587 # "makehybrid -hfs" always produced HFS+. 588 $systemcall = "cd " . shell_quote($localtempdir) . 589 " && hdiutil create -srcfolder " . shell_quote($folder) . 590 " -volname " . shell_quote($volume_name) . 591 " -fs HFS+ -format UDZO -ov " . shell_quote($archive); 592 if (( $ref ne "" ) && ( $$ref ne "" )) { 593 $systemcall .= " && hdiutil unflatten " . shell_quote($archive) . 594 " && Rez -a " . shell_quote($$ref) . " -o " . shell_quote($archive) . 595 " && hdiutil flatten " . shell_quote($archive); 596 } 597 } 598 else 599 { 600 # getting the path of the getuid.so (Solaris) or fakeroot (Linux) 601 my $getuidlibrary = ""; 602 my $ldpreloadstring = ""; 603 if ( $installer::globals::issolarisbuild ) 604 { 605 $getuidlibrary = installer::download::get_path_for_library($includepatharrayref); 606 if ( $getuidlibrary ne "" ) { $ldpreloadstring = "LD_PRELOAD=" . $getuidlibrary; } 607 } 608 elsif ( $installer::globals::islinuxbuild ) 609 { 610 $ldpreloadstring = $ENV{'FAKEROOT'}; 611 } 612 613 $systemcall = "cd $tempdir; $ldpreloadstring tar -cf - . | gzip > $archive"; 614 } 615 616 if ( $makesystemcall ) 617 { 618 $installer::logger::Info->printf("... %s ...\n", $systemcall); 619 my $returnvalue = system($systemcall); 620 my $infoline = "Systemcall: $systemcall\n"; 621 $installer::logger::Lang->print($infoline); 622 623 if ($returnvalue) 624 { 625 $infoline = "ERROR: Could not execute \"$systemcall\"!\n"; 626 $installer::logger::Lang->print($infoline); 627 } 628 else 629 { 630 $infoline = "Success: Executed \"$systemcall\" successfully!\n"; 631 $installer::logger::Lang->print($infoline); 632 # Sign the finished disk image. This completes the chain: the .app 633 # inside was signed before the image was built, and the image itself 634 # is signed here. It has to happen at this point rather than earlier - 635 # the Rez step above rewrites the image to attach the license 636 # resource, and that would invalidate a signature applied before it. 637 # 638 # Skipped for an ad-hoc identity: an ad-hoc signed .dmg buys nothing 639 # (Gatekeeper rejects it either way) and macosx-codesign.sh refuses 640 # it outright, which would turn a working ad-hoc build into an error. 641 if (( $archive =~ /dmg$/ ) && 642 ( $ENV{'MACOSX_CODESIGNING_IDENTITY'} ) && 643 ( $ENV{'MACOSX_CODESIGNING_IDENTITY'} ne "-" )) 644 { 645 my $signscript = $ENV{'SOLARENV'} . "/bin/macosx-codesign.sh"; 646 my @signcall = ($signscript, "-i", $ENV{'MACOSX_CODESIGNING_IDENTITY'}); 647 push(@signcall, "-k", $ENV{'MACOSX_CODESIGNING_KEYCHAIN'}) if $ENV{'MACOSX_CODESIGNING_KEYCHAIN'}; 648 push(@signcall, "--notarize", $ENV{'MACOSX_NOTARY_PROFILE'}) if $ENV{'MACOSX_NOTARY_PROFILE'}; 649 push(@signcall, $archive); 650 my $signreturn = system(@signcall); 651 if ( $signreturn ) { installer::exiter::exit_program("ERROR: Could not code-sign $archive!", "create_package"); } 652 $installer::logger::Lang->print("Success: Code-signed $archive\n"); 653 } 654 } 655 } 656 657 if ( $return_to_start ) { chdir($from); } 658 659 $installer::logger::Info->printf("... removing %s ...\n", $tempdir); 660 installer::systemactions::remove_complete_directory($tempdir); 661} 662 663#################################################### 664# Main method for creating the simple package 665# installation sets 666#################################################### 667 668sub create_simple_package 669{ 670 my ( $filesref, $dirsref, $scpactionsref, $linksref, $unixlinksref, $loggingdir, $languagestringref, $shipinstalldir, $allsettingsarrayref, $allvariables, $includepatharrayref ) = @_; 671 672 # Creating directories 673 674 my $current_install_number = ""; 675 my $infoline = ""; 676 677 $installer::logger::Info->print( "... creating installation directory ...\n" ); 678 installer::logger::include_header_into_logfile("Creating installation directory"); 679 680 $installer::globals::csp_installdir = installer::worker::create_installation_directory($shipinstalldir, $languagestringref, \$current_install_number); 681 $installer::globals::csp_installlogdir = installer::systemactions::create_directory_next_to_directory($installer::globals::csp_installdir, "log"); 682 683 my $installdir = $installer::globals::csp_installdir; 684 my $installlogdir = $installer::globals::csp_installlogdir; 685 686 # Setting package name (similar to the download name) 687 my $packagename = ""; 688 689 if ( $installer::globals::packageformat eq "archive" || 690 $installer::globals::packageformat eq "dmg" ) 691 { 692 $installer::globals::csp_languagestring = $$languagestringref; 693 694 my $locallanguage = $installer::globals::csp_languagestring; 695 696 if ( $allvariables->{'AOODOWNLOADNAME'} ) 697 { 698 $packagename = installer::download::set_download_filename(\$locallanguage, $allvariables); 699 } 700 else 701 { 702 $downloadname = installer::ziplist::getinfofromziplist($allsettingsarrayref, "downloadname"); 703 if ( $installer::globals::languagepack ) { $downloadname = installer::ziplist::getinfofromziplist($allsettingsarrayref, "langpackdownloadname"); } 704 if ( $installer::globals::patch ) { $downloadname = installer::ziplist::getinfofromziplist($allsettingsarrayref, "patchdownloadname"); } 705 $packagename = installer::download::resolve_variables_in_downloadname($allvariables, $$downloadname, \$locallanguage); 706 } 707 } 708 709 # Work around Windows problems with long pathnames (see issue 50885) by 710 # putting the to-be-archived installation tree into the temp directory 711 # instead of the module output tree (unless LOCALINSTALLDIR dictates 712 # otherwise, anyway); can be removed once issue 50885 is fixed: 713 my $tempinstalldir = $installdir; 714 if ( $installer::globals::iswindowsbuild && 715 $installer::globals::packageformat eq "archive" && 716 !$installer::globals::localinstalldirset ) 717 { 718 $tempinstalldir = File::Temp::tempdir; 719 } 720 721 # Creating subfolder in installdir, which shall become the root of package or zip file 722 my $subfolderdir = ""; 723 if ( $packagename ne "" ) { $subfolderdir = $tempinstalldir . $installer::globals::separator . $packagename; } 724 else { $subfolderdir = $tempinstalldir; } 725 726 if ( ! -d $subfolderdir ) { installer::systemactions::create_directory($subfolderdir); } 727 728 # Create directories, copy files and ScpActions 729 730 $installer::logger::Info->print("... creating directories ...\n"); 731 installer::logger::include_header_into_logfile("Creating directories:"); 732 733 for ( my $i = 0; $i <= $#{$dirsref}; $i++ ) 734 { 735 my $onedir = ${$dirsref}[$i]; 736 737 if ( $onedir->{'HostName'} ) 738 { 739 my $destdir = $subfolderdir . $installer::globals::separator . $onedir->{'HostName'}; 740 741 if ( ! -d $destdir ) 742 { 743 if ( $^O =~ /cygwin/i || $^O =~ /os2/i ) # Cygwin performance check 744 { 745 $installer::logger::Lang->printf("Try to create directory %s\n", $destdir); 746 # Directories in $dirsref are sorted and all parents were added -> "mkdir" works without parent creation! 747 if ( ! ( -d $destdir )) { mkdir($destdir, 0775); } 748 } 749 else 750 { 751 installer::systemactions::create_directory_structure($destdir); 752 } 753 } 754 } 755 } 756 757 # stripping files ?! 758 if (( $installer::globals::strip ) && ( ! $installer::globals::iswindowsbuild ) && ( ! $installer::globals::isos2 )) { installer::strip::strip_libraries($filesref, $languagestringref); } 759 760 # copy Files 761 $installer::logger::Info->print("... copying files ...\n"); 762 installer::logger::include_header_into_logfile("Copying files:"); 763 764 for ( my $i = 0; $i <= $#{$filesref}; $i++ ) 765 { 766 my $onefile = ${$filesref}[$i]; 767 768 if (( $onefile->{'Styles'} ) && ( $onefile->{'Styles'} =~ /\bBINARYTABLE_ONLY\b/ )) { next; } 769 if (( $installer::globals::patch ) && ( $onefile->{'Styles'} ) && ( ! ( $onefile->{'Styles'} =~ /\bPATCH\b/ ))) { next; } 770 if (( $installer::globals::patch ) && ( $installer::globals::packageformat eq "dmg" )) { push(@installer::globals::patchfilecollector, "$onefile->{'destination'}\n"); } 771 772 my $source = $onefile->{'sourcepath'}; 773 my $destination = $onefile->{'destination'}; 774 $destination = $subfolderdir . $installer::globals::separator . $destination; 775 776 # Replacing $$ by $ is necessary to install files with $ in its name (back-masquerading) 777 # Otherwise, the following shell command does not work and the file list is not correct 778 $source =~ s/\$\$/\$/; 779 $destination =~ s/\$\$/\$/; 780 781 if ( $^O =~ /cygwin/i || $^O =~ /os2/i ) # Cygwin performance, do not use copy_one_file. "chmod -R" at the end 782 { 783 my $copyreturn = copy($source, $destination); 784 785 if ($copyreturn) 786 { 787 $installer::logger::Lang->printf("Copy: $source to %s\n", $destination); 788 $returnvalue = 1; 789 } 790 else 791 { 792 $installer::logger::Lang->printf("ERROR: Could not copy %s to %s\n", $source, $destination); 793 $returnvalue = 0; 794 } 795 } 796 else 797 { 798 installer::systemactions::copy_one_file($source, $destination); 799 800 if ( ! $installer::globals::iswindowsbuild ) 801 { 802 # see issue 102274 803 my $unixrights = ""; 804 if ( $onefile->{'UnixRights'} ) 805 { 806 $unixrights = $onefile->{'UnixRights'}; 807 808 my $localcall = "$installer::globals::wrapcmd chmod $unixrights \'$destination\' \>\/dev\/null 2\>\&1"; 809 system($localcall); 810 } 811 } 812 } 813 } 814 815 # creating Links 816 817 $installer::logger::Info->print("... creating links ...\n"); 818 installer::logger::include_header_into_logfile("Creating links:"); 819 820 for ( my $i = 0; $i <= $#{$linksref}; $i++ ) 821 { 822 my $onelink = ${$linksref}[$i]; 823 824 if (( $installer::globals::patch ) && ( $onelink->{'Styles'} ) && ( ! ( $onelink->{'Styles'} =~ /\bPATCH\b/ ))) { next; } 825 826 my $destination = $onelink->{'destination'}; 827 $destination = $subfolderdir . $installer::globals::separator . $destination; 828 my $destinationfile = $onelink->{'destinationfile'}; 829 830 my $localcall = "ln -sf \'$destinationfile\' \'$destination\' \>\/dev\/null 2\>\&1"; 831 system($localcall); 832 833 $installer::logger::Lang->printf("Creating link: \"ln -sf %s %s\"\n", 834 $destinationfile, 835 $destination); 836 } 837 838 for ( my $i = 0; $i <= $#{$unixlinksref}; $i++ ) 839 { 840 my $onelink = ${$unixlinksref}[$i]; 841 842 if (( $installer::globals::patch ) && ( $onelink->{'Styles'} ) && ( ! ( $onelink->{'Styles'} =~ /\bPATCH\b/ ))) { next; } 843 844 my $target = $onelink->{'Target'}; 845 my $destination = $subfolderdir . $installer::globals::separator . $onelink->{'destination'}; 846 847 my $localcall = "ln -sf \'$target\' \'$destination\' \>\/dev\/null 2\>\&1"; 848 system($localcall); 849 850 $installer::logger::Lang->printf("Creating Unix link: \"ln -sf %s %s\"\n", 851 $target, 852 $destination); 853 } 854 855 # Setting privileges for cygwin globally 856 857 if ( $^O =~ /cygwin/i ) 858 { 859 $installer::logger::Lang->print( "... changing privileges in $subfolderdir ...\n" ); 860 installer::logger::include_header_into_logfile("Changing privileges in $subfolderdir:"); 861 862 my $localcall = "chmod -R 755 " . "\"" . $subfolderdir . "\""; 863 system($localcall); 864 } 865 866 $installer::logger::Lang->print( "... removing superfluous directories ...\n" ); 867 installer::logger::include_header_into_logfile("Removing superfluous directories:"); 868 869 my ( $extensionfolder, $preregdir ) = get_extensions_dir($subfolderdir); 870 installer::systemactions::remove_empty_dirs_in_folder($extensionfolder); 871 872 # Registering the extensions 873 874 $installer::logger::Lang->print( "... registering extensions ...\n" ); 875 installer::logger::include_header_into_logfile("Registering extensions:"); 876 register_extensions($subfolderdir, $languagestringref, $preregdir); 877 878 if ( $installer::globals::compiler =~ /^unxmac/ ) 879 { 880 installer::worker::put_scpactions_into_installset("$installdir/$packagename"); 881 } 882 883 # Creating archive file 884 if ( $installer::globals::packageformat eq "archive" ) 885 { 886 create_package($tempinstalldir, $installdir, $packagename, $allvariables, $includepatharrayref, $languagestringref, $installer::globals::archiveformat); 887 } 888 elsif ( $installer::globals::packageformat eq "dmg" ) 889 { 890 create_package($installdir, $installdir, $packagename, $allvariables, $includepatharrayref, $languagestringref, ".dmg"); 891 } 892 893 # Analyzing the log file 894 895 installer::worker::clean_output_tree(); # removing directories created in the output tree 896 installer::worker::analyze_and_save_logfile($loggingdir, $installdir, $installlogdir, $allsettingsarrayref, $languagestringref, $current_install_number); 897} 898 8991; 900