1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Switch to gtk-mac-bundler and jhbuild for building OS X app bundle

This commit is contained in:
dmiller
2015-12-09 04:16:50 +00:00
parent 53d41055c7
commit 94d48e7913
13 changed files with 371 additions and 312 deletions

View File

@@ -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!

View File

@@ -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"

19
macosx/openssl.modules Normal file
View File

@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<!DOCTYPE moduleset SYSTEM "moduleset.dtd">
<?xml-stylesheet type="text/xsl" href="moduleset.xsl"?>
<moduleset>
<!--
This is a jhbuild moduleset that can be used to build openssl as required for
building Nmap, Ncat, and Nping. Use it like this:
jhbuild -m openssl.modules build openssl
-->
<include href="http://git.gnome.org/browse/gtk-osx/plain/modulesets-stable/gtk-osx.modules"/>
<repository type="tarball" name="openssl" href="http://www.openssl.org/source/"/>
<autotools id="openssl" autogen-sh="Configure"
autogen-template="%(srcdir)s/%(autogen-sh)s --prefix=%(prefix)s --libdir=lib darwin-i386-cc shared"
makeinstallargs="install_sw">
<branch repo="openssl" version="1.0.2e" module="openssl-1.0.2e.tar.gz"/>
</autotools>
</moduleset>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
@@ -7,6 +7,26 @@
<key>CFBundleName</key>
<string>Zenmap</string>
<key>NSHumanReadableCopyright</key>
<string>© Insecure.Com LLC</string>
<string>${APP_COPYRIGHT}</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>Zenmap</string>
<key>CFBundleGetInfoString</key>
<string>${VERSION}, ${APP_COPYRIGHT} ${APP_WEB_SITE}</string>
<key>CFBundleIconFile</key>
<string>zenmap.icns</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${VERSION}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${VERSION}</string>
<key>LSMinimumSystemVersion</key>
<string>10.9</string>
</dict>
</plist>

View File

@@ -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.

View File

@@ -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\")"

View File

@@ -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 <kees@outflux.net>
# Michael Wybrow <mjwybrow@users.sourceforge.net>
# Jean-Olivier Irisson <jo.irisson@gmail.com>
#
# 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/ *<dir>'$(echo "$LIBPREFIX" | sed -e 's/\([^a-zA-Z0-9]\)/\\\1/g')'\/share\/fonts<\/dir>//g' $BASE/Resources/etc/fonts/fonts.conf
sed -i "" '/<cachedir>'$(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

View File

@@ -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()

View File

@@ -0,0 +1,158 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<app-bundle>
<meta>
<!-- Where to pick up the GTK+ installation, icon themes,
etc. Note that "${env:JHBUILD_PREFIX}" is evaluated to the
value of the environment variable JHBUILD_PREFIX. You can
define additional prefixes and refer to them in paths
throughout this file on the form "${prefix:name}". This is
useful for installing certain libraries or even the
application itself separately. Note that JHBUILD_PREFIX is
defined by jhbuild, so it you are not using jhbuild you can
either define your own or just hardcode the path here.
-->
<prefix name="default">${env:JHBUILD_PREFIX}</prefix>
<!-- The project directory is the default location of the created
app. If you leave out the path, the current directory is
used. Note the usage of an environment variable here again.
-->
<destination overwrite="yes">${env:ZENMAP_DIST_DIR}</destination>
<!-- Comment this out to keep the install names in binaries. -->
<run-install-name-tool/>
<!--A launcher script is pretty much mandatory here so that we can
set $PYTHON to point to the python in the bundle.
-->
<launcher-script>${project}/launcher.sh</launcher-script>
<!-- Indicate the active gtk version to use. This is needed only
for gtk+-3.0 projects. -->
<!--gtk>gtk+-2.0</gtk-->
</meta>
<!-- The special macro "${project}" refers to the directory where
this bundle file is located. The application name and bundle
identifier are taken from the plist file.
-->
<plist>${project}/Info.plist</plist>
<!-- This is mandatory, and the result gets named to the appname from
Info.plist with bin tacked on the end, in this example,
PyGtkDemo-bin. Bundler won't let us use the one from $project,
so we use the original and ignore it. If your original will work
in the bundle, you can use this instead.-->
<main-binary>
${prefix}/bin/pygtk-demo
</main-binary>
<!-- We need to pack our own Python to avoid compatibility problems. -->
<binary dest="${bundle}/Contents/MacOS">
${prefix}/bin/python
</binary>
<!-- Copy in libpyglib, which will pull in other dependencies we need -->
<binary>
${prefix}/lib/libpyglib-2.0-python.0.dylib
</binary>
<!-- Gtk+ is required by python modules which aren't searched for
dependencies, so we have to pull it in explicitly. It will
bring Pango and Cairo with it. Note the use of ${gtkversion},
which expands to either 2.0 or 3.0, depending on which value of
gtk is specified.-->
<binary>
${prefix}/lib/libgtk-quartz-${gtkversion}.0.dylib
</binary>
<!-- Copy in GTK+ modules. Note the ${gtkdir} macro, which expands
to the correct library subdirectory for the specified gtk
version.
-->
<binary>
${prefix}/lib/${gtkdir}/modules/*.so
</binary>
<!-- Copy in GTK+ theme engines and print backends. Note the use of the
"${pkg:module:variable}" macro, which evaluates to a pkg-config
variable in the specified module. Note that any libraries that
binaries link to are also copied in automatically. Note also
the included ${gtk} macro, which gets the correct package name
to get. -->
<binary>
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/engines/*.so
</binary>
<binary>
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/printbackends/*.so
</binary>
<!-- Starting with 2.24, gdk-pixbuf installs into its own directory. -->
<binary>
${prefix}/lib/gdk-pixbuf-2.0/${pkg:gdk-pixbuf-2.0:gdk_pixbuf_binary_version}/loaders/*.so
</binary>
<binary>
${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/*.so
</binary>
<!-- Translation filenames, one for each program or library that you
want to copy in to the bundle. The "dest" attribute is
optional, as usual. Bundler will find all translations of that
library/program under the indicated directory and copy them.-->
<translations name="gtk20">
${prefix}/share/locale
</translations>
<!-- We have to pull in the python modules, which are mixed python
and loadable modules. -->
<binary>${prefix}/lib/python2.7/lib-dynload/*.so</binary>
<binary>${prefix}/lib/python2.7/site-packages/*.so</binary>
<binary>${prefix}/lib/python2.7/site-packages/cairo/*.so</binary>
<binary>${prefix}/lib/python2.7/site-packages/glib/*.so</binary>
<binary>${prefix}/lib/python2.7/site-packages/gobject/*.so</binary>
<binary>${prefix}/lib/python2.7/site-packages/gtk-2.0/*.so</binary>
<binary>${prefix}/lib/python2.7/site-packages/gtk-2.0/gtk/*.so</binary>
<binary>${prefix}/lib/python2.7/site-packages/gtkmacintegration/*.so</binary>
<binary>${prefix}/lib/python2.7/site-packages/gtkosx_application/*.so</binary>
<data>
${prefix}/lib/python2.7/
</data>
<!-- Copy in the themes data. You may want to trim this to save space
in your bundle. -->
<data>
${prefix}/share/themes
</data>
<!-- Copy icons. Note that the .icns file is an Apple format which
contains up to 4 sizes of icon. You can use
/Developer/Applications/Utilities/Icon Composer.app to import
artwork and create the file. -->
<data dest="${bundle}/Contents/Resources">
${project}/zenmap.icns
</data>
<!-- This is where theme commands go. You can copy them in from your
theme of choice if they provide and example, or you can just
change the source path. -->
<data dest="${bundle}/Contents/Resources/etc/${gtkdir}/gtkrc">
${project}/gtkrc
</data>
<!-- Icon themes to copy. The "icons" property can be either of
"auto", "all", or "none". All or none should be
self-explanatory, while auto means that the script will try to
figure out which icons are needed. This is done by getting all
the strings from all copied binaries, and matching them against
icon names. To be safe, you should use "all". "none" is useful
if you want just the index.theme file but no icons, mostly
needed for the "hicolor" base theme.
>
<icon-theme icons="auto">
Tango
</icon-theme -->
</app-bundle>

View File

@@ -18,7 +18,7 @@
#include <Security/Authorization.h>
#include <Security/AuthorizationTags.h>
#define EXECUTABLE_NAME "zenmap_wrapper.py"
#define EXECUTABLE_NAME "zenmap.bin"
int main(int argc, char *argv[]) {
AuthorizationItem items[] = {

View File

@@ -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
)

View File

@@ -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 = {

View File

@@ -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: