The branch, release/4.0.0.x has been updated via 5bcc8e1aa722ea013d68fa863b764af5027b2b2e (commit) via 16d3a91db10c575f0447a3f1df8b3011752ba475 (commit) from d351dcec2702444a87ff9eafb5a1733281be6e85 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 5bcc8e1aa722ea013d68fa863b764af5027b2b2e Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Fri Mar 1 21:24:53 2013 +0100 Add scripts and additional files for building X2Go Client disk images for Mac OS X. (Fixes: #131). commit 16d3a91db10c575f0447a3f1df8b3011752ba475 Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Fri Mar 1 21:23:03 2013 +0100 Continue development... ----------------------------------------------------------------------- Summary of changes: VERSION | 2 +- debian/changelog | 9 + macbuild.sh | 68 ++ macdmg.DS_Store | Bin 0 -> 15364 bytes pkg-dmg | 1523 +++++++++++++++++++++++++++++++++++++++ png/macinstaller_background.png | Bin 0 -> 59943 bytes svg/macinstaller_background.svg | 630 ++++++++++++++++ version.h | 2 +- x2goclient.pro | 3 - x2goplugin.rc | 12 +- 10 files changed, 2238 insertions(+), 11 deletions(-) create mode 100755 macbuild.sh create mode 100644 macdmg.DS_Store create mode 100755 pkg-dmg create mode 100644 png/macinstaller_background.png create mode 100644 svg/macinstaller_background.svg The diff of changes is: diff --git a/VERSION b/VERSION index 3ab15cd..6813a82 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.0.0.3 +4.0.0.4 diff --git a/debian/changelog b/debian/changelog index 31ac841..bce38bb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +x2goclient (4.0.0.4-0~x2go1) UNRELEASED; urgency=low + + [ Clemens Lang ] + * New upstream version (4.0.0.4): + - Add scripts and additional files for building X2Go Client + disk images for Mac OS X. (Fixes: #131). + + -- Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Fri, 01 Mar 2013 21:20:27 +0100 + x2goclient (4.0.0.3-0~x2go1) unstable; urgency=low * Fix version in version.h, VERSION and x2goplugin.rc. diff --git a/macbuild.sh b/macbuild.sh new file mode 100755 index 0000000..70084e6 --- /dev/null +++ b/macbuild.sh @@ -0,0 +1,68 @@ +#!/bin/sh +NAME=x2goclient +APPBUNDLE=./$NAME.app +DMGFILE=./$NAME.dmg +PROJECT=./$NAME.pro +PKG_DMG=./pkg-dmg + +NXPROXY=`which nxproxy` +LIBXCOMP=libXcomp.3.dylib +LIBPNG=libpng15.15.dylib +LIBJPEG=libjpeg.9.dylib +LIBZ=libz.1.dylib + +set -e + +function phase() { + echo + echo "***" + echo "*** ${1}…" + echo "***" + echo +} + +phase "Cleaning" +make clean +rm -rf "$APPBUNDLE" +rm -rf "$DMGFILE" + +phase "Running lrelease" +lrelease "$PROJECT" + +phase "Running qmake" +qmake -config release \ + CONFIG+=x86_64 \ + QMAKE_MAC_SDK=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk \ + QMAKE_MACOSX_DEPLOYMENT_TARGET=10.7 + +phase "Running make" +make -j2 + +phase "Copying nxproxy" +mkdir -p "$APPBUNDLE/Contents/exe" +cp "$NXPROXY" "$APPBUNDLE/Contents/exe" +dylibbundler \ + --fix-file "$APPBUNDLE/Contents/exe/nxproxy" \ + --bundle-deps \ + --dest-dir "$APPBUNDLE/Contents/Frameworks" \ + --install-path "@executable_path/../Frameworks/" \ + --create-dir + +phase "Bundling up using macdeployqt" +macdeployqt "$APPBUNDLE" -verbose=2 + +phase "Creating DMG" +$PKG_DMG \ + --source "$APPBUNDLE" \ + --sourcefile \ + --target "$DMGFILE" \ + --volname "x2goclient" \ + --verbosity 2 \ + --mkdir "/.background" \ + --copy "./png/macinstaller_background.png:/.background" \ + --copy "./macdmg.DS_Store:/.DS_Store" \ + --copy "./LICENSE" \ + --copy "./COPYING" \ + --symlink "/Applications: " \ + --icon "./icons/x2go-mac.icns" \ + --format "UDBZ" diff --git a/macdmg.DS_Store b/macdmg.DS_Store new file mode 100644 index 0000000..b5db793 Binary files /dev/null and b/macdmg.DS_Store differ diff --git a/pkg-dmg b/pkg-dmg new file mode 100755 index 0000000..82b9010 --- /dev/null +++ b/pkg-dmg @@ -0,0 +1,1523 @@ +#!/usr/bin/perl +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is pkg-dmg, a Mac OS X disk image (.dmg) packager +# +# The Initial Developer of the Original Code is +# Mark Mentovai <mark@moxienet.com>. +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +use strict; +use warnings; + +=pod + +=head1 NAME + +B<pkg-dmg> - Mac OS X disk image (.dmg) packager + +=head1 SYNOPSIS + +B<pkg-dmg> +B<--source> I<source-folder> +B<--target> I<target-image> +[B<--format> I<format>] +[B<--volname> I<volume-name>] +[B<--tempdir> I<temp-dir>] +[B<--mkdir> I<directory>] +[B<--copy> I<source>[:I<dest>]] +[B<--symlink> I<source>[:I<dest>]] +[B<--license> I<file>] +[B<--resource> I<file>] +[B<--icon> I<icns-file>] +[B<--attribute> I<a>:I<file>[:I<file>...] +[B<--idme>] +[B<--sourcefile>] +[B<--verbosity> I<level>] +[B<--dry-run>] + +=head1 DESCRIPTION + +I<pkg-dmg> takes a directory identified by I<source-folder> and transforms +it into a disk image stored as I<target-image>. The disk image will +occupy the least space possible for its format, or the least space that the +authors have been able to figure out how to achieve. + +=head1 OPTIONS + +=over 5 + +==item B<--source> I<source-folder> + +Identifies the directory that will be packaged up. This directory is not +touched, a copy will be made in a temporary directory for staging purposes. +See B<--tempdir>. + +==item B<--target> I<target-image> + +The disk image to create. If it exists and is not in use, it will be +overwritten. If I<target-image> already contains a suitable extension, +it will be used unmodified. If no extension is present, or the extension +is incorrect for the selected format, the proper extension will be added. +See B<--format>. + +==item B<--format> I<format> + +The format to create the disk image in. Valid values for I<format> are: + - UDZO - zlib-compressed, read-only; extension I<.dmg> + - UDBZ - bzip2-compressed, read-only; extension I<.dmg>; + create and use on 10.4 ("Tiger") and later only + - UDRO - uncompressed, read-only; extension I<.dmg> + - UDRW - uncompressed, read-write; extension I<.dmg> + - UDSP - uncompressed, read-write, sparse; extension I<.sparseimage> + +UDZO is the default format. + +See L<hdiutil(1)> for a description of these formats. + +=item B<--volname> I<volume-name> + +The name of the volume in the disk image. If not specified, I<volume-name> +defaults to the name of the source directory from B<--source>. + +=item B<--tempdir> I<temp-dir> + +A temporary directory to stage intermediate files in. I<temp-dir> must +have enough space available to accommodate twice the size of the files +being packaged. If not specified, defaults to the same directory that +the I<target-image> is to be placed in. B<pkg-dmg> will remove any +temporary files it places in I<temp-dir>. + +=item B<--mkdir> I<directory> + +Specifies a directory that should be created in the disk image. +I<directory> and any ancestor directories will be created. This is +useful in conjunction with B<--copy>, when copying files to directories +that may not exist in I<source-folder>. B<--mkdir> may appear multiple +times. + +=item B<--copy> I<source>[:I<dest>] + +Additional files to copy into the disk image. If I<dest> is +specified, I<source> is copied to the location I<dest> identifies, +otherwise, I<source> is copied to the root of the new volume. B<--copy> +provides a way to package up a I<source-folder> by adding files to it +without modifying the original I<source-folder>. B<--copy> may appear +multiple times. + +This option is useful for adding .DS_Store files and window backgrounds +to disk images. + +=item B<--symlink> I<source>[:I<dest>] + +Like B<--copy>, but allows symlinks to point out of the volume. Empty symlink +destinations are interpreted as "like the source path, but inside the dmg" + +This option is useful for adding symlinks to external resources, +e.g. to /Applications. + +=item B<--license> I<file> + +A plain text file containing a license agreement to be displayed before +the disk image is mounted. English is the only supported language. To +include license agreements in other languages, in multiple languages, +or to use formatted text, prepare a resource and use L<--resource>. + +=item B<--resource> I<file> + +A resource file to merge into I<target-image>. If I<format> is UDZO, UDBZ, +or UDRO, the disk image will be flattened to a single-fork file that contains +the resource but may be freely transferred without any special encodings. +I<file> must be in a format suitable for L<Rez(1)>. See L<Rez(1)> for a +description of the format, and L<hdiutil(1)> for a discussion on flattened +disk images. B<--resource> may appear multiple times. + +This option is useful for adding license agreements and other messages +to disk images. + +=item B<--icon> I<icns-file> + +Specifies an I<icns> file that will be used as the icon for the root of +the volume. This file will be copied to the new volume and the custom +icon attribute will be set on the root folder. + +=item B<--attribute> I<a>:I<file>[:I<file>...] + +Sets the attributes of I<file> to the attribute list in I<a>. See +L<SetFile(1)> + +=item B<--idme> + +Enable IDME to make the disk image "Internet-enabled." The first time +the image is mounted, if IDME processing is enabled on the system, the +contents of the image will be copied out of the image and the image will +be placed in the trash with IDME disabled. + +=item B<--sourcefile> + +If this option is present, I<source-folder> is treated as a file, and is +placed as a file within the volume's root folder. Without this option, +I<source-folder> is treated as the volume root itself. + +=item B<--verbosity> I<level> + +Adjusts the level of loudness of B<pkg-dmg>. The possible values for +I<level> are: + 0 - Only error messages are displayed. + 1 - Print error messages and command invocations. + 2 - Print everything, including command output. + +The default I<level> is 2. + +=item B<--dry-run> + +When specified, the commands that would be executed are printed, without +actually executing them. When commands depend on the output of previous +commands, dummy values are displayed. + +=back + +=head1 NON-OPTIONS + +=over 5 + +=item + +Resource forks aren't copied. + +=item + +The root folder of the created volume is designated as the folder +to open when the volume is mounted. See L<bless(8)>. + +=item + +All files in the volume are set to be world-readable, only writable +by the owner, and world-executable when appropriate. All other +permissions bits are cleared. + +=item + +When possible, disk images are created without any partition tables. This +is what L<hdiutil(1)> refers to as I<-layout NONE>, and saves a handful of +kilobytes. The alternative, I<SPUD>, contains a partition table that +is not terribly handy on disk images that are not intended to represent any +physical disk. + +=item + +Read-write images are created with journaling off. Any read-write image +created by this tool is expected to be transient, and the goal of this tool +is to create images which consume a minimum of space. + +=back + +=head1 EXAMPLE + +pkg-dmg --source /Applications/DeerPark.app --target ~/DeerPark.dmg + --sourcefile --volname DeerPark --icon ~/DeerPark.icns + --mkdir /.background + --copy DeerParkBackground.png:/.background/background.png + --copy DeerParkDSStore:/.DS_Store + --symlink /Applications:"/Drag to here" + +=head1 REQUIREMENTS + +I<pkg-dmg> has been tested with Mac OS X releases 10.2 ("Jaguar") +through 10.4 ("Tiger"). Certain adjustments to behavior are made +depending on the host system's release. Mac OS X 10.3 ("Panther") or +later are recommended. + +=head1 LICENSE + +MPL 1.1/GPL 2.0/LGPL 2.1. Your choice. + +=head1 AUTHOR + +Mark Mentovai + +=head1 SEE ALSO + +L<bless(8)>, L<diskutil(8)>, L<hdid(8)>, L<hdiutil(1)>, L<Rez(1)>, +L<rsync(1)>, L<SetFile(1)> + +=cut + +use Fcntl; +use POSIX; +use Getopt::Long; + +sub argumentEscape(@); +sub cleanupDie($); +sub command(@); +sub commandInternal($@); +sub commandInternalVerbosity($$@); +sub commandOutput(@); +sub commandOutputVerbosity($@); +sub commandVerbosity($@); +sub copyFiles($@); +sub diskImageMaker($$$$$$$$); +sub giveExtension($$); +sub hdidMountImage($@); +sub isFormatReadOnly($); +sub licenseMaker($$); +sub pathSplit($); +sub setAttributes($@); +sub trapSignal($); +sub usage(); + +# Variables used as globals +my(@gCleanup, %gConfig, $gDarwinMajor, $gDryRun, $gVerbosity); + +# Use the commands by name if they're expected to be in the user's +# $PATH (/bin:/sbin:/usr/bin:/usr/sbin). Otherwise, go by absolute +# path. These may be overridden with --config. +%gConfig = ('cmd_bless' => 'bless', + 'cmd_chmod' => 'chmod', + 'cmd_diskutil' => 'diskutil', + 'cmd_du' => 'du', + 'cmd_hdid' => 'hdid', + 'cmd_hdiutil' => 'hdiutil', + 'cmd_mkdir' => 'mkdir', + 'cmd_mktemp' => 'mktemp', + 'cmd_Rez' => '/usr/bin/Rez', + 'cmd_rm' => 'rm', + 'cmd_rsync' => 'rsync', + 'cmd_SetFile' => '/usr/bin/SetFile', + + # create_directly indicates whether hdiutil create supports + # -srcfolder and -srcdevice. It does on >= 10.3 (Panther). + # This is fixed up for earlier systems below. If false, + # hdiutil create is used to create empty disk images that + # are manually filled. + 'create_directly' => 1, + + # If hdiutil attach -mountpoint exists, use it to avoid + # mounting disk images in the default /Volumes. This reduces + # the likelihood that someone will notice a mounted image and + # interfere with it. Only available on >= 10.3 (Panther), + # fixed up for earlier systems below. + # + # This is presently turned off for all systems, because there + # is an infrequent synchronization problem during ejection. + # diskutil eject might return before the image is actually + # unmounted. If pkg-dmg then attempts to clean up its + # temporary directory, it could remove items from a read-write + # disk image or attempt to remove items from a read-only disk + # image (or a read-only item from a read-write image) and fail, + # causing pkg-dmg to abort. This problem is experienced + # under Tiger, which appears to eject asynchronously where + # previous systems treated it as a synchronous operation. + # Using hdiutil attach -mountpoint didn't always keep images + # from showing up on the desktop anyway. + 'hdiutil_mountpoint' => 0, + + # hdiutil makehybrid results in optimized disk images that + # consume less space and mount more quickly. Use it when + # it's available, but that's only on >= 10.3 (Panther). + # If false, hdiutil create is used instead. Fixed up for + # earlier systems below. + 'makehybrid' => 1, + + # hdiutil create doesn't allow specifying a folder to open + # at volume mount time, so those images are mounted and + # their root folders made holy with bless -openfolder. But + # only on >= 10.3 (Panther). Earlier systems are out of luck. + # Even on Panther, bless refuses to run unless root. + # Fixed up below. + 'openfolder_bless' => 1, + + # It's possible to save a few more kilobytes by including the + # partition only without any partition table in the image. + # This is a good idea on any system, so turn this option off. + # + # Except it's buggy. "-layout NONE" seems to be creating + # disk images with more data than just the partition table + # stripped out. You might wind up losing the end of the + # filesystem - the last file (or several) might be incomplete. + 'partition_table' => 1, + + # To create a partition table-less image from something + # created by makehybrid, the hybrid image needs to be + # mounted and a new image made from the device associated + # with the relevant partition. This requires >= 10.4 + # (Tiger), presumably because earlier systems have + # problems creating images from devices themselves attached + # to images. If this is false, makehybrid images will + # have partition tables, regardless of the partition_table + # setting. Fixed up for earlier systems below. + 'recursive_access' => 1); + +# --verbosity +$gVerbosity = 2; + +# --dry-run +$gDryRun = 0; + +# %gConfig fix-ups based on features and bugs present in certain releases. +my($ignore, $uname_r, $uname_s); +($uname_s, $ignore, $uname_r, $ignore, $ignore) = POSIX::uname(); +if($uname_s eq 'Darwin') { + ($gDarwinMajor, $ignore) = split(/\./, $uname_r, 2); + + # $major is the Darwin major release, which for our purposes, is 4 higher + # than the interesting digit in a Mac OS X release. + if($gDarwinMajor <= 6) { + # <= 10.2 (Jaguar) + # hdiutil create does not support -srcfolder or -srcdevice + $gConfig{'create_directly'} = 0; + # hdiutil attach does not support -mountpoint + $gConfig{'hdiutil_mountpoint'} = 0; + # hdiutil mkhybrid does not exist + $gConfig{'makehybrid'} = 0; + } + if($gDarwinMajor <= 7) { + # <= 10.3 (Panther) + # Can't mount a disk image and then make a disk image from the device + $gConfig{'recursive_access'} = 0; + # bless does not support -openfolder on 10.2 (Jaguar) and must run + # as root under 10.3 (Panther) + $gConfig{'openfolder_bless'} = 0; + } +} +else { + # If it's not Mac OS X, just assume all of those good features are + # available. They're not, but things will fail long before they + # have a chance to make a difference. + # + # Now, if someone wanted to document some of these private formats... + print STDERR ($0.": warning, not running on Mac OS X, ". + "this could be interesting.\n"); +} + +# Non-global variables used in Getopt +my(@attributes, @copyFiles, @createSymlinks, $iconFile, $idme, $licenseFile, + @makeDirs, $outputFormat, @resourceFiles, $sourceFile, $sourceFolder, + $targetImage, $tempDir, $volumeName); + +# --format +$outputFormat = 'UDZO'; + +# --idme +$idme = 0; + +# --sourcefile +$sourceFile = 0; + +# Leaving this might screw up the Apple tools. +delete $ENV{'NEXT_ROOT'}; + +# This script can get pretty messy, so trap a few signals. +$SIG{'INT'} = \&trapSignal; +$SIG{'HUP'} = \&trapSignal; +$SIG{'TERM'} = \&trapSignal; + +Getopt::Long::Configure('pass_through'); +GetOptions('source=s' => \$sourceFolder, + 'target=s' => \$targetImage, + 'volname=s' => \$volumeName, + 'format=s' => \$outputFormat, + 'tempdir=s' => \$tempDir, + 'mkdir=s' => \@makeDirs, + 'copy=s' => \@copyFiles, + 'symlink=s' => \@createSymlinks, + 'license=s' => \$licenseFile, + 'resource=s' => \@resourceFiles, + 'icon=s' => \$iconFile, + 'attribute=s' => \@attributes, + 'idme' => \$idme, + 'sourcefile' => \$sourceFile, + 'verbosity=i' => \$gVerbosity, + 'dry-run' => \$gDryRun, + 'config=s' => \%gConfig); # "hidden" option not in usage() + +if(@ARGV) { + # All arguments are parsed by Getopt + usage(); + exit(1); +} + +if($gVerbosity<0 || $gVerbosity>2) { + usage(); + exit(1); +} + +if(!defined($sourceFolder) || $sourceFolder eq '' || + !defined($targetImage) || $targetImage eq '') { + # --source and --target are required arguments + usage(); + exit(1); +} + +# Make sure $sourceFolder doesn't contain trailing slashes. It messes with +# rsync. +while(substr($sourceFolder, -1) eq '/') { + chop($sourceFolder); +} + +if(!defined($volumeName)) { + # Default volumeName is the name of the source directory. + my(@components); + @components = pathSplit($sourceFolder); + $volumeName = pop(@components); +} + +my(@tempDirComponents, $targetImageFilename); +@tempDirComponents = pathSplit($targetImage); +$targetImageFilename = pop(@tempDirComponents); + +if(defined($tempDir)) { + @tempDirComponents = pathSplit($tempDir); +} +else { + # Default tempDir is the same directory as what is specified for + # targetImage + $tempDir = join('/', @tempDirComponents); +} + +# Ensure that the path of the target image has a suitable extension. If +# it didn't, hdiutil would add one, and we wouldn't be able to find the +# file. +# +# Note that $targetImageFilename is not being reset. This is because it's +# used to build other names below, and we don't need to be adding all sorts +# of extra unnecessary extensions to the name. +my($originalTargetImage, $requiredExtension); +$originalTargetImage = $targetImage; +if($outputFormat eq 'UDSP') { + $requiredExtension = '.sparseimage'; +} +else { + $requiredExtension = '.dmg'; +} +$targetImage = giveExtension($originalTargetImage, $requiredExtension); + +if($targetImage ne $originalTargetImage) { + print STDERR ($0.": warning: target image extension is being added\n"); + print STDERR (' The new filename is '. + giveExtension($targetImageFilename,$requiredExtension)."\n"); +} + +# Make a temporary directory in $tempDir for our own nefarious purposes. +my(@output, $tempSubdir, $tempSubdirTemplate); +$tempSubdirTemplate=join('/', @tempDirComponents, + 'pkg-dmg.'.$$.'.XXXXXXXX'); +if(!(@output = commandOutput($gConfig{'cmd_mktemp'}, '-d', + $tempSubdirTemplate)) || $#output != 0) { + cleanupDie('mktemp failed'); +} + +if($gDryRun) { + (@output)=($tempSubdirTemplate); +} + +($tempSubdir) = @output; + +push(@gCleanup, + sub {commandVerbosity(0, $gConfig{'cmd_rm'}, '-rf', $tempSubdir);}); + +my($tempMount, $tempRoot, @tempsToMake); +$tempRoot = $tempSubdir.'/stage'; +$tempMount = $tempSubdir.'/mount'; +push(@tempsToMake, $tempRoot); +if($gConfig{'hdiutil_mountpoint'}) { + push(@tempsToMake, $tempMount); +} + +if(command($gConfig{'cmd_mkdir'}, @tempsToMake) != 0) { + cleanupDie('mkdir tempRoot/tempMount failed'); +} + +# This cleanup object is not strictly necessary, because $tempRoot is inside +# of $tempSubdir, but the rest of the script relies on this object being +# on the cleanup stack and expects to remove it. +push(@gCleanup, + sub {commandVerbosity(0, $gConfig{'cmd_rm'}, '-rf', $tempRoot);}); + +# If $sourceFile is true, it means that $sourceFolder is to be treated as +# a file and placed as a file within the volume root, as opposed to being +# treated as the volume root itself. rsync will do this by default, if no +# trailing '/' is present. With a trailing '/', $sourceFolder becomes +# $tempRoot, instead of becoming an entry in $tempRoot. +if(command($gConfig{'cmd_rsync'}, '-aC', '--include', '*.so', + '--copy-unsafe-links', $sourceFolder.($sourceFile?'':'/'),$tempRoot) != 0) { + cleanupDie('rsync failed'); +} + +if(@makeDirs) { + my($makeDir, @tempDirsToMake); + foreach $makeDir (@makeDirs) { + if($makeDir =~ /^\//) { + push(@tempDirsToMake, $tempRoot.$makeDir); + } + else { + push(@tempDirsToMake, $tempRoot.'/'.$makeDir); + } + } + if(command($gConfig{'cmd_mkdir'}, '-p', @tempDirsToMake) != 0) { + cleanupDie('mkdir failed'); + } +} + +# copy files and/or create symlinks +copyFiles($tempRoot, 'copy', @copyFiles); +copyFiles($tempRoot, 'symlink', @createSymlinks); + +if($gConfig{'create_directly'}) { + # If create_directly is false, the contents will be rsynced into a + # disk image and they would lose their attributes. + setAttributes($tempRoot, @attributes); +} + +if(defined($iconFile)) { + if(command($gConfig{'cmd_rsync'}, '-aC', '--include', '*.so', + '--copy-unsafe-links', $iconFile, $tempRoot.'/.VolumeIcon.icns') != 0) { + cleanupDie('rsync failed for volume icon'); + } + + # It's pointless to set the attributes of the root when diskutil create + # -srcfolder is being used. In that case, the attributes will be set + # later, after the image is already created. + if(isFormatReadOnly($outputFormat) && + (command($gConfig{'cmd_SetFile'}, '-a', 'C', $tempRoot) != 0)) { + cleanupDie('SetFile failed'); + } +} + +if(command($gConfig{'cmd_chmod'}, '-R', 'a+rX,a-st,u+w,go-w', + $tempRoot) != 0) { + cleanupDie('chmod failed'); +} + +my($unflattenable); +if(isFormatReadOnly($outputFormat)) { + $unflattenable = 1; +} +else { + $unflattenable = 0; +} + +diskImageMaker($tempRoot, $targetImage, $outputFormat, $volumeName, + $tempSubdir, $tempMount, $targetImageFilename, defined($iconFile)); + +if(defined($licenseFile) && $licenseFile ne '') { + my($licenseResource); + $licenseResource = $tempSubdir.'/license.r'; + if(!licenseMaker($licenseFile, $licenseResource)) { + cleanupDie('licenseMaker failed'); + } + push(@resourceFiles, $licenseResource); + # Don't add a cleanup object because licenseResource is in tempSubdir. +} + +if(@resourceFiles) { + # Add resources, such as a license agreement. + + # Only unflatten read-only and compressed images. It's not supported + # on other image times. + if($unflattenable && + (command($gConfig{'cmd_hdiutil'}, 'unflatten', $targetImage)) != 0) { + cleanupDie('hdiutil unflatten failed'); + } + # Don't push flatten onto the cleanup stack. If we fail now, we'll be + # removing $targetImage anyway. + + # Type definitions come from Carbon.r. + if(command($gConfig{'cmd_Rez'}, 'Carbon.r', @resourceFiles, '-a', '-o', + $targetImage) != 0) { + cleanupDie('Rez failed'); + } + + # Flatten. This merges the resource fork into the data fork, so no + # special encoding is needed to transfer the file. + if($unflattenable && + (command($gConfig{'cmd_hdiutil'}, 'flatten', $targetImage)) != 0) { + cleanupDie('hdiutil flatten failed'); + } +} + +# $tempSubdir is no longer needed. It's buried on the stack below the +# rm of the fresh image file. Splice in this fashion is equivalent to +# pop-save, pop, push-save. +splice(@gCleanup, -2, 1); +# No need to remove licenseResource separately, it's in tempSubdir. +if(command($gConfig{'cmd_rm'}, '-rf', $tempSubdir) != 0) { + cleanupDie('rm -rf tempSubdir failed'); +} + +if($idme) { + if(command($gConfig{'cmd_hdiutil'}, 'internet-enable', '-yes', + $targetImage) != 0) { + cleanupDie('hdiutil internet-enable failed'); + } +} + +# Done. + +exit(0); + +# argumentEscape(@arguments) +# +# Takes a list of @arguments and makes them shell-safe. +sub argumentEscape(@) { + my(@arguments); + @arguments = @_; + my($argument, @argumentsOut); + foreach $argument (@arguments) { + $argument =~ s%([^A-Za-z0-9_\-/.=+,])%\\$1%g; + push(@argumentsOut, $argument); + } + return @argumentsOut; +} + +# cleanupDie($message) +# +# Displays $message as an error message, and then runs through the +# @gCleanup stack, performing any cleanup operations needed before +# exiting. Does not return, exits with exit status 1. +sub cleanupDie($) { + my($message); + ($message) = @_; + print STDERR ($0.': '.$message.(@gCleanup?' (cleaning up)':'')."\n"); + while(@gCleanup) { + my($subroutine); + $subroutine = pop(@gCleanup); + &$subroutine; + } + exit(1); +} + +# command(@arguments) +# +# Runs the specified command at the verbosity level defined by $gVerbosity. +# Returns nonzero on failure, returning the exit status if appropriate. +# Discards command output. +sub command(@) { + my(@arguments); + @arguments = @_; + return commandVerbosity($gVerbosity,@arguments); +} + +# commandInternal($command, @arguments) +# +# Runs the specified internal command at the verbosity level defined by +# $gVerbosity. +# Returns zero(!) on failure, because commandInternal is supposed to be a +# direct replacement for the Perl system call wrappers, which, unlike shell +# commands and C equivalent system calls, return true (instead of 0) to +# indicate success. +sub commandInternal($@) { + my(@arguments, $command); + ($command, @arguments) = @_; + return commandInternalVerbosity($gVerbosity, $command, @arguments); +} + +# commandInternalVerbosity($verbosity, $command, @arguments) +# +# Run an internal command, printing a bogus command invocation message if +# $verbosity is true. +# +# If $command is unlink: +# Removes the files specified by @arguments. Wraps unlink. +# +# If $command is symlink: +# Creates the symlink specified by @arguments. Wraps symlink. +sub commandInternalVerbosity($$@) { + my(@arguments, $command, $verbosity); + ($verbosity, $command, @arguments) = @_; + if($command eq 'unlink') { + if($verbosity || $gDryRun) { + print(join(' ', 'rm', '-f', argumentEscape(@arguments))."\n"); + } + if($gDryRun) { + return $#arguments+1; + } + return unlink(@arguments); + } + elsif($command eq 'symlink') { + if($verbosity || $gDryRun) { + print(join(' ', 'ln', '-s', argumentEscape(@arguments))."\n"); + } + if($gDryRun) { + return 1; + } + my($source, $target); + ($source, $target) = @arguments; + return symlink($source, $target); + } +} + +# commandOutput(@arguments) +# +# Runs the specified command at the verbosity level defined by $gVerbosity. +# Output is returned in an array of lines. undef is returned on failure. +# The exit status is available in $?. +sub commandOutput(@) { + my(@arguments); + @arguments = @_; + return commandOutputVerbosity($gVerbosity, @arguments); +} + +# commandOutputVerbosity($verbosity, @arguments) +# +# Runs the specified command at the verbosity level defined by the +# $verbosity argument. Output is returned in an array of lines. undef is +# returned on failure. The exit status is available in $?. +# +# If an error occurs in fork or exec, an error message is printed to +# stderr and undef is returned. +# +# If $verbosity is 0, the command invocation is not printed, and its +# stdout is not echoed back to stdout. +# +# If $verbosity is 1, the command invocation is printed. +# +# If $verbosity is 2, the command invocation is printed and the output +# from stdout is echoed back to stdout. +# +# Regardless of $verbosity, stderr is left connected. +sub commandOutputVerbosity($@) { + my(@arguments, $verbosity); + ($verbosity, @arguments) = @_; + my($pid); + if($verbosity || $gDryRun) { + print(join(' ', argumentEscape(@arguments))."\n"); + } + if($gDryRun) { + return(1); + } + if (!defined($pid = open(*COMMAND, '-|'))) { + printf STDERR ($0.': fork: '.$!."\n"); + return undef; + } + elsif ($pid) { + # parent + my(@lines); + while(!eof(*COMMAND)) { + my($line); + chop($line = <COMMAND>); + if($verbosity > 1) { + print($line."\n"); + } + push(@lines, $line); + } + close(*COMMAND); + if ($? == -1) { + printf STDERR ($0.': fork: '.$!."\n"); + return undef; + } + elsif ($? & 127) { + printf STDERR ($0.': exited on signal '.($? & 127). + ($? & 128 ? ', core dumped' : '')."\n"); + return undef; + } + return @lines; + } + else { + # child; this form of exec is immune to shell games + if(!exec {$arguments[0]} (@arguments)) { + printf STDERR ($0.': exec: '.$!."\n"); + exit(-1); + } + } +} + +# commandVerbosity($verbosity, @arguments) +# +# Runs the specified command at the verbosity level defined by the +# $verbosity argument. Returns nonzero on failure, returning the exit +# status if appropriate. Discards command output. +sub commandVerbosity($@) { + my(@arguments, $verbosity); + ($verbosity, @arguments) = @_; + if(!defined(commandOutputVerbosity($verbosity, @arguments))) { + return -1; + } + return $?; +} + +# copyFiles($tempRoot, $method, @arguments) +# +# Copies files or create symlinks in the disk image. +# See --copy and --symlink descriptions for details. +# If $method is 'copy', @arguments are interpreted as source:target, if $method +# is 'symlink', @arguments are interpreted as symlink:target. +sub copyFiles($@) { + my(@fileList, $method, $tempRoot); + ($tempRoot, $method, @fileList) = @_; + my($file, $isSymlink); + $isSymlink = ($method eq 'symlink'); + foreach $file (@fileList) { + my($source, $target); + ($source, $target) = split(/:/, $file); + if(!defined($target) and $isSymlink) { + # empty symlink targets would result in an invalid target and fail, + # but they shall be interpreted as "like source path, but inside dmg" + $target = $source; + } + if(!defined($target)) { + $target = $tempRoot; + } + elsif($target =~ /^\//) { + $target = $tempRoot.$target; + } + else { + $target = $tempRoot.'/'.$target; + } + + my($success); + if($isSymlink) { + $success = commandInternal('symlink', $source, $target); + } + else { + $success = !command($gConfig{'cmd_rsync'}, '-aC', '--include', '*.so', + '--copy-unsafe-links', $source, $target); + } + if(!$success) { + cleanupDie('copyFiles failed for method '.$method); + } + } +} + +# diskImageMaker($source, $destination, $format, $name, $tempDir, $tempMount, +# $baseName, $setRootIcon) +# +# Creates a disk image in $destination of format $format corresponding to the +# source directory $source. $name is the volume name. $tempDir is a good +# place to write temporary files, which should be empty (aside from the other +# things that this script might create there, like stage and mount). +# $tempMount is a mount point for temporary disk images. $baseName is the +# name of the disk image, and is presently unused. $setRootIcon is true if +# a volume icon was added to the staged $source and indicates that the +# custom volume icon bit on the volume root needs to be set. +sub diskImageMaker($$$$$$$$) { + my($baseName, $destination, $format, $name, $setRootIcon, $source, + $tempDir, $tempMount); + ($source, $destination, $format, $name, $tempDir, $tempMount, + $baseName, $setRootIcon) = @_; + if(isFormatReadOnly($format)) { + my($uncompressedImage); + + if($gConfig{'makehybrid'}) { + my($hybridImage); + $hybridImage = giveExtension($tempDir.'/hybrid', '.dmg'); + + if(command($gConfig{'cmd_hdiutil'}, 'makehybrid', '-hfs', + '-hfs-volume-name', $name, + ($gConfig{'openfolder_bless'} ? ('-hfs-openfolder', $source) : ()), + '-ov', $source, '-o', $hybridImage) != 0) { + cleanupDie('hdiutil makehybrid failed'); + } + + $uncompressedImage = $hybridImage; + + # $source is no longer needed and will be removed before anything + # else can fail. splice in this form is the same as pop/push. + splice(@gCleanup, -1, 1, + sub {commandInternalVerbosity(0, 'unlink', $hybridImage);}); + + if(command($gConfig{'cmd_rm'}, '-rf', $source) != 0) { + cleanupDie('rm -rf failed'); + } + + if(!$gConfig{'partition_table'} && $gConfig{'recursive_access'}) { + # Even if we do want to create disk images without partition tables, + # it's impossible unless recursive_access is set. + my($rootDevice, $partitionDevice, $partitionMountPoint); + + if(!(($rootDevice, $partitionDevice, $partitionMountPoint) = + hdidMountImage($tempMount, '-readonly', $hybridImage))) { + cleanupDie('hdid mount failed'); + } + + push(@gCleanup, sub {commandVerbosity(0, + $gConfig{'cmd_diskutil'}, 'eject', $rootDevice);}); + + my($udrwImage); + $udrwImage = giveExtension($tempDir.'/udrw', '.dmg'); + + if(command($gConfig{'cmd_hdiutil'}, 'create', '-format', 'UDRW', + '-ov', '-srcdevice', $partitionDevice, $udrwImage) != 0) { + cleanupDie('hdiutil create failed'); + } + + $uncompressedImage = $udrwImage; + + # Going to eject before anything else can fail. Get the eject off + # the stack. + pop(@gCleanup); + + # $hybridImage will be removed soon, but until then, it needs to + # stay on the cleanup stack. It needs to wait until after + # ejection. $udrwImage is staying around. Make it appear as + # though it's been done before $hybridImage. + # + # splice in this form is the same as popping one element to + # @tempCleanup and pushing the subroutine. + my(@tempCleanup); + @tempCleanup = splice(@gCleanup, -1, 1, + sub {commandInternalVerbosity(0, 'unlink', $udrwImage);}); + push(@gCleanup, @tempCleanup); + + if(command($gConfig{'cmd_diskutil'}, 'eject', $rootDevice) != 0) { + cleanupDie('diskutil eject failed'); + } + + # Pop unlink of $uncompressedImage + pop(@gCleanup); + + if(commandInternal('unlink', $hybridImage) != 1) { + cleanupDie('unlink hybridImage failed: '.$!); + } + } + } + else { + # makehybrid is not available, fall back to making a UDRW and + # converting to a compressed image. It ought to be possible to + # create a compressed image directly, but those come out far too + # large (journaling?) and need to be read-write to fix up the + # volume icon anyway. Luckily, we can take advantage of a single + # call back into this function. + my($udrwImage); + $udrwImage = giveExtension($tempDir.'/udrw', '.dmg'); + + diskImageMaker($source, $udrwImage, 'UDRW', $name, $tempDir, + $tempMount, $baseName, $setRootIcon); + + # The call back into diskImageMaker already removed $source. + + $uncompressedImage = $udrwImage; + } + + # The uncompressed disk image is now in its final form. Compress it. + # Jaguar doesn't support hdiutil convert -ov, but it always allows + # overwriting. + # bzip2-compressed UDBZ images can only be created and mounted on 10.4 + # and later. The bzip2-level imagekey is only effective when creating + # images in 10.5. In 10.4, bzip2-level is harmlessly ignored, and the + # default value of 1 is always used. + if(command($gConfig{'cmd_hdiutil'}, 'convert', '-format', $format, + ($format eq 'UDZO' ? ('-imagekey', 'zlib-level=9') : ()), + ($format eq 'UDBZ' ? ('-imagekey', 'bzip2-level=9') : ()), + (defined($gDarwinMajor) && $gDarwinMajor <= 6 ? () : ('-ov')), + $uncompressedImage, '-o', $destination) != 0) { + cleanupDie('hdiutil convert failed'); + } + + # $uncompressedImage is going to be unlinked before anything else can + # fail. splice in this form is the same as pop/push. + splice(@gCleanup, -1, 1, + sub {commandInternalVerbosity(0, 'unlink', $destination);}); + + if(commandInternal('unlink', $uncompressedImage) != 1) { + cleanupDie('unlink uncompressedImage failed: '.$!); + } + + # At this point, the only thing that the compressed block has added to + # the cleanup stack is the removal of $destination. $source has already + # been removed, and its cleanup entry has been removed as well. + } + elsif($format eq 'UDRW' || $format eq 'UDSP') { + my(@extraArguments); + if(!$gConfig{'partition_table'}) { + @extraArguments = ('-layout', 'NONE'); + } + + if($gConfig{'create_directly'}) { + # Use -fs HFS+ to suppress the journal. + if(command($gConfig{'cmd_hdiutil'}, 'create', '-format', $format, + @extraArguments, '-fs', 'HFS+', '-volname', $name, + '-ov', '-srcfolder', $source, $destination) != 0) { + cleanupDie('hdiutil create failed'); + } + + # $source is no longer needed and will be removed before anything + # else can fail. splice in this form is the same as pop/push. + splice(@gCleanup, -1, 1, + sub {commandInternalVerbosity(0, 'unlink', $destination);}); + + if(command($gConfig{'cmd_rm'}, '-rf', $source) != 0) { + cleanupDie('rm -rf failed'); + } + } + else { + # hdiutil create does not support -srcfolder or -srcdevice, it only + # knows how to create blank images. Figure out how large an image + # is needed, create it, and fill it. This is needed for Jaguar. + + # Use native block size for hdiutil create -sectors. + delete $ENV{'BLOCKSIZE'}; + + my(@duOutput, $ignore, $sizeBlocks, $sizeOverhead, $sizeTotal, $type); + if(!(@output = commandOutput($gConfig{'cmd_du'}, '-s', $tempRoot)) || + $? != 0) { + cleanupDie('du failed'); + } + ($sizeBlocks, $ignore) = split(' ', $output[0], 2); + + # The filesystem itself takes up 152 blocks of its own blocks for the + # filesystem up to 8192 blocks, plus 64 blocks for every additional + # 4096 blocks or portion thereof. + $sizeOverhead = 152 + 64 * POSIX::ceil( + (($sizeBlocks - 8192) > 0) ? (($sizeBlocks - 8192) / (4096 - 64)) : 0); + + # The number of blocks must be divisible by 8. + my($mod); + if($mod = ($sizeOverhead % 8)) { + $sizeOverhead += 8 - $mod; + } + + # sectors is taken as the size of a disk, not a filesystem, so the + # partition table eats into it. + if($gConfig{'partition_table'}) { + $sizeOverhead += 80; + } + + # That was hard. Leave some breathing room anyway. Use 1024 sectors + # (512kB). These read-write images wouldn't be useful if they didn't + # have at least a little free space. + $sizeTotal = $sizeBlocks + $sizeOverhead + 1024; + + # Minimum sizes - these numbers are larger on Jaguar than on later + # systems. Just use the Jaguar numbers, since it's unlikely to wind + # up here on any other release. + if($gConfig{'partition_table'} && $sizeTotal < 8272) { + $sizeTotal = 8272; + } + if(!$gConfig{'partition_table'} && $sizeTotal < 8192) { + $sizeTotal = 8192; + } + + # hdiutil create without -srcfolder or -srcdevice will not accept + # -format. It uses -type. Fortunately, the two supported formats + # here map directly to the only two supported types. + if ($format eq 'UDSP') { + $type = 'SPARSE'; + } + else { + $type = 'UDIF'; + } + + if(command($gConfig{'cmd_hdiutil'}, 'create', '-type', $type, + @extraArguments, '-fs', 'HFS+', '-volname', $name, + '-ov', '-sectors', $sizeTotal, $destination) != 0) { + cleanupDie('hdiutil create failed'); + } + + push(@gCleanup, + sub {commandInternalVerbosity(0, 'unlink', $destination);}); + + # The rsync will occur shortly. + } + + my($mounted, $rootDevice, $partitionDevice, $partitionMountPoint); + + $mounted=0; + if(!$gConfig{'create_directly'} || $gConfig{'openfolder_bless'} || + $setRootIcon) { + # The disk image only needs to be mounted if: + # create_directly is false, because the content needs to be copied + # openfolder_bless is true, because bless -openfolder needs to run + # setRootIcon is true, because the root needs its attributes set. + if(!(($rootDevice, $partitionDevice, $partitionMountPoint) = + hdidMountImage($tempMount, $destination))) { + cleanupDie('hdid mount failed'); + } + + $mounted=1; + + push(@gCleanup, sub {commandVerbosity(0, + $gConfig{'cmd_diskutil'}, 'eject', $rootDevice);}); + } + + if(!$gConfig{'create_directly'}) { + # Couldn't create and copy directly in one fell swoop. Now that + # the volume is mounted, copy the files. --copy-unsafe-links is + # unnecessary since it was used to copy everything to the staging + # area. There can be no more unsafe links. + if(command($gConfig{'cmd_rsync'}, '-aC', '--include', '*.so', + $source.'/',$partitionMountPoint) != 0) { + cleanupDie('rsync to new volume failed'); + } + + # We need to get the rm -rf of $source off the stack, because it's + # being cleaned up here. There are two items now on top of it: + # removing the target image and, above that, ejecting it. Splice it + # out. + my(@tempCleanup); + @tempCleanup = splice(@gCleanup, -2); + # The next splice is the same as popping once and pushing @tempCleanup. + splice(@gCleanup, -1, 1, @tempCleanup); + + if(command($gConfig{'cmd_rm'}, '-rf', $source) != 0) { + cleanupDie('rm -rf failed'); + } + } + + if($gConfig{'openfolder_bless'}) { + # On Tiger, the bless docs say to use --openfolder, but only + # --openfolder is accepted on Panther. Tiger takes it with a single + # dash too. Jaguar is out of luck. + if(command($gConfig{'cmd_bless'}, '-openfolder', + $partitionMountPoint) != 0) { + cleanupDie('bless failed'); + } + } + + setAttributes($partitionMountPoint, @attributes); + + if($setRootIcon) { + # When "hdiutil create -srcfolder" is used, the root folder's + # attributes are not copied to the new volume. Fix up. + + if(command($gConfig{'cmd_SetFile'}, '-a', 'C', + $partitionMountPoint) != 0) { + cleanupDie('SetFile failed'); + } + } + + if($mounted) { + # Pop diskutil eject + pop(@gCleanup); + + if(command($gConfig{'cmd_diskutil'}, 'eject', $rootDevice) != 0) { + cleanupDie('diskutil eject failed'); + } + } + + # End of UDRW/UDSP section. At this point, $source has been removed + # and its cleanup entry has been removed from the stack. + } + else { + cleanupDie('unrecognized format'); + print STDERR ($0.": unrecognized format\n"); + exit(1); + } +} + +# giveExtension($file, $extension) +# +# If $file does not end in $extension, $extension is added. The new +# filename is returned. +sub giveExtension($$) { + my($extension, $file); + ($file, $extension) = @_; + if(substr($file, -length($extension)) ne $extension) { + return $file.$extension; + } + return $file; +} + +# hdidMountImage($mountPoint, @arguments) +# +# Runs the hdid command with arguments specified by @arguments. +# @arguments may be a single-element array containing the name of the +# disk image to mount. Returns a three-element array, with elements +# corresponding to: +# - The root device of the mounted image, suitable for ejection +# - The device corresponding to the mounted partition +# - The mounted partition's mount point +# +# If running on a system that supports easy mounting at points outside +# of the default /Volumes with hdiutil attach, it is used instead of hdid, +# and $mountPoint is used as the mount point. +# +# The root device will differ from the partition device when the disk +# image contains a partition table, otherwise, they will be identical. +# +# If hdid fails, undef is returned. +sub hdidMountImage($@) { + my(@arguments, @command, $mountPoint); + ($mountPoint, @arguments) = @_; + my(@output); + + if($gConfig{'hdiutil_mountpoint'}) { + @command=($gConfig{'cmd_hdiutil'}, 'attach', @arguments, + '-mountpoint', $mountPoint); + } + else { + @command=($gConfig{'cmd_hdid'}, @arguments); + } + + if(!(@output = commandOutput(@command)) || + $? != 0) { + return undef; + } + + if($gDryRun) { + return('/dev/diskX','/dev/diskXsY','/Volumes/'.$volumeName); + } + + my($line, $restOfLine, $rootDevice); + + foreach $line (@output) { + my($device, $mountpoint); + if($line !~ /^\/dev\//) { + # Consider only lines that correspond to /dev entries + next; + } + ($device, $restOfLine) = split(' ', $line, 2); + + if(!defined($rootDevice) || $rootDevice eq '') { + # If this is the first device seen, it's the root device to be + # used for ejection. Keep it. + $rootDevice = $device; + } + + if($restOfLine =~ /(\/.*)/) { + # The first partition with a mount point is the interesting one. It's + # usually Apple_HFS and usually the last one in the list, but beware of + # the possibility of other filesystem types and the Apple_Free partition. + # If the disk image contains no partition table, the partition will not + # have a type, so look for the mount point by looking for a slash. + $mountpoint = $1; + return($rootDevice, $device, $mountpoint); + } + } + + # No mount point? This is bad. If there's a root device, eject it. + if(defined($rootDevice) && $rootDevice ne '') { + # Failing anyway, so don't care about failure + commandVerbosity(0, $gConfig{'cmd_diskutil'}, 'eject', $rootDevice); + } + + return undef; +} + +# isFormatReadOnly($format) +# +# Returns true if $format corresponds to a read-only disk image format. +# Returns false otherwise. +sub isFormatReadOnly($) { + my($format); + ($format) = @_; + return $format eq 'UDZO' || $format eq 'UDBZ' || $format eq 'UDRO'; +} + +# licenseMaker($text, $resource) +# +# Takes a plain text file at path $text and creates a license agreement +# resource containing the text at path $license. English-only, and +# no special formatting. This is the bare-bones stuff. For more +# intricate license agreements, create your own resource. +# +# ftp://ftp.apple.com/developer/Development_Kits/SLAs_for_UDIFs_1.0.dmg +sub licenseMaker($$) { + my($resource, $text); + ($text, $resource) = @_; + if(!sysopen(*TEXT, $text, O_RDONLY)) { + print STDERR ($0.': licenseMaker: sysopen text: '.$!."\n"); + return 0; + } + if(!sysopen(*RESOURCE, $resource, O_WRONLY|O_CREAT|O_EXCL)) { + print STDERR ($0.': licenseMaker: sysopen resource: '.$!."\n"); + return 0; + } + print RESOURCE << '__EOT__'; +// See /System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers/Script.h for language IDs. +data 'LPic' (5000) { + // Default language ID, 0 = English + $"0000" + // Number of entries in list + $"0001" + + // Entry 1 + // Language ID, 0 = English + $"0000" + // Resource ID, 0 = STR#/TEXT/styl 5000 + $"0000" + // Multibyte language, 0 = no + $"0000" +}; + +resource 'STR#' (5000, "English") { + { + // Language (unused?) = English + "English", + // Agree + "Agree", + // Disagree + "Disagree", +__EOT__ + # This stuff needs double-quotes for interpolations to work. + print RESOURCE (" // Print, ellipsis is 0xC9\n"); + print RESOURCE (" \"Print\xc9\",\n"); + print RESOURCE (" // Save As, ellipsis is 0xC9\n"); + print RESOURCE (" \"Save As\xc9\",\n"); + print RESOURCE (' // Descriptive text, curly quotes are 0xD2 and 0xD3'. + "\n"); + print RESOURCE (' "If you agree to the terms of this license '. + "agreement, click \xd2Agree\xd3 to access the software. If you ". + "do not agree, press \xd2Disagree.\xd3\"\n"); +print RESOURCE << '__EOT__'; + }; +}; + +// Beware of 1024(?) byte (character?) line length limitation. Split up long +// lines. +// If straight quotes are used ("), remember to escape them (\"). +// Newline is \n, to leave a blank line, use two of them. +// 0xD2 and 0xD3 are curly double-quotes ("), 0xD4 and 0xD5 are curly +// single quotes ('), 0xD5 is also the apostrophe. +data 'TEXT' (5000, "English") { +__EOT__ + + while(!eof(*TEXT)) { + my($line); + chop($line = <TEXT>); + + while(defined($line)) { + my($chunk); + + # Rez doesn't care for lines longer than (1024?) characters. Split + # at less than half of that limit, in case everything needs to be + # backwhacked. + if(length($line)>500) { + $chunk = substr($line, 0, 500); + $line = substr($line, 500); + } + else { + $chunk = $line; + $line = undef; + } + + if(length($chunk) > 0) { + # Unsafe characters are the double-quote (") and backslash (\), escape + # them with backslashes. + $chunk =~ s/(["\\])/\\$1/g; + + print RESOURCE ' "'.$chunk.'"'."\n"; + } + } + print RESOURCE ' "\n"'."\n"; + } + close(*TEXT); + + print RESOURCE << '__EOT__'; +}; + +data 'styl' (5000, "English") { + // Number of styles following = 1 + $"0001" + + // Style 1. This is used to display the first two lines in bold text. + // Start character = 0 + $"0000 0000" + // Height = 16 + $"0010" + // Ascent = 12 + $"000C" + // Font family = 1024 (Lucida Grande) + $"0400" + // Style bitfield, 0x1=bold 0x2=italic 0x4=underline 0x8=outline + // 0x10=shadow 0x20=condensed 0x40=extended + $"00" + // Style, unused? + $"02" + // Size = 12 point + $"000C" + // Color, RGB + $"0000 0000 0000" +}; +__EOT__ + close(*RESOURCE); + + return 1; +} + +# pathSplit($pathname) +# +# Splits $pathname into an array of path components. +sub pathSplit($) { + my($pathname); + ($pathname) = @_; + return split(/\//, $pathname); +} + +# setAttributes($root, @attributeList) +# +# @attributeList is an array, each element of which must be in the form +# <a>:<file>. <a> is a list of attributes, per SetFile. <file> is a file +# which is taken as relative to $root (even if it appears as an absolute +# path.) SetFile is called to set the attributes on each file in +# @attributeList. +sub setAttributes($@) { + my(@attributes, $root); + ($root, @attributes) = @_; + my($attribute); + foreach $attribute (@attributes) { + my($attrList, $file, @fileList, @fixedFileList); + ($attrList, @fileList) = split(/:/, $attribute); + if(!defined($attrList) || !@fileList) { + cleanupDie('--attribute requires <attributes>:<file>'); + } + @fixedFileList=(); + foreach $file (@fileList) { + if($file =~ /^\//) { + push(@fixedFileList, $root.$file); + } + else { + push(@fixedFileList, $root.'/'.$file); + } + } + if(command($gConfig{'cmd_SetFile'}, '-a', $attrList, @fixedFileList)) { + cleanupDie('SetFile failed to set attributes'); + } + } + return; +} + +sub trapSignal($) { + my($signalName); + ($signalName) = @_; + cleanupDie('exiting on SIG'.$signalName); +} + +sub usage() { + print STDERR ( +"usage: pkg-dmg --source <source-folder>\n". +" --target <target-image>\n". +" [--format <format>] (default: UDZO)\n". +" [--volname <volume-name>] (default: same name as source)\n". +" [--tempdir <temp-dir>] (default: same dir as target)\n". +" [--mkdir <directory>] (make directory in image)\n". +" [--copy <source>[:<dest>]] (extra files to add)\n". +" [--symlink <source>[:<dest>]] (extra symlinks to add)\n". +" [--license <file>] (plain text license agreement)\n". +" [--resource <file>] (flat .r files to merge)\n". +" [--icon <icns-file>] (volume icon)\n". +" [--attribute <a>:<file>] (set file attributes)\n". +" [--idme] (make Internet-enabled image)\n". +" [--sourcefile] (treat --source as a file)\n". +" [--verbosity <level>] (0, 1, 2; default=2)\n". +" [--dry-run] (print what would be done)\n"); + return; +} diff --git a/png/macinstaller_background.png b/png/macinstaller_background.png new file mode 100644 index 0000000..cf3435c Binary files /dev/null and b/png/macinstaller_background.png differ diff --git a/svg/macinstaller_background.svg b/svg/macinstaller_background.svg new file mode 100644 index 0000000..989ce3e --- /dev/null +++ b/svg/macinstaller_background.svg @@ -0,0 +1,630 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="700" + height="498.16937" + id="svg2" + version="1.1" + inkscape:version="0.48.1 r9760" + sodipodi:docname="macinstaller_background.svg" + inkscape:export-filename="/Users/clemens/Development/x2goclient-4.0.0.1/png/macinstaller_background.png" + inkscape:export-xdpi="89.790001" + inkscape:export-ydpi="89.790001"> + <defs + id="defs4"> + <marker + inkscape:stockid="Arrow2Lend" + orient="auto" + refY="0" + refX="0" + id="Arrow2Lend" + style="overflow:visible"> + <path + id="path5378" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="matrix(-1.1,0,0,-1.1,-1.1,0)" + inkscape:connector-curvature="0" /> + </marker> + <marker + inkscape:stockid="Arrow1Lend" + orient="auto" + refY="0" + refX="0" + id="Arrow1Lend" + style="overflow:visible"> + <path + id="path5360" + d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" + transform="matrix(-0.8,0,0,-0.8,-10,0)" + inkscape:connector-curvature="0" /> + </marker> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="120.54888" + x2="133.85397" + y1="-49.590809" + x1="278.59366" + id="linearGradient2808" + xlink:href="#linearGradient2802" + inkscape:collect="always" /> + <metadata + id="CorelCorpID_0Corel-Layer" /> + <linearGradient + y2="135.464" + x2="207.00999" + y1="135.464" + x1="202.494" + gradientUnits="userSpaceOnUse" + id="id0"> + <stop + id="stop9" + style="stop-color:black" + offset="0" /> + <stop + id="stop11" + style="stop-color:#6E707F" + offset="1" /> + </linearGradient> + <style + id="style6" + type="text/css"> + + .fil1 {fill:#6699FF} + .fil0 {fill:white} + .fil2 {fill:#6E707F} + .fil4 {fill:white} + .fil3 {fill:url(#id0)} + + </style> + <linearGradient + id="linearGradient2844"> + <stop + id="stop2846" + offset="0" + style="stop-color:#deeaed;stop-opacity:1;" /> + <stop + id="stop2848" + offset="1" + style="stop-color:white;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient2852"> + <stop + id="stop2854" + offset="0" + style="stop-color:white;stop-opacity:1;" /> + <stop + id="stop2856" + offset="1" + style="stop-color:#69f;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2802" + inkscape:collect="always"> + <stop + id="stop2804" + offset="0" + style="stop-color:white;stop-opacity:1;" /> + <stop + id="stop2806" + offset="1" + style="stop-color:white;stop-opacity:0;" /> + </linearGradient> + <inkscape:perspective + id="perspective28" + inkscape:persp3d-origin="180.52499 : 90.333333 : 1" + inkscape:vp_z="361.04999 : 135.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 135.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <linearGradient + id="linearGradient2855"> + <stop + id="stop2857" + offset="0" + style="stop-color:#ffffff;stop-opacity:1;" /> + <stop + id="stop2859" + offset="1" + style="stop-color:#246ed8;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient2863"> + <stop + id="stop2865" + offset="0" + style="stop-color:#ffffff;stop-opacity:1;" /> + <stop + id="stop2867" + offset="1" + style="stop-color:#246ed8;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient2877"> + <stop + id="stop2879" + offset="0" + style="stop-color:#ffffff;stop-opacity:1;" /> + <stop + id="stop2881" + offset="1" + style="stop-color:#246ed8;stop-opacity:1;" /> + </linearGradient> + <pattern + inkscape:collect="always" + xlink:href="#Wavywhite" + id="pattern4837" + patternTransform="matrix(1.0895522,0,0,1.0923077,-3.8512144,-24.413743)" /> + <pattern + inkscape:stockid="Wavy white" + id="Wavywhite" + height="5.1805778" + width="30.066020" + patternUnits="userSpaceOnUse" + inkscape:collect="always"> + <path + id="path4539" + d="M 7.597,0.061 C 5.079,-0.187 2.656,0.302 -0.01,1.788 L -0.01,3.061 C 2.773,1.431 5.173,1.052 7.472,1.280 C 9.770,1.508 11.969,2.361 14.253,3.218 C 18.820,4.931 23.804,6.676 30.066,3.061 L 30.062,1.788 C 23.622,5.497 19.246,3.770 14.691,2.061 C 12.413,1.207 10.115,0.311 7.597,0.061 z " + style="fill:white;stroke:none;" /> + </pattern> + <linearGradient + id="linearGradient3333"> + <stop + style="stop-color:#ffffff;stop-opacity:0.41880342;" + offset="0" + id="stop3335" /> + <stop + style="stop-color:#ffffff;stop-opacity:0.60683763;" + offset="1" + id="stop3337" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient3235"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop3237" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop3239" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + id="linearGradient3177"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop3179" /> + <stop + style="stop-color:#ffffff;stop-opacity:0;" + offset="1" + id="stop3181" /> + </linearGradient> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 135.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="361.04999 : 135.5 : 1" + inkscape:persp3d-origin="180.52499 : 90.333333 : 1" + id="perspective2592" /> + <linearGradient + id="linearGradient2600"> + <stop + style="stop-color:white;stop-opacity:1;" + offset="0" + id="stop2602" /> + <stop + style="stop-color:#69f;stop-opacity:0;" + offset="1" + id="stop2604" /> + </linearGradient> + <linearGradient + id="linearGradient2606"> + <stop + style="stop-color:#deeaed;stop-opacity:1;" + offset="0" + id="stop2608" /> + <stop + style="stop-color:white;stop-opacity:1;" + offset="1" + id="stop2610" /> + </linearGradient> + <style + type="text/css" + id="style2618"> + + .fil1 {fill:#6699FF} + .fil0 {fill:white} + .fil2 {fill:#6E707F} + .fil4 {fill:white} + .fil3 {fill:url(#id0)} + + </style> + <linearGradient + id="linearGradient2620" + gradientUnits="userSpaceOnUse" + x1="202.494" + y1="135.464" + x2="207.00999" + y2="135.464"> + <stop + offset="0" + style="stop-color:black" + id="stop2622" /> + <stop + offset="1" + style="stop-color:#6E707F" + id="stop2624" /> + </linearGradient> + <metadata + id="metadata2626" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient1948-5" + id="linearGradient2628" + x1="107.24445" + y1="268.11078" + x2="107.64762" + y2="207.717" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient2802-8" + id="linearGradient2630" + x1="278.59366" + y1="-49.590809" + x2="133.85397" + y2="120.54888" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0000171,0,0,1.0000148,0,-0.00400005)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3177" + id="linearGradient3183" + x1="0" + y1="135.96677" + x2="65.034927" + y2="135.96677" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.0470449,0,-6.8968197)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3235" + id="linearGradient3241" + x1="50.316132" + y1="121.91985" + x2="96.761787" + y2="121.91985" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(2.9166667,0,0,1,-146.75538,31.608847)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3333" + id="linearGradient3339" + x1="18.062202" + y1="-45.155499" + x2="162.5598" + y2="144.4976" + gradientUnits="userSpaceOnUse" /> + <inkscape:perspective + id="perspective2513" + inkscape:persp3d-origin="46.062992 : 30.708661 : 1" + inkscape:vp_z="92.125984 : 46.062992 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 46.062992 : 1" + sodipodi:type="inkscape:persp3d" /> + <metadata + id="CorelCorpID_0Corel-Layer-7" /> + <linearGradient + y2="135.464" + x2="207.00999" + y1="135.464" + x1="202.494" + gradientUnits="userSpaceOnUse" + id="id0-8"> + <stop + id="stop9-2" + style="stop-color:black" + offset="0" /> + <stop + id="stop11-0" + style="stop-color:#6E707F" + offset="1" /> + </linearGradient> + <style + id="style6-9" + type="text/css"> + + .fil1 {fill:#6699FF} + .fil0 {fill:white} + .fil2 {fill:#6E707F} + .fil4 {fill:white} + .fil3 {fill:url(#id0)} + + </style> + <linearGradient + id="linearGradient1948-5" + inkscape:collect="always"> + <stop + id="stop1950-8" + offset="0" + style="stop-color:#69f;stop-opacity:1;" /> + <stop + id="stop1952-2" + offset="1" + style="stop-color:#69f;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2844-1"> + <stop + id="stop2846-5" + offset="0" + style="stop-color:#deeaed;stop-opacity:1;" /> + <stop + id="stop2848-5" + offset="1" + style="stop-color:white;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient2852-4"> + <stop + id="stop2854-4" + offset="0" + style="stop-color:white;stop-opacity:1;" /> + <stop + id="stop2856-9" + offset="1" + style="stop-color:#69f;stop-opacity:0;" /> + </linearGradient> + <linearGradient + id="linearGradient2802-8" + inkscape:collect="always"> + <stop + id="stop2804-7" + offset="0" + style="stop-color:white;stop-opacity:1;" /> + <stop + id="stop2806-7" + offset="1" + style="stop-color:white;stop-opacity:0;" /> + </linearGradient> + <inkscape:perspective + id="perspective28-7" + inkscape:persp3d-origin="180.52499 : 90.333333 : 1" + inkscape:vp_z="361.04999 : 135.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 135.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3333" + id="radialGradient3152" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.26159009,0,114.82274)" + spreadMethod="pad" + cx="218.5" + cy="155.5" + fx="218.5" + fy="155.5" + r="170.25" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="4" + inkscape:cx="136.66909" + inkscape:cy="434.40442" + inkscape:document-units="px" + inkscape:current-layer="g3095" + showgrid="false" + inkscape:window-width="1440" + inkscape:window-height="852" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(202.23253,-561.2639)" /> + <g + inkscape:groupmode="layer" + id="layer2" + inkscape:label="Overlay" + transform="translate(202.23253,180.09827)"> + <g + id="g3123" + transform="matrix(1.6018307,0,0,1.6018307,-202.23253,-180.09829)"> + <g + id="g4178" + transform="translate(0,-741.36217)"> + <rect + class="fil0" + x="0" + y="741.36218" + width="437" + height="311" + id="rect15" + style="fill:#246ed8;fill-opacity:1;fill-rule:evenodd" /> + <path + inkscape:connector-curvature="0" + id="_209413168" + d="m 437,784.19187 -51.09387,15.50719 2.67726,4.9352 c 6.60756,-2.00336 11.66542,-2.6798 15.19269,-2.00795 3.25174,0.58094 5.90188,2.5612 7.67698,5.85451 1.04846,1.94516 1.89718,6.04621 2.19343,12.0477 l -7.03186,64.98019 -59.80306,-44.70714 c -4.42729,-3.18215 -7.53098,-6.41256 -9.22528,-9.55591 -3.46793,-6.43388 0.85501,-11.40513 12.70895,-14.99915 l -2.67726,-4.93521 -76.93112,23.32126 2.64501,4.93521 c 7.77402,-2.35704 14.59537,-2.68786 20.48271,-0.99188 5.6952,1.75585 13.23574,6.08392 22.61162,12.9912 l 87.12409,65.17372 -9.03175,91.88189 c -0.61305,7.6728 -2.35469,13.2366 -4.87069,16.9587 -2.51526,3.7235 -6.46083,6.489 -11.70901,8.0802 l 2.67726,4.9352 54.22273,-16.4265 -2.67726,-4.9352 c -11.65923,3.535 -19.07883,2.2888 -22.38583,-3.8465 -1.69355,-3.142 -2.0307,-7.9169 -1.16123,-14.27342 l 7.67699,-73.01199 20.7085,15.26526 0,-33.38521 -17.99898,-13.32989 7.7415,-71.63303 c 1.48071,-14.02881 3.14397,-23.09161 5.77386,-27.02267 1.05552,-1.57859 2.55398,-3.01 644 4.48 362,-4.35459 l 0,-7.45119 z" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" /> + <polygon + transform="matrix(18.028797,-5.4662042,7.48364,13.884058,-4968.8161,-1621.9047)" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + points="179.314,250.52 185.945,250.339 185.945,250.702 179.314,250.52 " + class="fil4" + id="_209583128" /> + <polygon + transform="matrix(18.028797,-5.4662042,7.48364,13.884058,-4968.8161,-1621.9047)" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + points="186.914,251.524 186.953,251.532 186.988,251.541 187.02,251.55 187.048,251.56 187.074,251.571 187.097,251.581 187.118,251.592 187.137,251.603 187.154,251.615 187.169,251.627 187.178,251.635 187.184,251.64 179.314,251.425 179.314,251.425 185.945,251.243 185.945,251.492 186.724,251.505 186.777,251.507 186.827,251.512 186.872,251.517 " + class="fil4" + id="_209423624" /> + <polygon + transform="matrix(18.028797,-5.4662042,7.48364,13.884058,-4968.8161,-1621.9047)" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + points="187.498,252.105 187.529,252.163 187.572,252.245 187.616,252.333 187.661,252.426 187.707,252.524 187.723,252.56 179.314,252.329 179.314,252.329 " + class="fil4" + id="_208944912" /> + <polygon + transform="matrix(18.028797,-5.4662042,7.48364,13.884058,-4968.8161,-1621.9047)" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + points="179.314,253.234 187.916,252.998 188.124,253.475 179.314,253.234 " + class="fil4" + id="_209380624" /> + <polygon + transform="matrix(18.028797,-5.4662042,7.48364,13.884058,-4968.8161,-1621.9047)" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + points="179.314,254.138 188.306,253.892 188.525,254.391 179.314,254.138 " + class="fil4" + id="_209438256" /> + <polygon + transform="matrix(18.028797,-5.4662042,7.48364,13.884058,-4968.8161,-1621.9047)" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + points="179.314,255.043 188.697,254.786 188.925,255.306 179.314,255.043 " + class="fil4" + id="_209597128" /> + <polygon + transform="matrix(18.028797,-5.4662042,7.48364,13.884058,-4968.8161,-1621.9047)" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + points="179.314,255.947 189.088,255.679 189.325,256.221 179.314,255.947 " + class="fil4" + id="_209596936" /> + <polygon + transform="matrix(18.028797,-5.4662042,7.48364,13.884058,-4968.8161,-1621.9047)" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + points="179.314,256.851 189.479,256.573 189.725,257.137 179.314,256.851 " + class="fil4" + id="_209588560" /> + <polygon + transform="matrix(18.028797,-5.4662042,7.48364,13.884058,-4968.8161,-1621.9047)" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + points="190.058,258.05 179.314,257.756 179.314,257.756 189.87,257.467 190.094,257.979 " + class="fil4" + id="_209560832" /> + <polygon + transform="matrix(18.028797,-5.4662042,7.48364,13.884058,-4968.8161,-1621.9047)" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + points="179.314,258.66 189.896,258.37 189.607,258.942 179.314,258.66 " + class="fil4" + id="_209558944" /> + <polygon + transform="matrix(18.028797,-5.4662042,7.48364,13.884058,-4968.8161,-1621.9047)" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + points="179.314,259.565 189.432,259.288 189.155,259.834 179.314,259.565 " + class="fil4" + id="_209559488" /> + <polygon + transform="matrix(18.028797,-5.4662042,7.48364,13.884058,-4968.8161,-1621.9047)" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + points="179.314,260.469 188.968,260.205 188.704,260.727 179.314,260.469 " + class="fil4" + id="_209558344" /> + <polygon + transform="matrix(18.028797,-5.4662042,7.48364,13.884058,-4968.8161,-1621.9047)" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + points="179.314,261.374 188.504,261.122 188.253,261.619 179.314,261.374 " + class="fil4" + id="_209557016" /> + <path + inkscape:connector-curvature="0" + id="_209557776" + d="m 365.29439,1038.3307 -42.80402,14.0315 13.25731,0 32.25624,-8.9995 -2.70953,-5.032 z" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" /> + <path + inkscape:connector-curvature="0" + id="_209553608" + d="m 377.68079,1019.485 -100.25238,32.8772 6.51576,0 77.28594,-21.5553 -1.61282,-3.024 13.35409,-4.3062 0.38707,-0.1451 0.38708,-0.1452 0.32256,-0.1452 0.32256,-0.1693 0.29031,-0.1693 0.2903,-0.1694 0.25805,-0.1693 0.25805,-0.1936 0.25805,-0.1935 0.2258,-0.2177 0.25805,-0.2178 0.19353,-0.2419 0.2258,-0.2419 0.22579,-0.2661 0.19354,-0.2903 0.22579,-0.3387 0.22579,-0.4113 0.16129,-0.2661 z" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" /> + <polygon + transform="matrix(18.028797,-5.4662042,7.48364,13.884058,-4968.8161,-1621.9047)" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + points="179.314,263.183 187.576,262.956 187.455,263.196 187.414,263.277 187.378,263.348 187.348,263.403 179.314,263.183 " + class="fil4" + id="_209553416" /> + <polygon + transform="matrix(18.028797,-5.4662042,7.48364,13.884058,-4968.8161,-1621.9047)" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + points="179.314,262.278 188.04,262.039 187.801,262.511 179.314,262.278 " + class="fil4" + id="_209552080" /> + <path + inkscape:connector-curvature="0" + id="_208969032" + d="m 434.1292,749.04063 c -3.01919,0.0519 -6.08889,0.5109 -9.03175,1.40315 l -298.91852,90.64809 c -13.45309,4.07889 -19.90606,15.88823 -14.32177,26.24852 l 99.73628,185.02181 6.32222,0 -99.51049,-184.58636 c -4.96389,-9.2093 0.78272,-19.69552 12.74122,-23.32125 l 293.49947,-89.00303 c 4.03635,-1.22379 8.30229,-1.49837 12.35414,-0.99188 l 0,-5.34647 c -0.96071,-0.0644 -1.90069,-0.0892 -2.8708,-0.0726 z" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" /> + <path + inkscape:connector-curvature="0" + style="opacity:0.27156552;fill:#ffffff;fill-rule:evenodd" + d="m 365.29439,1038.3307 -42.80402,14.0315 13.25731,0 32.25624,-8.9995 -2.70953,-5.032 z" + id="path3356" /> + </g> + <g + id="g3095"> + <text + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.28717142;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.80357139000000000;stroke-dasharray:none;font-family:Sans" + x="23.857143" + y="51.142857" + id="text4974" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4976" + x="23.857143" + y="51.142857" + style="font-size:24.97142799999999951px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.28717142;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.80357139000000000;stroke-dasharray:none;font-family:Tahoma;-inkscape-font-specification:Tahoma">x2goclient</tspan></text> + <rect + style="fill:url(#radialGradient3152);fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-opacity:0.80357139;stroke-dasharray:none" + id="rect4982" + width="340" + height="88.571426" + x="48.5" + y="111.21429" + rx="5" + ry="5" /> + <path + style="fill:#ffffff;fill-opacity:0.78431373999999998;stroke:#000000;stroke-width:0.68171998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 225.32812,138.37425 0,10.05263 -31.75,0 0,6.91767 0,0.3109 0,6.91767 31.75,0 0,10.05263 L 243.42187,155.5 z" + id="path6168" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccccccc" /> + </g> + </g> + </g> +</svg> diff --git a/version.h b/version.h index b44511f..f858ac4 100644 --- a/version.h +++ b/version.h @@ -15,5 +15,5 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ -#define VERSION "4.0.0.3" +#define VERSION "4.0.0.4" diff --git a/x2goclient.pro b/x2goclient.pro index 3d13687..5d2206d 100755 --- a/x2goclient.pro +++ b/x2goclient.pro @@ -159,7 +159,6 @@ x2go_linux_static { macx { message(building $$TARGET with ldap and cups) LIBS += -framework LDAP -lcups -lcrypto -lssl -lz - CONFIG += x86 x86_64 ppc } win32-* { message(building $$TARGET for windows without ldap and cups) @@ -169,8 +168,6 @@ win32-* { QT += svg network ICON = icons/x2go-mac.icns QMAKE_INFO_PLIST = Info.plist -QMAKE_MAC_SDK = /Developer/SDKs/MacOSX10.5.sdk -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.5 plugin { DEFINES += CFGPLUGIN diff --git a/x2goplugin.rc b/x2goplugin.rc index 70eccaf..d49572e 100644 --- a/x2goplugin.rc +++ b/x2goplugin.rc @@ -1,8 +1,8 @@ 1 TYPELIB "x2goplugin.rc" 1 VERSIONINFO - FILEVERSION 4,0,0,3 - PRODUCTVERSION 4,0,0,3 + FILEVERSION 4,0,0,4 + PRODUCTVERSION 4,0,0,4 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -21,13 +21,13 @@ BEGIN VALUE "FileDescription", "Allows you to start X2Go session in a webbrowser\0" VALUE "FileExtents", "x2go\0" VALUE "FileOpenName", "Configuration File for X2Go Session (*.x2go)\0" - VALUE "FileVersion", "4, 0, 0 ,3\0" + VALUE "FileVersion", "4, 0, 0 ,4\0" VALUE "InternalName", "x2goplugin\0" - VALUE "LegalCopyright", "Copyright � 2010-2012 Obviously Nice\0" + VALUE "LegalCopyright", "Copyright � 2010-2013 Obviously Nice\0" VALUE "MIMEType", "application/x2go\0" VALUE "OriginalFilename", "npx2goplugin.dll\0" - VALUE "ProductName", "X2GoClient Plug-in 4.0.0.3\0" - VALUE "ProductVersion", "4, 0, 0, 3\0" + VALUE "ProductName", "X2GoClient Plug-in 4.0.0.4\0" + VALUE "ProductVersion", "4, 0, 0, 4\0" END END BLOCK "VarFileInfo" hooks/post-receive -- x2goclient.git (X2Go Client) This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "x2goclient.git" (X2Go Client).