diff --git a/CHANGELOG b/CHANGELOG
index 0b014d1f1..06515aa3b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,9 @@
# Nmap Changelog ($Id$); -*-text-*-
+o Switch to using gtk-mac-bundler and jhbuild for building the OS X installer.
+ This promises to reduce a lot of the problems we've had with local paths and
+ dependencies using the py2app and macports build system.
+
Nmap 7.00 [2015-11-19]
o This is the most important release since Nmap 6.00 back in May 2012!
diff --git a/macosx/Makefile b/macosx/Makefile
index 6fe469a14..ed6759d88 100644
--- a/macosx/Makefile
+++ b/macosx/Makefile
@@ -29,6 +29,9 @@ NPING_STAGING_DIR = Nping
NMAP_UPDATE_BUILD_DIR = nmap-update-build
NMAP_UPDATE_STAGING_DIR = nmap-update
+JHBUILD_PREFIX=$(HOME)/gtk/inst
+# MACPORTS_PREFIX is still here because of nmap-update, which needs
+# libsvn and libapr, which jhbuild doesn't support yet.
MACPORTS_PREFIX=$(HOME)/macports-10.8
PREFIX = /usr/local
@@ -52,7 +55,8 @@ UNIVERSAL_ARCHFLAGS = -arch i386
UNIVERSAL_CPPFLAGS = -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk
UNIVERSAL_CFLAGS = $(UNIVERSAL_CPPFLAGS) -mmacosx-version-min=10.8 $(UNIVERSAL_ARCHFLAGS)
UNIVERSAL_CXXFLAGS = $(UNIVERSAL_CFLAGS)
-UNIVERSAL_LDFLAGS = -Wl,-syslibroot,/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk -mmacosx-version-min=10.8 $(UNIVERSAL_ARCHFLAGS)
+# https://stackoverflow.com/questions/19637164/c-linking-error-after-upgrading-to-mac-os-x-10-9-xcode-5-0-1/19637199#19637199
+UNIVERSAL_LDFLAGS = -stdlib=libstdc++ -Wl,-syslibroot,/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk -mmacosx-version-min=10.9 $(UNIVERSAL_ARCHFLAGS)
CC = $(UNIVERSAL_CC)
CXX = $(UNIVERSAL_CXX)
@@ -63,8 +67,8 @@ CFLAGS += $(UNIVERSAL_CFLAGS)
CXXFLAGS += $(UNIVERSAL_CXXFLAGS)
LDFLAGS += $(UNIVERSAL_LDFLAGS)
-PYTHON = $(MACPORTS_PREFIX)/bin/python2.7
-OPENSSL_STATIC = $(MACPORTS_PREFIX)/lib/libssl.a $(MACPORTS_PREFIX)/lib/libcrypto.a $(MACPORTS_PREFIX)/lib/libz.a
+PYTHON = $(JHBUILD_PREFIX)/bin/python2.7
+OPENSSL_STATIC = $(JHBUILD_PREFIX)/lib/libssl.a $(JHBUILD_PREFIX)/lib/libcrypto.a
$(IMAGE_NAME): $(IMAGE_STAGING_DIR)/$(PKG_NAME)
rm -f $@
@@ -76,7 +80,7 @@ $(IMAGE_STAGING_DIR)/$(PKG_NAME): check-nmap check-ncat check-ndiff check-zenmap
$(PACKAGEMAKER) --doc nmap.pmdoc --title "Nmap $(NMAP_VERSION)" --no-relocate -o $@
check-%: stage-%
- if (find $* -perm -a+x -type f | xargs otool -L | grep "$(MACPORTS_PREFIX)"); then false; else echo "Libs are clean"; fi
+ if (find $* -perm -a+x -type f | xargs otool -L | grep "$(JHBUILD_PREFIX)"); then false; else echo "Libs are clean"; fi
export-%:
rm -rf $*
@@ -84,28 +88,28 @@ export-%:
svn export .. $*
stage-nmap: export-$(NMAP_BUILD_DIR)
- cd $(NMAP_BUILD_DIR) && ./configure --without-zenmap --without-ncat --without-ndiff --without-nping --without-nmap-update --with-openssl="$(MACPORTS_PREFIX)" $(CONFIGURE_ARGS)
+ cd $(NMAP_BUILD_DIR) && ./configure --without-zenmap --without-ncat --without-ndiff --without-nping --without-nmap-update --with-openssl="$(JHBUILD_PREFIX)" $(CONFIGURE_ARGS)
make -C $(NMAP_BUILD_DIR) OPENSSL_LIBS="$(OPENSSL_STATIC)"
rm -rf $(NMAP_STAGING_DIR)
make -C $(NMAP_BUILD_DIR) install DESTDIR="`pwd`/$(NMAP_STAGING_DIR)" OPENSSL_LIBS="$(OPENSSL_STATIC)"
stage-ncat: export-$(NCAT_BUILD_DIR)
- cd $(NCAT_BUILD_DIR) && ./configure --without-zenmap --with-ncat --without-ndiff --without-nping --without-nmap-update --with-openssl="$(MACPORTS_PREFIX)" $(CONFIGURE_ARGS)
- make -d -C $(NCAT_BUILD_DIR) build-ncat OPENSSL_LIBS="$(OPENSSL_STATIC)"
+ cd $(NCAT_BUILD_DIR) && ./configure --without-zenmap --with-ncat --without-ndiff --without-nping --without-nmap-update --with-openssl="$(JHBUILD_PREFIX)" $(CONFIGURE_ARGS)
+ make -C $(NCAT_BUILD_DIR) build-ncat OPENSSL_LIBS="$(OPENSSL_STATIC)"
rm -rf $(NCAT_STAGING_DIR)
- make -d -C $(NCAT_BUILD_DIR) install-ncat DESTDIR="`pwd`/$(NCAT_STAGING_DIR)" OPENSSL_LIBS="$(OPENSSL_STATIC)"
+ make -C $(NCAT_BUILD_DIR) install-ncat DESTDIR="`pwd`/$(NCAT_STAGING_DIR)" OPENSSL_LIBS="$(OPENSSL_STATIC)"
stage-nping: export-$(NPING_BUILD_DIR)
- cd $(NPING_BUILD_DIR) && ./configure --without-zenmap --without-ncat --without-ndiff --with-nping --without-nmap-update --with-openssl="$(MACPORTS_PREFIX)" $(CONFIGURE_ARGS)
+ cd $(NPING_BUILD_DIR) && ./configure --without-zenmap --without-ncat --without-ndiff --with-nping --without-nmap-update --with-openssl="$(JHBUILD_PREFIX)" $(CONFIGURE_ARGS)
make -C $(NPING_BUILD_DIR) build-nping OPENSSL_LIBS="$(OPENSSL_STATIC)"
rm -rf $(NPING_STAGING_DIR)
make -C $(NPING_BUILD_DIR) install-nping DESTDIR="`pwd`/$(NPING_STAGING_DIR)" OPENSSL_LIBS="$(OPENSSL_STATIC)"
stage-nmap-update: export-$(NMAP_UPDATE_BUILD_DIR)
- cd $(NMAP_UPDATE_BUILD_DIR) && ./configure --without-zenmap --without-ncat --without-ndiff --without-nping --with-nmap-update --with-apr=$(MACPORTS_PREFIX) --with-subversion=$(MACPORTS_PREFIX) --with-openssl="$(MACPORTS_PREFIX)" $(CONFIGURE_ARGS)
- make -C $(NMAP_UPDATE_BUILD_DIR) build-nmap-update OPENSSL_LIBS="$(OPENSSL_STATIC)"
+ cd $(NMAP_UPDATE_BUILD_DIR) && ./configure --without-zenmap --without-ncat --without-ndiff --without-nping --with-nmap-update --with-apr=$(MACPORTS_PREFIX) --with-subversion=$(MACPORTS_PREFIX) $(CONFIGURE_ARGS)
+ make -C $(NMAP_UPDATE_BUILD_DIR) build-nmap-update
rm -rf $(NMAP_UPDATE_STAGING_DIR)
- make -C $(NMAP_UPDATE_BUILD_DIR) install-nmap-update DESTDIR="`pwd`/$(NMAP_UPDATE_STAGING_DIR)" OPENSSL_LIBS="$(OPENSSL_STATIC)"
+ make -C $(NMAP_UPDATE_BUILD_DIR) install-nmap-update DESTDIR="`pwd`/$(NMAP_UPDATE_STAGING_DIR)"
install_name_tool -change "$(MACPORTS_PREFIX)/lib/libapr-1.0.dylib" "/usr/lib/libapr-1.0.dylib" "$(NMAP_UPDATE_STAGING_DIR)/usr/local/bin/nmap-update"
install_name_tool -change "$(MACPORTS_PREFIX)/lib/libsvn_client-1.0.dylib" "/usr/lib/libsvn_client-1.0.dylib" "$(NMAP_UPDATE_STAGING_DIR)/usr/local/bin/nmap-update"
install_name_tool -change "$(MACPORTS_PREFIX)/lib/libsvn_subr-1.0.dylib" "/usr/lib/libsvn_subr-1.0.dylib" "$(NMAP_UPDATE_STAGING_DIR)/usr/local/bin/nmap-update"
diff --git a/macosx/openssl.modules b/macosx/openssl.modules
new file mode 100644
index 000000000..236ad96f2
--- /dev/null
+++ b/macosx/openssl.modules
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/zenmap/install_scripts/macosx/Info.plist b/zenmap/install_scripts/macosx/Info.plist
index a1d666797..f0e07f8c3 100644
--- a/zenmap/install_scripts/macosx/Info.plist
+++ b/zenmap/install_scripts/macosx/Info.plist
@@ -1,5 +1,5 @@
-
+
CFBundleIdentifier
@@ -7,6 +7,26 @@
CFBundleName
Zenmap
NSHumanReadableCopyright
- © Insecure.Com LLC
+ ${APP_COPYRIGHT}
+ CFBundleDevelopmentRegion
+ English
+ CFBundleExecutable
+ Zenmap
+ CFBundleGetInfoString
+ ${VERSION}, ${APP_COPYRIGHT} ${APP_WEB_SITE}
+ CFBundleIconFile
+ zenmap.icns
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ ${VERSION}
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ ${VERSION}
+ LSMinimumSystemVersion
+ 10.9
diff --git a/zenmap/install_scripts/macosx/README b/zenmap/install_scripts/macosx/README
index 7dfb9330e..32cbd611b 100644
--- a/zenmap/install_scripts/macosx/README
+++ b/zenmap/install_scripts/macosx/README
@@ -3,32 +3,34 @@ to do with packaging on Mac OS X. They are useful only for those wanting
to build binary distributions of Zenmap for Mac OS X.
== Info.plist
-A properties list file that whose contents are merged with the default
-properties added by py2app.
+A properties list file template that is filled out by make-bundle.sh
== make-bundle.sh
This script builds a .app bundle. It must be run from the root of the
Zenmap source tree. The finished bundle is put in dist/Zenmap.app.
-== test_wrapper.py
-This file contains unit tests for zenmap_wrapper.py, because it needs to
-do some tricky escaping and substitution of configuration files.
-
== zenmap.icns
The icon file for the bundle. It was created using the Icon Composer
utility (open -a "Icon Composer").
== zenmap_auth.c
-This is a simple wrapper program that attempts to run zenmap_wrapper.py
+This is a simple wrapper program that attempts to run launcher.sh
with privileges.
-== zenmap_wrapper.py
-This is a wrapper script that gets installed in the application bundle.
-It sets up an execution environment and then calls the main zenmap
-executable.
+== launcher.sh
+A launcher script that configures the environment for Zenmap, Python, and GTK
+before launching the main Zenmap script file.
+
+== zenmap.bundle
+An XML config file for gtk-mac-bundler which specifies files and metadata for
+the application bundle. https://wiki.gnome.org/Projects/GTK%2B/OSX/Building
+
== MacPorts-ports.diff
+*** Note: The MacPorts tree is only currently used for building libsvn and
+libapr for nmap-update, and will hopefully be removed in future releases.
+
This patch against a MacPorts ports tree contains various changes needed
to install dependencies in a sufficiently portable way. The main thing
accomplished by this patch is to avoid building a MacPorts libiconv.
@@ -36,15 +38,15 @@ libcups depends on libiconv, but it depends on an Apple version of
libconv, and MacPorts doesn't have a port for libcups. The MacPorts
libiconv is incompatible and causes a dynamic linker error at runtime.
-The following instructions show how to make a 10.5-compatible
+The following instructions show how to make a 10.9-compatible
environment suitable for building Zenmap packages. It will be a separate
-installation in $HOME/macports-10.5 that won't interfere with your
+installation in $HOME/macports-10.9 that won't interfere with your
normal MacPorts installation in /opt/local. These instructions were done
with MacPorts 2.3.3 on Mac OS X 10.9.5.
1. Install MacPorts.
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
- export PREFIX=$HOME/macports-10.8
+ export PREFIX=$HOME/macports-10.9
tar xzvf MacPorts-2.3.3.tar.gz
cd MacPorts-2.3.3
./configure --with-no-root-privileges --prefix=$PREFIX --with-applications-dir=$PREFIX/Applications
@@ -56,12 +58,12 @@ with MacPorts 2.3.3 on Mac OS X 10.9.5.
Uncomment the line
build_arch i386
Add this line at the bottom:
- macosx_deployment_target 10.8
+ macosx_deployment_target 10.9
4. Make a local patched ports tree.
cd $PREFIX
mkdir ports
ln -s var/macports/sources/rsync.macports.org/release/tarballs/ports ports.orig
- for x in archivers/xz editors/vim devel/apr-util devel/atk devel/gettext devel/glib2 gnome/gtk2 graphics/fontconfig graphics/gdk-pixbuf2 mail/libidn perl/p5-locale-gettext python/py-gobject python/py-libxml2 textproc/help2man textproc/libxml2 textproc/libxslt x11/pango; do
+ for x in archivers/xz editors/vim devel/apr-util devel/atk devel/gettext mail/libidn perl/p5-locale-gettext textproc/help2man; do
mkdir -v -p ports/$x;
cp -R ports.orig/$x ports/$(dirname $x);
done
@@ -71,10 +73,10 @@ with MacPorts 2.3.3 on Mac OS X 10.9.5.
$PREFIX/bin/portindex
6. Edit the file $PREFIX/etc/macports/sources.conf.
Add a line
- file:///Users/user/macports-10.8/ports
+ file:///Users/user/macports-10.9/ports
above the rsync line. (Replace "user" with your user name.)
7. Install the dependencies of Zenmap.
- $PREFIX/bin/port install py26-pygtk py26-py2app apr apr-util
+ $PREFIX/bin/port install apr apr-util openssl
Here are instructions for updating the patch to keep up with MacPorts
changes. First, sync the original ports tree.
@@ -84,7 +86,7 @@ Restore a pristine partial ports tree:
# rsync handles deleting deleted files, but can't pick up new ones like this...
rsync -rv --existing --delete --exclude=PortIndex ports.orig/ ports/
# ...so we copy everything over again.
- for x in archivers/xz editors/vim devel/apr-util devel/atk devel/gettext devel/glib2 gnome/gtk2 graphics/fontconfig graphics/gdk-pixbuf2 mail/libidn perl/p5-locale-gettext python/py-gobject python/py-libxml2 textproc/help2man textproc/libxml2 textproc/libxslt x11/pango; do
+ for x in archivers/xz editors/vim devel/apr-util devel/atk devel/gettext mail/libidn perl/p5-locale-gettext textproc/help2man; do
cp -R ports.orig/$x ports/$(dirname $x);
done
Reapply the patch. Resolve any conflicts.
diff --git a/zenmap/install_scripts/macosx/launcher.sh b/zenmap/install_scripts/macosx/launcher.sh
new file mode 100755
index 000000000..2f6b48984
--- /dev/null
+++ b/zenmap/install_scripts/macosx/launcher.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+name=`basename "$0"`
+tmp="$0"
+tmp=`dirname "$tmp"`
+tmp=`dirname "$tmp"`
+bundle=`dirname "$tmp"`
+bundle_contents="$bundle"/Contents
+bundle_res="$bundle_contents"/Resources
+bundle_lib="$bundle_res"/lib
+bundle_bin="$bundle_res"/bin
+bundle_data="$bundle_res"/share
+bundle_etc="$bundle_res"/etc
+
+export DYLD_LIBRARY_PATH="$bundle_lib"
+export XDG_CONFIG_DIRS="$bundle_etc"/xdg
+export XDG_DATA_DIRS="$bundle_data"
+export GTK_DATA_PREFIX="$bundle_res"
+export GTK_EXE_PREFIX="$bundle_res"
+export GTK_PATH="$bundle_res"
+
+export GTK2_RC_FILES="$bundle_etc/gtk-2.0/gtkrc"
+export GTK_IM_MODULE_FILE="$bundle_etc/gtk-2.0/gtk.immodules"
+export GDK_PIXBUF_MODULE_FILE="$bundle_lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
+export PANGO_LIBDIR="$bundle_lib"
+export PANGO_SYSCONFDIR="$bundle_etc"
+
+#Set $PYTHON to point inside the bundle
+export PYTHON="$bundle_contents/MacOS/python"
+#Add the bundle's python modules
+PYTHONHOME="$bundle_res"
+export PYTHONHOME
+PYTHONPATH="$bundle_res/lib/zenmap"
+export PYTHONPATH
+
+# We need a UTF-8 locale.
+if test "x$LANG" == "x"; then
+lang=`defaults read .GlobalPreferences AppleLocale 2>/dev/null`
+if test "$?" != "0"; then
+ lang=`defaults read .GlobalPreferences AppleCollationOrder 2>/dev/null | sed 's/_.*//'`
+fi
+if test "$?" == "0"; then
+ export LANG="`grep \"\`echo $lang\`_\" /usr/share/locale/locale.alias | \
+ tail -n1 | sed 's/\./ /' | awk '{print $2}'`.UTF-8"
+fi
+fi
+
+if test -f "$bundle_lib/charset.alias"; then
+ export CHARSETALIASDIR="$bundle_lib"
+fi
+
+# Extra arguments can be added in environment.sh.
+EXTRA_ARGS=
+if test -f "$bundle_res/environment.sh"; then
+ source "$bundle_res/environment.sh"
+fi
+
+# Strip out the argument added by the OS.
+if /bin/expr "x$1" : "x-psn_.*" > /dev/null; then
+ shift 1
+fi
+
+# Make the real UID equal the effective UID. They are unequal when running
+# with privileges under AuthorizationExecuteWithPrivileges. GTK+ refuses to
+# run if they are different
+# Note that we're calling $PYTHON here to override the version in zenmap's shebang.
+$EXEC $PYTHON -c $'import os\nif os.getuid()!=os.geteuid():os.setuid(os.geteuid())\n'"os.execl(\"$PYTHON\",\"$PYTHON\",\"$bundle_bin/zenmap\")"
diff --git a/zenmap/install_scripts/macosx/make-bundle.sh b/zenmap/install_scripts/macosx/make-bundle.sh
index b8020f579..5919bc5df 100755
--- a/zenmap/install_scripts/macosx/make-bundle.sh
+++ b/zenmap/install_scripts/macosx/make-bundle.sh
@@ -1,35 +1,15 @@
#!/bin/sh -e
+set -x
# make-bundle.sh
-# David Fifield
-#
-# This script works the magic needed to build Zenmap into a .app bundle for Mac
-# OS X. It's complicated because py2app doesn't really support Pango or PyGTK.
-#
-# It is based on the osx-app.sh script used by Wireshark, which contains the
-# following notice:
-#
-# AUTHORS
-# Kees Cook
-# Michael Wybrow
-# Jean-Olivier Irisson
-#
-# Copyright (C) 2005 Kees Cook
-# Copyright (C) 2005-2007 Michael Wybrow
-# Copyright (C) 2007 Jean-Olivier Irisson
-#
-# Released under GNU GPL, read the file 'COPYING' for more information
-
-# This script relies on having an installation of MacPorts in $(LIBPREFIX),
-# configured as you wish. See README for instructions on how to make a build
-# environment. You need to have installed the packages py26-gtk and
-# py26-py2app.
-
-LIBPREFIX=$HOME/macports-10.8
-PYTHON=$LIBPREFIX/bin/python2.7
-PKG_CONFIG=$LIBPREFIX/bin/pkg-config
APP_NAME=Zenmap
-BASE=dist/$APP_NAME.app/Contents
+ZENMAP_DIST_DIR=$PWD/dist
+ZENMAP_BUILD_DIR=$PWD/build
+
+export ZENMAP_DIST_DIR
+export ZENMAP_BUILD_DIR
+
+BASE=$ZENMAP_DIST_DIR/$APP_NAME.app/Contents
SCRIPT_DIR=`dirname "$0"`
CC=${CC:-gcc}
@@ -38,48 +18,63 @@ CFLAGS=${CFLAGS:--Wall -arch i386}
echo "Running $0."
echo "Removing old build."
-rm -rf build dist
+rm -rf "$ZENMAP_DIST_DIR" "$ZENMAP_BUILD_DIR"
-echo "Compiling using py2app."
-$PYTHON setup.py py2app --arch=i386 --no-strip
+echo "Building bundle"
+# jhbuild bootstrap
+# jhbuild build meta-gtk-osx-bootstrap
+# jhbuild build meta-gtk-osx-core
+# jhbuild build meta-gtk-osx-python
+gtk-mac-bundler "$SCRIPT_DIR/zenmap.bundle"
-# Delete a library that causes compatibility problems with OS X 10.9.
-# http://seclists.org/nmap-dev/2013/q4/85
-rm -f $BASE/Frameworks/libxml2.2.dylib
-
-mkdir -p $BASE/Resources/etc
-mkdir -p $BASE/Resources/lib
-
-gtk_version=`$PKG_CONFIG --variable=gtk_binary_version gtk+-2.0`
-echo "Copying GTK+ $gtk_version files."
-mkdir -p $BASE/Resources/lib/gtk-2.0/$gtk_version
-cp -R $LIBPREFIX/lib/gtk-2.0/$gtk_version/* $BASE/Resources/lib/gtk-2.0/$gtk_version/
-
-mkdir -p $BASE/Resources/etc/gtk-2.0
-cp $SCRIPT_DIR/gtkrc $BASE/Resources/etc/gtk-2.0/
-
-echo "Updating paths in GTK+ .so files"
-ESCAPED_LIBPREFIX=$(echo $LIBPREFIX | sed 's/\([\/\\.]\)/\\\1/g')
-find $BASE/Resources/lib/gtk-2.0/$gtk_version/ -type f -name '*.so' | while read so; do
- otool -L "$so" | awk "/$ESCAPED_LIBPREFIX/{print \$1}" | while read dep; do
- install_name_tool -change $dep $(echo $dep | sed "s/$ESCAPED_LIBPREFIX\/lib/@executable_path\/..\/Frameworks/") "$so"
- done
+echo "Stripping unoptimized Python libraries"
+#Remove some stuff that is unneeded. This cuts 40M off the installed size.
+rm -rf $BASE/Resources/lib/python2.7/test/
+rm -rf $BASE/Resources/lib/python2.7/config/
+rm -rf $BASE/Resources/lib/python2.7/idlelib/
+rm -rf $BASE/Resources/lib/python2.7/lib-tk/
+rm -rf $BASE/Resources/lib/python2.7/lib2to3/
+rm -f $BASE/Resources/lib/python2.7/site-packages/*.a
+find "$BASE/Resources/lib/python2.7" -type f -name '*.py' | while read py; do
+# If the .pyc exists, delete the .py
+ test -f "${py}c" && rm -v "$py"
+done
+find "$BASE/Resources/lib/python2.7" -type f -name '*.pyo' | while read py; do
+ # If the .pyc exists, delete the .pyo
+ test -f "${py/%o/c}" && rm -v "$py"
done
-echo "Copying Fontconfig files."
-cp -R $LIBPREFIX/etc/fonts $BASE/Resources/etc/
-# Remove the dir and cachedir under $LIBPREFIX. The cachedir ~/.fontconfig remains.
-sed -i "" 's/ *'$(echo "$LIBPREFIX" | sed -e 's/\([^a-zA-Z0-9]\)/\\\1/g')'\/share\/fonts<\/dir>//g' $BASE/Resources/etc/fonts/fonts.conf
-sed -i "" '/'$(echo "$LIBPREFIX" | sed -e 's/\([^a-zA-Z0-9]\)/\\\1/g')'\/var\/cache\/fontconfig<\/cachedir>/d' $BASE/Resources/etc/fonts/fonts.conf
-# Disable hinting to better match the Mac GUI.
-cp $LIBPREFIX/share/fontconfig/conf.avail/10-unhinted.conf $BASE/Resources/etc/fonts/conf.d
+echo "Building using distutils"
+python setup.py build --executable "/usr/bin/env python"
+python setup.py install vanilla --prefix "$BASE/Resources"
+
+# This isn't truly necessary, but it allows us to do a simpler check for problems later.
+echo "Rewriting linker paths to pass checks"
+ESCAPED_LIBBASE=$(echo "$BASE/Resources/" | sed 's/\([\/\\.]\)/\\\1/g')
+find $BASE/Resources/lib -type f -name '*.dylib' | while read so; do
+ dep=$(echo "$so" | sed "s/$ESCAPED_LIBBASE//")
+ install_name_tool -id "@executable_path/../Resources/$dep" "$so"
+done
echo "Renaming main Zenmap executable."
mv $BASE/MacOS/$APP_NAME $BASE/MacOS/zenmap.bin
-
-echo "Installing wrapper script."
-cp $SCRIPT_DIR/zenmap_wrapper.py $BASE/MacOS/
+# This is a dummy script, so we'll clean it up:
+rm $BASE/MacOS/$APP_NAME-bin
echo "Compiling and installing authorization wrapper."
-echo $CC $CPPFLAGS $CFLAGS $LDFLAGS -framework Security -o $BASE/MacOS/$APP_NAME $SCRIPT_DIR/zenmap_auth.c
-$CC $CPPFLAGS $CFLAGS $LDFLAGS -framework Security -o $BASE/MacOS/$APP_NAME $SCRIPT_DIR/zenmap_auth.c
+echo $CC $CPPFLAGS $CFLAGS $LDFLAGS -framework Security -o "$BASE/MacOS/$APP_NAME" "$SCRIPT_DIR/zenmap_auth.c"
+$CC $CPPFLAGS $CFLAGS $LDFLAGS -framework Security -o "$BASE/MacOS/$APP_NAME" "$SCRIPT_DIR/zenmap_auth.c"
+
+echo "Filling out Info.plist"
+python - "$SCRIPT_DIR/Info.plist" >"$BASE/Info.plist" <<'EOF'
+import sys
+from string import Template
+from zenmapCore.Version import *
+from zenmapCore.Name import *
+with open(sys.argv[1],"r") as f:
+ sys.stdout.write(Template(f.read()).substitute(
+ VERSION=VERSION,
+ APP_WEB_SITE=APP_WEB_SITE,
+ APP_COPYRIGHT=APP_COPYRIGHT
+ ))
+EOF
diff --git a/zenmap/install_scripts/macosx/test_wrapper.py b/zenmap/install_scripts/macosx/test_wrapper.py
deleted file mode 100755
index a6e671d69..000000000
--- a/zenmap/install_scripts/macosx/test_wrapper.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python
-
-# This is a test class for the non-trivial escaping done by zenmap_wrapper.py.
-
-import unittest
-
-import zenmap_wrapper
-
-class test_key_file(unittest.TestCase):
- def test_escape(self):
- TESTS = (
- ("", ""),
- ("a", "a"),
- ("a\nb\tc\rd\\e", "a\\nb\\tc\\rd\\\\e"),
- ("a\"b", "a\"b")
- )
- for test_line, expected in TESTS:
- actual = zenmap_wrapper.escape_key_file_value(test_line)
- self.assertEqual(expected, actual)
-
- def test_escape_first_space(self):
- # Check first-character space escaping.
- self.assert_(zenmap_wrapper.escape_key_file_value(" abc").startswith("\\s"))
-
- def test_substitute(self):
- original = "abc"
- replacements = {"b": "\"\\\t\r\ndef"}
- expected = "a\"\\\\\\t\\r\\ndefc"
- actual = zenmap_wrapper.substitute_key_file_line(original, replacements)
- self.assertEqual(expected, actual)
-
-unittest.main()
diff --git a/zenmap/install_scripts/macosx/zenmap.bundle b/zenmap/install_scripts/macosx/zenmap.bundle
new file mode 100644
index 000000000..7e3fb4ef2
--- /dev/null
+++ b/zenmap/install_scripts/macosx/zenmap.bundle
@@ -0,0 +1,158 @@
+
+
+
+
+
+ ${env:JHBUILD_PREFIX}
+
+
+ ${env:ZENMAP_DIST_DIR}
+
+
+
+
+
+ ${project}/launcher.sh
+
+
+
+
+
+
+ ${project}/Info.plist
+
+
+
+ ${prefix}/bin/pygtk-demo
+
+
+
+
+ ${prefix}/bin/python
+
+
+
+
+ ${prefix}/lib/libpyglib-2.0-python.0.dylib
+
+
+
+ ${prefix}/lib/libgtk-quartz-${gtkversion}.0.dylib
+
+
+
+
+ ${prefix}/lib/${gtkdir}/modules/*.so
+
+
+
+
+ ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/engines/*.so
+
+
+ ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/printbackends/*.so
+
+
+
+
+ ${prefix}/lib/gdk-pixbuf-2.0/${pkg:gdk-pixbuf-2.0:gdk_pixbuf_binary_version}/loaders/*.so
+
+
+
+ ${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/*.so
+
+
+
+
+ ${prefix}/share/locale
+
+
+
+
+ ${prefix}/lib/python2.7/lib-dynload/*.so
+ ${prefix}/lib/python2.7/site-packages/*.so
+ ${prefix}/lib/python2.7/site-packages/cairo/*.so
+ ${prefix}/lib/python2.7/site-packages/glib/*.so
+ ${prefix}/lib/python2.7/site-packages/gobject/*.so
+ ${prefix}/lib/python2.7/site-packages/gtk-2.0/*.so
+ ${prefix}/lib/python2.7/site-packages/gtk-2.0/gtk/*.so
+ ${prefix}/lib/python2.7/site-packages/gtkmacintegration/*.so
+ ${prefix}/lib/python2.7/site-packages/gtkosx_application/*.so
+
+ ${prefix}/lib/python2.7/
+
+
+
+
+ ${prefix}/share/themes
+
+
+
+
+ ${project}/zenmap.icns
+
+
+
+
+
+ ${project}/gtkrc
+
+
+
+
+
diff --git a/zenmap/install_scripts/macosx/zenmap_auth.c b/zenmap/install_scripts/macosx/zenmap_auth.c
index 97c8d8404..8c378ebb1 100644
--- a/zenmap/install_scripts/macosx/zenmap_auth.c
+++ b/zenmap/install_scripts/macosx/zenmap_auth.c
@@ -18,7 +18,7 @@
#include
#include
-#define EXECUTABLE_NAME "zenmap_wrapper.py"
+#define EXECUTABLE_NAME "zenmap.bin"
int main(int argc, char *argv[]) {
AuthorizationItem items[] = {
diff --git a/zenmap/install_scripts/macosx/zenmap_wrapper.py b/zenmap/install_scripts/macosx/zenmap_wrapper.py
deleted file mode 100755
index 8689e73aa..000000000
--- a/zenmap/install_scripts/macosx/zenmap_wrapper.py
+++ /dev/null
@@ -1,181 +0,0 @@
-#!/usr/bin/env python
-
-# This is a wrapper script around the zenmap executable, used in a Mac OS X
-# .app bundle. It sets environment variables, fills in template configuration
-# files, starts X11 if necessary, and execs the real zenmap executable.
-#
-# This program is the second link in the chain
-# zenmap_auth -> zenmap_wrapper.py -> zenmap.bin
-
-import errno
-import os
-import os.path
-import sys
-
-HOME = os.path.expanduser("~")
-
-
-def create_dir(path):
- """Create a directory with os.makedirs without raising an error if the
- directory already exists."""
- try:
- os.makedirs(path)
- except OSError, e:
- if e.errno != errno.EEXIST:
- raise
-
-# We will need to rewrite some configuration files to refer to directories
-# inside the application bundle, wherever it may be. This is tricky because of
-# escaping issues in the formats of the configuration files. The following
-# functions handle it.
-
-# The format of pango/pangorc is called "key file." It's described at
-# http://library.gnome.org/devel/glib/stable/glib-Key-value-file-parser.
-
-
-# Escape a string as appropriate for a "key file."
-def escape_key_file_value(value):
- result = []
- for c in value:
- if c == "\n":
- c = "\\n"
- elif c == "\t":
- c = "\\t"
- elif c == "\r":
- c = "\\r"
- elif c == "\\":
- c = "\\\\"
- result.append(c)
- if len(result) > 0 and result[0] == " ":
- result[0] = "\\s"
- result = "".join(result)
- return result
-
-
-def substitute_key_file_line(line, replacements):
- for text, rep in replacements.items():
- line = line.replace(text, escape_key_file_value(rep))
- return line
-
-
-# Substitute a dict of replacements into a "key file."
-def substitute_key_file(in_file_name, out_file_name, replacements):
- in_file = open(in_file_name, "r")
- out_file = open(out_file_name, "w")
- for line in in_file:
- out_file.write(substitute_key_file_line(line, replacements))
- in_file.close()
- out_file.close()
-
-
-def escape_shell(arg):
- """Escape a string to be a shell argument."""
- result = []
- for c in arg:
- if c in "$`\"\\":
- c = "\\" + c
- result.append(c)
- return "\"" + "".join(result) + "\""
-
-
-def hack_xinitrc(system_xinitrc_filename, home_xinitrc_filename):
- """Hack the system xinitrc file and put the modified contents into another
- file. The parameter names reflect the fact that this is intended to copy
- the system xinitrc into ~/.xinitrc. The modified xinitrc will delete itself
- on its first invocation and will not run any instances of xterm. This is
- necessary on Mac OS X 10.4 and earlier, which include a call to xterm in
- the system xinitrc."""
- system_xinitrc = open(system_xinitrc_filename, "r")
- home_xinitrc = open(home_xinitrc_filename, "w")
- lines = iter(system_xinitrc)
- # Look for the first non-comment line so we don't preempt the #! line.
- for line in lines:
- if not line.lstrip().startswith("#"):
- break
- home_xinitrc.write(line)
- # Write the self-destruct line.
- home_xinitrc.write("\n")
- home_xinitrc.write("rm -f %s\n" % escape_shell(home_xinitrc_filename))
- home_xinitrc.write(line)
- # Copy the rest, removing any calls to xterm
- for line in lines:
- if line.lstrip().startswith("xterm"):
- line = "# " + line
- home_xinitrc.write(line)
- system_xinitrc.close()
- home_xinitrc.close()
-
-
-def start_x11():
- """Start the X11 server if necessary and set the DISPLAY environment as
- appropriate. If the user hasn't set up a custom ~/.xinitrc, call
- hack_xinitrc to make a ~/.xinitrc that will not start an xterm along with
- the application. A similar approach is taken by Wireshark and Inkscape."""
- if "DISPLAY" in os.environ:
- return
- system_xinitrc_filename = "/usr/X11R6/lib/X11/xinit/xinitrc"
- home_xinitrc_filename = os.path.join(HOME, ".xinitrc")
- if (os.path.exists(system_xinitrc_filename) and not
- os.path.exists(home_xinitrc_filename)):
- hack_xinitrc(system_xinitrc_filename, home_xinitrc_filename)
- os.system("open -a X11")
- os.environ["DISPLAY"] = ":0"
-
-if __name__ == "__main__":
- # Make the real UID equal the effective UID. They are unequal when running
- # with privileges under AuthorizationExecuteWithPrivileges. GTK+ refuses to
- # run if they are different.
- if os.getuid() != os.geteuid():
- os.setuid(os.geteuid())
-
- # Paths within the application bundle.
- currentdir = os.path.dirname(os.path.abspath(sys.argv[0]))
- parentdir = os.path.dirname(currentdir)
- resourcedir = os.path.join(parentdir, "Resources")
-
- # A directory where we put automatically generated GTK+ and Pango files.
- # This could be something different like /tmp or "~/Library/Application
- # Support/Zenmap". It is put somewhere other than within the application
- # bundle to allow running from a read-only filesystem.
- etcdir = os.path.join(HOME, ".zenmap-etc")
-
- # See http://library.gnome.org/devel/gtk/2.12/gtk-running.html for the
- # meaning of the GTK+ environment variables. These files are static and
- # live inside the application bundle.
- os.environ["GTK_DATA_PREFIX"] = resourcedir
- os.environ["GTK_EXE_PREFIX"] = resourcedir
- os.environ["GTK_PATH"] = resourcedir
- os.environ["FONTCONFIG_PATH"] = os.path.join(resourcedir, "etc", "fonts")
- # Use the packaged gtkrc only if the user doesn't have a custom one.
- if not os.path.exists(os.path.expanduser("~/.gtkrc-2.0")):
- os.environ["GTK2_RC_FILES"] = os.path.join(
- resourcedir, "etc", "gtk-2.0", "gtkrc")
-
- # The following environment variables refer to files within ~/.zenmap-etc
- # that are automatically generated from templates.
- os.environ["PANGO_RC_FILE"] = os.path.join(etcdir, "pango", "pangorc")
-
- # Create the template directory.
- create_dir(os.path.join(etcdir, "pango"))
-
- REPLACEMENTS = {
- "${RESOURCES}": resourcedir,
- "${ETC}": etcdir
- }
-
- # Fill in the templated configuration files with the correct substitutions.
- KEY_FILE_TEMPLATES = (
- "pango/pangorc",
- )
- for f in KEY_FILE_TEMPLATES:
- in_file_name = os.path.join(resourcedir, "etc", f + ".in")
- out_file_name = os.path.join(etcdir, f)
- substitute_key_file(in_file_name, out_file_name, REPLACEMENTS)
-
- start_x11()
-
- # exec the real program.
- os.execl(
- os.path.join(os.path.dirname(sys.argv[0]), "zenmap.bin"),
- *sys.argv
- )
diff --git a/zenmap/setup.py b/zenmap/setup.py
index 68e60825a..fd0280140 100755
--- a/zenmap/setup.py
+++ b/zenmap/setup.py
@@ -629,6 +629,9 @@ elif 'py2app' in sys.argv:
}
setup_args.update(MACOSX_SETUP_ARGS)
+elif 'vanilla' in sys.argv:
+ # Don't create uninstaller, don't fix paths. Used for bundling on OS X
+ sys.argv.remove('vanilla')
else:
# Default args.
DEFAULT_SETUP_ARGS = {
diff --git a/zenmap/zenmapCore/Paths.py b/zenmap/zenmapCore/Paths.py
index 404d7ced2..a1195a177 100644
--- a/zenmap/zenmapCore/Paths.py
+++ b/zenmap/zenmapCore/Paths.py
@@ -139,7 +139,7 @@ from zenmapCore.Name import APP_NAME
# http://mail.python.org/pipermail/pythonmac-sig/2004-November/012121.html.
def get_prefix():
frozen = getattr(sys, "frozen", None)
- if frozen == "macosx_app":
+ if frozen == "macosx_app" or "Zenmap.app" in sys.executable:
# A py2app .app bundle.
return os.path.join(dirname(fs_dec(sys.executable)), "..", "Resources")
elif frozen is not None: