summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkali <kali@leap.se>2017-08-03 21:01:34 -0700
committerKali Kaneko <kali@leap.se>2017-08-14 18:09:15 -0400
commit201a751f0a0da9fa0427d683cb56725a40a00d89 (patch)
tree3c148c489cceb71ccbb9c0a8d37a331506001b67
parent9c74ffb925325de98e8dd73acdf1602dd40bfcc0 (diff)
[pkg] automate flat package
-rw-r--r--Makefile3
-rwxr-xr-xpkg/osx/installer/Bitmask.pkgproj755
-rw-r--r--pkg/osx/installer/README.rst2
-rwxr-xr-xpkg/osx/quickpkg557
-rwxr-xr-xpkg/osx/scripts/postinstall (renamed from pkg/osx/installer/post-inst.sh)2
-rwxr-xr-xpkg/osx/scripts/preinstall (renamed from pkg/osx/installer/pre-inst.sh)4
-rw-r--r--pkg/osx/scripts/se.leap.bitmask-helper.plist (renamed from pkg/osx/installer/se.leap.bitmask-helper.plist)0
-rw-r--r--pkg/pyinst/build.mk2
8 files changed, 566 insertions, 759 deletions
diff --git a/Makefile b/Makefile
index eac906c8..d4f3afe7 100644
--- a/Makefile
+++ b/Makefile
@@ -69,6 +69,9 @@ bundle_in_docker:
docker_container:
cd pkg/docker_bundle && docker build -t mybundle .
+osx_pkg:
+ pkg/osx/quickpkg --output dist/Bitmask-$(NEXT_VERSION).pkg --scripts pkg/osx/scripts/ dist/Bitmask.app/
+
cleanpkg:
rm -rf dist build
diff --git a/pkg/osx/installer/Bitmask.pkgproj b/pkg/osx/installer/Bitmask.pkgproj
deleted file mode 100755
index f42ffc87..00000000
--- a/pkg/osx/installer/Bitmask.pkgproj
+++ /dev/null
@@ -1,755 +0,0 @@
-<?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">
-<plist version="1.0">
-<dict>
- <key>PROJECT</key>
- <dict>
- <key>PACKAGE_FILES</key>
- <dict>
- <key>DEFAULT_INSTALL_LOCATION</key>
- <string>/Applications</string>
- <key>HIERARCHY</key>
- <dict>
- <key>CHILDREN</key>
- <array>
- <dict>
- <key>CHILDREN</key>
- <array>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>80</integer>
- <key>PATH</key>
- <string>Bitmask.app</string>
- <key>PATH_TYPE</key>
- <integer>3</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>3</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>80</integer>
- <key>PATH</key>
- <string>Utilities</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>GID</key>
- <integer>80</integer>
- <key>PATH</key>
- <string>Applications</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>509</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>80</integer>
- <key>PATH</key>
- <string>Application Support</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>Automator</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>Documentation</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>Filesystems</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>Frameworks</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>Input Methods</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>Internet Plug-Ins</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>LaunchAgents</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>LaunchDaemons</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>PreferencePanes</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>Preferences</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>80</integer>
- <key>PATH</key>
- <string>Printers</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>PrivilegedHelperTools</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>QuickLook</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>QuickTime</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>Screen Savers</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>Scripts</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>Services</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>Widgets</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>Library</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array>
- <dict>
- <key>CHILDREN</key>
- <array>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>Extensions</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>Library</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>System</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>CHILDREN</key>
- <array>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>Shared</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>1023</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>GID</key>
- <integer>80</integer>
- <key>PATH</key>
- <string>Users</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>/</string>
- <key>PATH_TYPE</key>
- <integer>0</integer>
- <key>PERMISSIONS</key>
- <integer>493</integer>
- <key>TYPE</key>
- <integer>1</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- <key>PAYLOAD_TYPE</key>
- <integer>0</integer>
- <key>VERSION</key>
- <integer>3</integer>
- </dict>
- <key>PACKAGE_SCRIPTS</key>
- <dict>
- <key>POSTINSTALL_PATH</key>
- <dict>
- <key>PATH</key>
- <string>../../bitmask-dev/pkg/osx/installer/post-inst.sh</string>
- <key>PATH_TYPE</key>
- <integer>3</integer>
- </dict>
- <key>PREINSTALL_PATH</key>
- <dict>
- <key>PATH</key>
- <string>../pkg/osx/installer/pre-inst.sh</string>
- <key>PATH_TYPE</key>
- <integer>3</integer>
- </dict>
- <key>RESOURCES</key>
- <array>
- <dict>
- <key>CHILDREN</key>
- <array/>
- <key>GID</key>
- <integer>0</integer>
- <key>PATH</key>
- <string>se.leap.bitmask-helper.plist</string>
- <key>PATH_TYPE</key>
- <integer>1</integer>
- <key>PERMISSIONS</key>
- <integer>420</integer>
- <key>TYPE</key>
- <integer>3</integer>
- <key>UID</key>
- <integer>0</integer>
- </dict>
- </array>
- </dict>
- <key>PACKAGE_SETTINGS</key>
- <dict>
- <key>AUTHENTICATION</key>
- <integer>1</integer>
- <key>CONCLUSION_ACTION</key>
- <integer>0</integer>
- <key>IDENTIFIER</key>
- <string>se.leap.pkg.Bitmask</string>
- <key>OVERWRITE_PERMISSIONS</key>
- <false/>
- <key>RELOCATABLE</key>
- <true/>
- <key>USE_HFS+_COMPRESSION</key>
- <true/>
- <key>VERSION</key>
- <string>0.10a1</string>
- </dict>
- <key>PROJECT_COMMENTS</key>
- <dict>
- <key>NOTES</key>
- <data>
- PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBIVE1M
- IDQuMDEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQv
- c3RyaWN0LmR0ZCI+CjxodG1sPgo8aGVhZD4KPG1ldGEgaHR0cC1l
- cXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7
- IGNoYXJzZXQ9VVRGLTgiPgo8bWV0YSBodHRwLWVxdWl2PSJDb250
- ZW50LVN0eWxlLVR5cGUiIGNvbnRlbnQ9InRleHQvY3NzIj4KPHRp
- dGxlPjwvdGl0bGU+CjxtZXRhIG5hbWU9IkdlbmVyYXRvciIgY29u
- dGVudD0iQ29jb2EgSFRNTCBXcml0ZXIiPgo8bWV0YSBuYW1lPSJD
- b2NvYVZlcnNpb24iIGNvbnRlbnQ9IjEyNjUuMjEiPgo8c3R5bGUg
- dHlwZT0idGV4dC9jc3MiPgpwLnAxIHttYXJnaW46IDAuMHB4IDAu
- MHB4IDAuMHB4IDAuMHB4OyBmb250OiAxMi4wcHggSGVsdmV0aWNh
- fQo8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5Pgo8cCBjbGFzcz0icDEi
- Pk1heSB0aGUgT1NYIGJ1bmRsZXMgYmUgd2l0aCB5b3U8L3A+Cjwv
- Ym9keT4KPC9odG1sPgo=
- </data>
- </dict>
- <key>PROJECT_SETTINGS</key>
- <dict>
- <key>BUILD_PATH</key>
- <dict>
- <key>PATH</key>
- <string>../../../../../Bitmask/build</string>
- <key>PATH_TYPE</key>
- <integer>1</integer>
- </dict>
- <key>CERTIFICATE</key>
- <dict>
- <key>NAME</key>
- <string>Developer ID Installer: LEAP Encryption Access Project (SB5RR8K33W)</string>
- <key>PATH</key>
- <string>/Users/user/Library/Keychains/login.keychain</string>
- </dict>
- <key>EXCLUDED_FILES</key>
- <array>
- <dict>
- <key>PATTERNS_ARRAY</key>
- <array>
- <dict>
- <key>REGULAR_EXPRESSION</key>
- <false/>
- <key>STRING</key>
- <string>.DS_Store</string>
- <key>TYPE</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>PROTECTED</key>
- <true/>
- <key>PROXY_NAME</key>
- <string>Remove .DS_Store files</string>
- <key>PROXY_TOOLTIP</key>
- <string>Remove ".DS_Store" files created by the Finder.</string>
- <key>STATE</key>
- <true/>
- </dict>
- <dict>
- <key>PATTERNS_ARRAY</key>
- <array>
- <dict>
- <key>REGULAR_EXPRESSION</key>
- <false/>
- <key>STRING</key>
- <string>.pbdevelopment</string>
- <key>TYPE</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>PROTECTED</key>
- <true/>
- <key>PROXY_NAME</key>
- <string>Remove .pbdevelopment files</string>
- <key>PROXY_TOOLTIP</key>
- <string>Remove ".pbdevelopment" files created by ProjectBuilder or Xcode.</string>
- <key>STATE</key>
- <true/>
- </dict>
- <dict>
- <key>PATTERNS_ARRAY</key>
- <array>
- <dict>
- <key>REGULAR_EXPRESSION</key>
- <false/>
- <key>STRING</key>
- <string>CVS</string>
- <key>TYPE</key>
- <integer>1</integer>
- </dict>
- <dict>
- <key>REGULAR_EXPRESSION</key>
- <false/>
- <key>STRING</key>
- <string>.cvsignore</string>
- <key>TYPE</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>REGULAR_EXPRESSION</key>
- <false/>
- <key>STRING</key>
- <string>.cvspass</string>
- <key>TYPE</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>REGULAR_EXPRESSION</key>
- <false/>
- <key>STRING</key>
- <string>.svn</string>
- <key>TYPE</key>
- <integer>1</integer>
- </dict>
- <dict>
- <key>REGULAR_EXPRESSION</key>
- <false/>
- <key>STRING</key>
- <string>.git</string>
- <key>TYPE</key>
- <integer>1</integer>
- </dict>
- <dict>
- <key>REGULAR_EXPRESSION</key>
- <false/>
- <key>STRING</key>
- <string>.gitignore</string>
- <key>TYPE</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>PROTECTED</key>
- <true/>
- <key>PROXY_NAME</key>
- <string>Remove SCM metadata</string>
- <key>PROXY_TOOLTIP</key>
- <string>Remove helper files and folders used by the CVS, SVN or Git Source Code Management systems.</string>
- <key>STATE</key>
- <true/>
- </dict>
- <dict>
- <key>PATTERNS_ARRAY</key>
- <array>
- <dict>
- <key>REGULAR_EXPRESSION</key>
- <false/>
- <key>STRING</key>
- <string>classes.nib</string>
- <key>TYPE</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>REGULAR_EXPRESSION</key>
- <false/>
- <key>STRING</key>
- <string>designable.db</string>
- <key>TYPE</key>
- <integer>0</integer>
- </dict>
- <dict>
- <key>REGULAR_EXPRESSION</key>
- <false/>
- <key>STRING</key>
- <string>info.nib</string>
- <key>TYPE</key>
- <integer>0</integer>
- </dict>
- </array>
- <key>PROTECTED</key>
- <true/>
- <key>PROXY_NAME</key>
- <string>Optimize nib files</string>
- <key>PROXY_TOOLTIP</key>
- <string>Remove "classes.nib", "info.nib" and "designable.nib" files within .nib bundles.</string>
- <key>STATE</key>
- <true/>
- </dict>
- <dict>
- <key>PATTERNS_ARRAY</key>
- <array>
- <dict>
- <key>REGULAR_EXPRESSION</key>
- <false/>
- <key>STRING</key>
- <string>Resources Disabled</string>
- <key>TYPE</key>
- <integer>1</integer>
- </dict>
- </array>
- <key>PROTECTED</key>
- <true/>
- <key>PROXY_NAME</key>
- <string>Remove Resources Disabled folders</string>
- <key>PROXY_TOOLTIP</key>
- <string>Remove "Resources Disabled" folders.</string>
- <key>STATE</key>
- <true/>
- </dict>
- <dict>
- <key>SEPARATOR</key>
- <true/>
- </dict>
- </array>
- <key>NAME</key>
- <string>Bitmask</string>
- <key>REFERENCE_FOLDER_PATH</key>
- <string>/Users/user/leap/bitmask-dev/dist</string>
- </dict>
- </dict>
- <key>TYPE</key>
- <integer>1</integer>
- <key>VERSION</key>
- <integer>2</integer>
-</dict>
-</plist>
diff --git a/pkg/osx/installer/README.rst b/pkg/osx/installer/README.rst
deleted file mode 100644
index ff5676e3..00000000
--- a/pkg/osx/installer/README.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-This is a project to generate Bitmask.pgk, using the program 'Packages'.
-That will sign the installer with LEAP's developer certificates.
diff --git a/pkg/osx/quickpkg b/pkg/osx/quickpkg
new file mode 100755
index 00000000..a8d04982
--- /dev/null
+++ b/pkg/osx/quickpkg
@@ -0,0 +1,557 @@
+#!/usr/bin/python
+
+import argparse
+import string
+import os
+import subprocess
+import tempfile
+import shutil
+import stat
+
+# includes FoundationPlist since some apps store their Info.plist
+# as binary PropertyLists
+
+# FoundationPlist:
+
+# Copyright 2009-2014 Greg Neagle.
+#
+# Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""FoundationPlist.py -- a tool to generate and parse MacOSX .plist files.
+
+This is intended as a drop-in replacement for Python's included plistlib,
+with a few caveats:
+ - readPlist() and writePlist() operate only on a filepath,
+ not a file object.
+ - there is no support for the deprecated functions:
+ readPlistFromResource()
+ writePlistToResource()
+ - there is no support for the deprecated Plist class.
+
+The Property List (.plist) file format is a simple XML pickle supporting
+basic object types, like dictionaries, lists, numbers and strings.
+Usually the top level object is a dictionary.
+
+To write out a plist file, use the writePlist(rootObject, filepath)
+function. 'rootObject' is the top level object, 'filepath' is a
+filename.
+
+To parse a plist from a file, use the readPlist(filepath) function,
+with a file name. It returns the top level object (again, usually a
+dictionary).
+
+To work with plist data in strings, you can use readPlistFromString()
+and writePlistToString().
+"""
+
+from Foundation import NSData, \
+ NSPropertyListSerialization, \
+ NSPropertyListMutableContainersAndLeaves, \
+ NSPropertyListXMLFormat_v1_0
+
+
+class FoundationPlistException(Exception):
+ '''Base error for this module'''
+ pass
+
+
+class NSPropertyListSerializationException(FoundationPlistException):
+ '''Read error for this module'''
+ pass
+
+
+class NSPropertyListWriteException(FoundationPlistException):
+ '''Write error for this module'''
+ pass
+
+
+# private functions
+def _dataToPlist(data):
+ '''low-level function that parses a data object into a propertyList object'''
+ darwin_vers = int(os.uname()[2].split('.')[0])
+ if darwin_vers > 10:
+ (plistObject, plistFormat, error) = (
+ NSPropertyListSerialization.propertyListWithData_options_format_error_(
+ data, NSPropertyListMutableContainersAndLeaves, None, None))
+ else:
+ # 10.5 doesn't support propertyListWithData:options:format:error:
+ # 10.6's PyObjC wrapper for propertyListWithData:options:format:error:
+ # is broken
+ # so use the older NSPropertyListSerialization function
+ (plistObject, plistFormat, error) = (
+ NSPropertyListSerialization.propertyListFromData_mutabilityOption_format_errorDescription_(
+ data, NSPropertyListMutableContainersAndLeaves, None, None))
+ if plistObject is None:
+ if error is None:
+ error = "Plist data is invalid and could not be deserialized."
+ raise NSPropertyListSerializationException(error)
+ else:
+ return plistObject
+
+
+def _plistToData(plistObject):
+ '''low-level function that creates NSData from a plist object'''
+ darwin_vers = int(os.uname()[2].split('.')[0])
+ if darwin_vers > 10:
+ (data, error) = (
+ NSPropertyListSerialization.dataWithPropertyList_format_options_error_(
+ plistObject, NSPropertyListXMLFormat_v1_0, 0, None))
+ else:
+ # use the older NSPropertyListSerialization function on 10.6 and 10.5
+ (data, error) = (
+ NSPropertyListSerialization.dataFromPropertyList_format_errorDescription_(
+ plistObject, NSPropertyListXMLFormat_v1_0, None))
+ if data is None:
+ if error is None:
+ error = "Property list invalid for format."
+ raise NSPropertyListSerializationException(error)
+ return data
+
+
+# public functions
+def readPlist(filepath):
+ '''Read a .plist file from filepath. Return the unpacked root object
+ (which is usually a dictionary).'''
+ try:
+ data = NSData.dataWithContentsOfFile_(filepath)
+ except NSPropertyListSerializationException, error:
+ # insert filepath info into error message
+ errmsg = (u'%s in %s' % (error, filepath))
+ raise NSPropertyListSerializationException(errmsg)
+ return _dataToPlist(data)
+
+
+def readPlistFromString(aString):
+ '''Read a plist data from a string. Return the root object.'''
+ data = buffer(aString)
+ return _dataToPlist(data)
+
+
+def writePlist(plistObject, filepath):
+ '''Write 'plistObject' as a plist to filepath.'''
+ plistData = _plistToData(plistObject)
+ if plistData.writeToFile_atomically_(filepath, True):
+ return
+ else:
+ raise NSPropertyListWriteException(
+ u"Failed to write plist data to %s" % filepath)
+
+
+def writePlistToString(plistObject):
+ '''Create a plist-formatted string from plistObject.'''
+ return str(_plistToData(plistObject))
+
+
+#
+# quickpkg
+#
+
+
+quickpkg_version = '0.5'
+supported_extensions = ['dmg', 'app', 'zip']
+
+
+# modeled after munkiimport but to build a pkg
+
+
+def logger(log, v=0):
+ if args.verbosity >= v:
+ print log
+
+
+def cmdexec(command, stdin=''):
+ """Execute a command."""
+ # if 'command' is a string, split the string into components
+ if isinstance(command, str):
+ command = command.split()
+
+ proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
+ (stdout, stderr) = proc.communicate(stdin)
+
+ logger("cmdexec: %s, result: %s, error: %s" % (command, stdout, stderr), 3)
+
+ # strip trailing whitespace, which would mess with string comparisons
+ return {"return_code": proc.returncode, "stderr": stderr.rstrip(), "stdout": stdout.rstrip()}
+
+
+# from munkicommons.py
+def getFirstPlist(textString):
+ """Gets the next plist from a text string that may contain one or
+ more text-style plists.
+ Returns a tuple - the first plist (if any) and the remaining
+ string after the plist"""
+ plist_header = '<?xml version'
+ plist_footer = '</plist>'
+ plist_start_index = textString.find(plist_header)
+ if plist_start_index == -1:
+ # not found
+ return ("", textString)
+ plist_end_index = textString.find(
+ plist_footer, plist_start_index + len(plist_header))
+ if plist_end_index == -1:
+ # not found
+ return ("", textString)
+ # adjust end value
+ plist_end_index = plist_end_index + len(plist_footer)
+ return (textString[plist_start_index:plist_end_index],
+ textString[plist_end_index:])
+
+
+def dmg_has_sla(dmgpath):
+ has_sla = False
+ imageinfo_cmd = ['/usr/bin/hdiutil', 'imageinfo', dmgpath, '-plist']
+ result = cmdexec(imageinfo_cmd)
+ if result["return_code"] != 0:
+ print "error getting imageinfo! %s, %s" % (result["return_code"], result["stderr"])
+ return False
+ result_plist = result["stdout"]
+ imageinfo_dict = readPlistFromString(result_plist)
+ properties = imageinfo_dict.get('Properties')
+ if properties is not None:
+ has_sla = properties.get('Software License Agreement', False)
+ return has_sla
+
+
+def attachdmg(dmgpath):
+ global dmg_was_mounted
+ info_cmd = ["hdiutil", "info", "-plist"]
+ info_result = cmdexec(info_cmd)
+ if info_result["return_code"] == 0:
+ # parse the plist output
+ (theplist, alltext) = getFirstPlist(info_result["stdout"])
+ info_dict = readPlistFromString(theplist)
+ volpaths = []
+ if "images" in info_dict.keys():
+ for y in info_dict["images"]:
+ if "image-path" in y.keys():
+ if os.path.samefile(y["image-path"], dmgpath):
+ for x in y.get("system-entities"):
+ if "mount-point" in x.keys():
+ volpaths.append(x["mount-point"])
+ dmg_was_mounted = True
+ return volpaths
+ else:
+ print "error getting hdiutil info"
+ print "(%d, %s)" % (info_result["returncode"], info_result["stderr"])
+ cleanup_and_exit(1)
+
+ attachcmd = ["/usr/bin/hdiutil",
+ "attach",
+ dmgpath,
+ "-mountrandom",
+ "/private/tmp",
+ "-plist",
+ "-nobrowse"]
+ if dmg_has_sla(dmgpath):
+ stdin = "Y\n"
+ print "NOTE: Disk image %s has a license agreement!" % dmgpath
+ else:
+ stdin = ''
+ result = cmdexec(attachcmd, stdin)
+ if result["return_code"] == 0:
+ # parse the plist output
+ (theplist, alltext) = getFirstPlist(result["stdout"])
+ resultdict = readPlistFromString(theplist)
+ volpaths = []
+ for x in resultdict["system-entities"]:
+ if x["potentially-mountable"]:
+ if x["volume-kind"] == 'hfs':
+ volpaths.append(x["mount-point"])
+ # return the paths to mounted volume
+ return volpaths
+ else:
+ print "error mounting disk image"
+ print "(%d, %s)" % (result["returncode"], result["stderr"])
+ cleanup_and_exit(1)
+
+
+def detachpaths(volpaths):
+ for x in volpaths:
+ if os.path.exists(x):
+ if os.path.ismount(x):
+ detachcmd = ["/usr/bin/hdiutil", "detach", x]
+ cmdexec(detachcmd)
+
+
+def finditemswithextension(dirpath, item_extension):
+ foundapps = []
+ if os.path.exists(dirpath):
+ for x in os.listdir(dirpath):
+ (item_basename, item_extension) = os.path.splitext(x)
+ item_extension = string.lstrip(item_extension, '.')
+ if item_extension == 'app':
+ foundapps.append(os.path.join(dirpath, x))
+ else:
+ print "path %s does not exist" % dirpath
+ cleanup_and_exit(1)
+ return foundapps
+
+
+def appNameAndVersion(app_path):
+ info_path = os.path.join(app_path, "Contents/Info.plist")
+ if not os.path.exists(info_path):
+ print "Application at path %s does not have Info.plist" % app_path
+ # TODO: cleanup volumes here
+ cleanup_and_exit(1)
+ info_plist = readPlist(info_path)
+ app_name = info_plist.get("CFBundleName")
+ if app_name is None:
+ app_name = info_plist.get("CFBundleDisplayName")
+ if app_name is None:
+ (app_name, app_ext) = os.path.splitext(os.path.basename(app_path))
+ app_identifier = info_plist.get("CFBundleIdentifier")
+ app_version = info_plist.get("CFBundleShortVersionString")
+ if app_version is None:
+ app_version = info_plist.get("CFBundleVersion")
+ return (app_name, app_identifier, app_version)
+
+
+def cleanup_and_exit(returncode):
+ global dmgvolumepaths
+ global dmg_was_mounted
+ global tmp_path
+
+ if args.clean:
+ if not dmg_was_mounted:
+ detachpaths(dmgvolumepaths)
+ if tmp_path is not None:
+ shutil.rmtree(tmp_path)
+ exit(returncode)
+
+
+if __name__ == "__main__":
+
+ parser = argparse.ArgumentParser(description="""Attempts to build a pkg from the input.
+ Installer item can be a dmg, zip, or app.""",
+ epilog="""Example: quickpkg /path/to/installer_item""")
+
+ # takes a path as input
+ parser.add_argument('item_path', help="path to the installer item")
+
+ scripts_group = parser.add_argument_group('Installation Scripts',
+ '''These options will set the installation scripts. You pass an entire folder of scripts,
+ just like the option of `pkgbuild` or you can give a file for the preinstall or postinstall
+ scripts respectively. If you give both the --scripts and either one or both of --preinstall
+ and --postinstall, quickpkg will attempt to merge, but throw an error if it cannot.''')
+ scripts_group.add_argument('--scripts', help="path to a folder with scripts")
+ scripts_group.add_argument('--preinstall', '--pre', help="path to the preinstall script")
+ scripts_group.add_argument('--postinstall', '--post', help="path to the postinstall script")
+
+ parser.add_argument('--ownership', choices=['recommended', 'preserve', 'preserve-other'],
+ help="will be passed through to pkgbuild")
+ parser.add_argument('--output', '--out', '-o',
+ help='''path where the package file will be created. If you give the full filename
+ then you can use '{name}', '{version}' and '{identifier}' as placeholders.
+ If this is a directory, then the
+ package will be created with the default filename {name}-{version}.pkg''')
+
+ parser.add_argument('--clean', dest='clean', action='store_true', help="clean up temp files (DEFAULT)")
+ parser.add_argument('--no-clean', dest='clean', action='store_false', help=" do NOT clean up temp files")
+ parser.set_defaults(clean=True)
+
+ parser.add_argument('--relocatable', dest='relocatable', action='store_true',
+ help="sets BundleIsRelocatable in the PackageInfo to true")
+ parser.add_argument('--no-relocatable', dest='relocatable', action='store_false',
+ help="sets BundleIsRelocatable in the PackageInfo (DEFAULT is false)")
+ parser.set_defaults(relocatable=False)
+
+
+ parser.add_argument("-v", "--verbosity", action="count", default=0, help="controls amount of logging output (max -vvv)")
+ parser.add_argument('--version', help='prints the version', action='version', version=quickpkg_version)
+
+ args = parser.parse_args()
+
+ # remove trailing '/' from path
+ item_path = string.rstrip(args.item_path, '/')
+
+ if item_path.startswith('~'):
+ item_path = os.path.expanduser(item_path)
+ item_path = os.path.abspath(item_path)
+
+ # get file extension
+ (item_basename, item_extension) = os.path.splitext(item_path)
+ item_extension = string.lstrip(item_extension, '.')
+
+ # is extension supported
+ if item_extension not in supported_extensions:
+ print ".%s is not a supported extension!" % item_extension
+ exit(1)
+
+ foundapps = []
+
+ # if item is an app, just pass it on
+ if item_extension == 'app':
+ if not os.path.exists(item_path):
+ print "This does not seem to be an Application!"
+ exit(1)
+ foundapps.append(item_path)
+
+ dmgvolumepaths = []
+ tmp_path = None
+ dmg_was_mounted = False
+ tmp_scripts_path = None
+ tmp_path = tempfile.mkdtemp()
+ payload_path = os.path.join(tmp_path, "payload")
+ os.makedirs(payload_path)
+
+ # if item is a dmg, mount it and find useful contents
+ if item_extension == 'dmg':
+ dmgvolumepaths = attachdmg(item_path)
+ for x in dmgvolumepaths:
+ moreapps = finditemswithextension(x, 'app')
+ foundapps.extend(moreapps)
+ if len(foundapps) == 0:
+ print "Could not find an application!"
+ cleanup_and_exit(1)
+ elif len(foundapps) > 1:
+ print "Found too many Applications! Can't decide!"
+ print foundapps
+ cleanup_and_exit(1)
+
+ # if item is zip, unzip to tmp location and find useful contents
+ if item_extension == 'zip':
+ unarchive_path = os.path.join(tmp_path, "unarchive")
+ unzip_cmd = ["/usr/bin/unzip", "-d", unarchive_path, item_path]
+ result = cmdexec(unzip_cmd)
+ if result["return_code"] != 0:
+ print "An error occured while unzipping:"
+ print "%d, %s" % (result["return_code"], result["stderr"])
+ cleanup_and_exit(1)
+ foundapps = finditemswithextension(unarchive_path, 'app')
+ if len(foundapps) == 0:
+ print "Could not find an application!"
+ cleanup_and_exit(1)
+ elif len(foundapps) > 1:
+ print "Found too many Applications! Can't decide!"
+ print foundapps
+ cleanup_and_exit(1)
+
+ logger("Found application: %s" % foundapps[0], 1)
+
+ # copy found app to payload folder
+ app_name = os.path.basename(foundapps[0])
+ app_path = os.path.join(payload_path, app_name)
+ shutil.copytree(foundapps[0], app_path)
+
+ # extract version and other metadata
+ (app_name, app_identifier, app_version) = appNameAndVersion(app_path)
+
+ logger("Name: %s, ID: %s, Version: %s" % (app_name, app_identifier, app_version), 1)
+
+ # create the component plist
+ component_plist = os.path.join(tmp_path, app_identifier) + ".plist"
+ analyzecmd = ["/usr/bin/pkgbuild",
+ "--analyze",
+ "--root", payload_path,
+ "--identifier", app_identifier,
+ "--version", app_version,
+ "--install-location", "/Applications",
+ component_plist]
+ result = cmdexec(analyzecmd)
+
+ logger(result["stdout"], 1)
+ if result["return_code"] != 0:
+ print "Error Code: %d " % result["return_code"]
+ print result["stderr"]
+ cleanup_and_exit(1)
+
+ if not args.relocatable:
+ # read and change component plist
+ components = readPlist(component_plist)
+ # component plist is an array of components
+ for bundle in components:
+ if "BundleIsRelocatable" in bundle.keys():
+ bundle["BundleIsRelocatable"] = False
+ writePlist(components, component_plist)
+
+ pkg_name = "{name}-{version}.pkg"
+ if args.output:
+ if os.path.isdir(args.output):
+ pkg_path = os.path.join(args.output, pkg_name)
+ else:
+ pkg_path = args.output
+ else:
+ pkg_path = pkg_name
+ nospace_app_name = app_name.replace(' ', '') # remove spaces
+ pkg_path = pkg_path.format(name=nospace_app_name, version=app_version, identifier=app_identifier)
+
+ if not pkg_path.endswith('pkg'):
+ pkg_path += '.pkg'
+
+ # run pkgutil to build result
+ pkgcmd = ["/usr/bin/pkgbuild",
+ "--root", payload_path,
+ "--component-plist", component_plist,
+ "--identifier", app_identifier,
+ "--version", app_version,
+ "--install-location", "/Applications",
+ pkg_path]
+
+ if args.scripts and not os.path.exists(args.scripts):
+ print "scripts folder %s does not exist!" % args.scripts
+ cleanup_and_exit(1)
+
+ if args.postinstall or args.preinstall:
+ tmp_scripts_path = os.path.join(tmp_dir, "scripts")
+ os.makedirs(tmp_scripts_path)
+
+ if args.scripts:
+ logger("copying %s to tmp scripts folder %s" % (args.scripts, tmp_scripts_path), 1)
+ shutil.rmtree(tmp_scripts_path)
+ shutil.copytree(args.scripts, tmp_scripts_path)
+ if args.postinstall:
+ if not os.path.exists(args.postinstall):
+ print "postinstall file %s does not exist!" % args.postinstall
+ cleanup_and_exit(1)
+ postinstall_path = os.path.join(tmp_scripts_path, "postinstall")
+ if os.path.exists(postinstall_path):
+ print "postinstall script already exists in %s" % args.scripts
+ cleanup_and_exit(1)
+ logger("copying %s to %s" % (args.postinstall, postinstall_path), 1)
+ shutil.copy2(args.postinstall, postinstall_path)
+ os.chmod(postinstall_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
+ stat.S_IRGRP | stat.S_IXGRP |
+ stat.S_IROTH | stat.S_IXOTH)
+ if args.preinstall:
+ if not os.path.exists(args.preinstall):
+ print "preinstall file %s does not exist!" % args.preinstall
+ cleanup_and_exit(1)
+ preinstall_path = os.path.join(tmp_scripts_path, "preinstall")
+ if os.path.exists(preinstall_path):
+ print "preinstall script already exists in %s" % args.scripts
+ cleanup_and_exit(1)
+ logger("copying %s to %s" % (args.preinstall, preinstall_path), 1)
+ shutil.copy2(args.preinstall, preinstall_path)
+ os.chmod(preinstall_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
+ stat.S_IRGRP | stat.S_IXGRP |
+ stat.S_IROTH | stat.S_IXOTH)
+
+ if tmp_scripts_path:
+ logger("scripts path: %s" % tmp_scripts_path, 1)
+ pkgcmd.extend(["--scripts", tmp_scripts_path])
+ elif args.scripts:
+ logger("scripts path: %s" % args.scripts, 1)
+ pkgcmd.extend(["--scripts", args.scripts])
+
+ if args.ownership:
+ pkgcmd.extend(["--ownership", args.ownership])
+
+ result = cmdexec(pkgcmd)
+
+ logger(result["stdout"], 1)
+ if result["return_code"] != 0:
+ print "Error Code: %d " % result["return_code"]
+ print result["stderr"]
+ else:
+ print pkg_path
+
+ cleanup_and_exit(0)
diff --git a/pkg/osx/installer/post-inst.sh b/pkg/osx/scripts/postinstall
index 0202323a..9c2176b2 100755
--- a/pkg/osx/installer/post-inst.sh
+++ b/pkg/osx/scripts/postinstall
@@ -2,3 +2,5 @@
# Bitmask Post-Instalation script
cp se.leap.bitmask-helper.plist /Library/LaunchDaemons/
launchctl load /Library/LaunchDaemons/se.leap.bitmask-helper.plist || echo "Already loaded, skipping..."
+echo `date` "::Bitmask post-installation script succeeded." >> /tmp/bitmask-install.log
+exit 0
diff --git a/pkg/osx/installer/pre-inst.sh b/pkg/osx/scripts/preinstall
index 1651a221..222922cf 100755
--- a/pkg/osx/installer/pre-inst.sh
+++ b/pkg/osx/scripts/preinstall
@@ -1,3 +1,5 @@
#!/bin/sh
-# Bitmask Post-Instalation script
+# Bitmask Pre-Instalation script
[[ -f /Library/LaunchDaemons/se.leap.bitmask-helper.plist ]] && launchctl unload /Library/LaunchDaemons/se.leap.bitmask-helper.plist
+echo `date` "::Bitmask pre-installation script succeeded." >> /tmp/bitmask-install.log
+exit 0
diff --git a/pkg/osx/installer/se.leap.bitmask-helper.plist b/pkg/osx/scripts/se.leap.bitmask-helper.plist
index 4428f131..4428f131 100644
--- a/pkg/osx/installer/se.leap.bitmask-helper.plist
+++ b/pkg/osx/scripts/se.leap.bitmask-helper.plist
diff --git a/pkg/pyinst/build.mk b/pkg/pyinst/build.mk
index b6dea151..2ad224b4 100644
--- a/pkg/pyinst/build.mk
+++ b/pkg/pyinst/build.mk
@@ -47,7 +47,7 @@ bundle_osx_helpers:
mkdir -p $(DIST_VERSION)/apps/helpers
cp src/leap/bitmask/vpn/helpers/osx/bitmask-helper $(DIST_VERSION)/apps/helpers/
cp src/leap/bitmask/vpn/helpers/osx/bitmask.pf.conf $(DIST_VERSION)/apps/helpers/
- cp pkg/osx/installer/se.leap.bitmask-helper.plist $(DIST_VERSION)/apps/helpers/
+ cp pkg/osx/scripts/se.leap.bitmask-helper.plist $(DIST_VERSION)/apps/helpers/
cp -r pkg/osx/daemon $(DIST_VERSION)/apps/helpers/
cp -r pkg/osx/openvpn $(DIST_VERSION)/apps/helpers/