[
  {
    "path": ".gitignore",
    "content": "# generic\n*~\n*#\n*._*\n*.log\n*.log.*\n*.pid\n\n# apple\n.DS_Store\n*~.nib\n\n# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n\n# C extensions\n*.so\n\n# Distribution / packaging\n.Python\nenv/\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib/\nlib64/\nparts/\nsdist/\nvar/\n*.egg-info/\n.installed.cfg\n*.egg\n\n# PyInstaller\n#  Usually these files are written by a python script from a template\n#  before PyInstaller builds the exe, so as to inject date/other infos into it.\n*.manifest\n*.spec\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.coverage\n.cache\nnosetests.xml\ncoverage.xml\n\n# Translations\n*.mo\n*.pot\n\n# Sphinx documentation\ndocs/_build/\n\n# PyBuilder\ntarget/\n\n# Development\n.*.sw[po]\n*.sublime-project\n*.sublime-workspace\n.project\n.pydevproject\n.ropeproject\n*.sass-cache\n.aws.env\n.codeintel\n.coverage\n.noseids\n.semantic.cache\n.settings\n.idea\n.realsync\n*.tm_build_errors\ntmtags\n*.iml\n\n# iresign version\nisign/version.json\n\n# iresign temp files\nEntitlements.plist\nstage\nout.app\nout.ipa\n\n# all credentials\n*.pem\n*.p12\n*.mobileprovision\n# except these\n!apple_credentials/applecerts.pem\n!tests/credentials/test.key.pem\n!tests/credentials/test.cert.pem\n!tests/credentials/test.mobileprovision\n!tests/credentials_std_names/certificate.pem\n!tests/credentials_std_names/isign.mobileprovision\n!tests/credentials_std_names_2/key.pem\n!tests/credentials_std_names_2/certificate.pem\n!tests/credentials_std_names_2/isign.mobileprovision\n"
  },
  {
    "path": "CONDUCT.md",
    "content": "## Code of Conduct\n\n### What is this code of conduct for?\n\n`isign` is a piece of technology, but **the core of the `isign` community is the people in it**. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, gender identity and expression, sexual orientation, ability, physical appearance, body size, race, age, socioeconomic status, religion (or lack thereof), or other marginalized aspect of comunity members. We expect all members of the `isign` community to abide by this Code of Conduct whenever interacting in `isign` venues (pull requests, GitHub issues, 1-1 or group chat, meetups, conferences, etc...)\n\n### Examples of inappropriate behavior\n\nBecause we come from a variety of backgrounds, we don't want to assume that everyone has the same assumptions about what is and isn't appropriate. Here are some examples of inappropriate behavior that are incompatible with our community's ethos:\n\n* Spamming, trolling, intentionally disrupting conversations, or irrelevant solicitation or advertisement\n* Making demeaning or discriminatory comments\n* Making negative assumptions about someone's background, abilities, or intentions\n* Harassing or stalking individuals (online or in person)\n* Giving someone unwelcome sexual attention or making unwelcome physical contact (in the case of an IRL event)\n* Sharing sexual images or using sexually explicit language\n\nIn general: treat others how you would like to be treated, were you in their place. Don't be a jerk. _Do_ ask questions. _Do_ keep conflicts productively focused on technical issues. _Do_ think before you speak; remember that what is perceived as a funny witticism in your group of friends might be hurtful or reinforce hurtful stereotypes in the context of our diverse online community. _Do_ remember that we are all people, not robots, and all equally deserving of sensitivity and respect. (If and when robots join our community, let's treat them with respect too!)\n\n### What will organizers do about inappropriate behavior?\n\nIf we notice you doing or saying something inappropriate, an organizer will explain why it's inappropriate and ask you to stop. We won't demonize or vilify you. But please do stop the inappropriate behavior so we can get back to writing and discussing code in a safe environment. If you have philosophical disagreements about what's actually inappropriate, please take them to a separate public or private conversation with an `isign` maintainer so we don't turn pull requests into an ethics debate.\n\nIf you keep doing unacceptable things, we'll likely ban you, report you to GitHub, or take other appropriate action.\n\n### What if I see or am subject to what feels like inappropriate behavior?\n\nLet us know! Please notify a community organizer as soon as possible. Full contact information is listed in the [Contact Info](#contact-info) section of this document. All communications will be kept strictly confidential, unless otherwise required by law. No issue will be considered too inconsequential or unimportant for us to have a conversation about.\n\n### Contact Info\n\nIf you need to report an incident, please contact any of the following organizers directly:\n\n* Neil Kandalgaonkar [email](mailto:neilk@neilk.net) [twitter](https://twitter.com/flipzagging/)\n* Jonathan Lipps [email](mailto:jlipps@saucelabs.com) [twitter](https://twitter.com/jlipps)\n\n### Credit, License, and Attribution\n\nThis Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/).\n\nIt's inspired among other things by:\n* [Citizen Code of Conduct](http://citizencodeofconduct.org/)\n* [npmjs](https://www.npmjs.com/policies/conduct)\n* [Geek Feminism](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy)\n* [Ashe Dryden](http://www.ashedryden.com/blog/codes-of-conduct-101-faq)\n* [Model View Culture](https://modelviewculture.com/issues/events)\n* [Open Source & Feelings](http://osfeels.com/conduct).\n"
  },
  {
    "path": "INSTALL.sh",
    "content": "#!/bin/bash\n\nset -e\n\nREQUIRED_OPENSSL_VERSION=\"1.0.1\"\nREQUIRED_PIP_VERSION=\"7.0.0\"\nBREW_USER=\"unknown\"\nDEVELOP=false\n\nif [[ \"$1\" == 'develop' ]]; then\n    DEVELOP=true\nfi\n\n\nabort_install() {\n    warn \"Aborting the install. If you want to install prerequisites\"\n    warn \"manually, see PREREQUISITES.rst.\"\n    exit 0;\n}\n\nwarn() {\n    echo \"$@\" 1>&2;\n}\n\ntrim() {\n    # has the side effect of trimming whitespace\n    echo \"$@\" | xargs\n}\n\nget_ok_to_upgrade() {\n    warn \"This script may install or upgrade the following software:\"\n    warn \"  - brew\";\n    warn \"  - openssl\";\n    warn \"  - libffi\"\n    warn \"  - python and pip\";\n    warn \"  - libimobiledevice and related utilities\";\n    read -p \"Okay to continue? [Y/n]\" -n 1 -r \n    warn \" \" \n    warn \" \" \n    if [[ $REPLY =~ ^[Nn]$ ]]; then\n        abort_install\n    fi\n}\n\n# given arguments like 1.0.2e, 3, returns \"2\"\nget_version_part() {\n    local version=$1\n    local part=$2\n    echo $version | cut -f $part -d '.' | sed 's/[^0-9]//g'\n}\n\ncheck_version() {\n    local required=$1;\n    local given=$2;\n    local i\n    for i in 1 2 3; do\n        local required_part=$(get_version_part $required $i);\n        local given_part=$(get_version_part $given $i);\n        if [[ $given_part -lt $required_part ]]; then\n            return 1;\n        fi\n    done;\n    return 0;\n}\n\nexists() {\n    # warn \"checking for existence of $1\"\n    which $1 > /dev/null\n}\n\n\nopenssl_version_ok() {\n    local openssl_path=$1\n    warn \"Trying to check if $openssl_path openssl version is okay...\"\n    if [[ -e $openssl_path ]]; then\n        local openssl_version=$($openssl_path version | cut -f 2 -d ' ');\n        warn \"Found $openssl_path version $openssl_version.\"\n        if check_version $REQUIRED_OPENSSL_VERSION $openssl_version; then\n            warn \"$openssl_path version looks okay.\"\n            return 0;\n        fi\n    fi\n    warn \"$openssl_path version was not okay!\"\n    return 1;\n}\n\nsetup_brew() {\n    if exists brew; then\n        warn \"You seem to have brew.\"\n    else\n        # This is what https://brew.sh recommends...\n        # Installing straight from a URL? What could go wrong?\n        local homebrew_install_url=\"https://raw.githubusercontent.com/Homebrew/install/master/install\"\n        warn \"We need to install brew...\"\n        warn \"Okay to install via ruby script at this URL?\"\n        warn \"  $homebrew_install_url\";\n        warn \" \"\n        read -p \"Okay to continue? [Y/n]\" -n 1 -r \n        warn \" \" \n        warn \" \" \n        if [[ $REPLY =~ ^[Nn]$ ]]; then\n            abort_install\n        fi\n        ruby -e \"$(curl -fsSL $homebrew_install_url)\";\n    fi\n    # which user owns the Cellar? We'll need this to install things...\n    BREW_USER=$(stat -f '%Su' `brew --cellar`)\n    warn \"brew's stuff seems to be owned by $BREW_USER...\"\n    return 0;\n}\n\n# Commands that write to brew's Cellar need to not be root\nbrew_write() {\n    local command=$1 \n    local package=$2\n    if [[ $EUID -eq 0 ]]; then\n        sudo -u $BREW_USER brew $command $package\n    else\n        brew $command $package\n    fi\n}\n\n# some brew packages have this in machine readable form\n# but not all :(\nbrew_get_flags() {\n    local package=$1\n    local flags=$2\n    brew info $package | grep $flags | awk '{print $2}'\n}\n\n# check if a program is managed by brew\n# it might be a symlink like /usr/local/bin/openssl, pointing to somewhere in the Cellar\nis_brew_program() {\n    readlink `which $1` | grep `brew --prefix` >/dev/null;\n}\n\nmac_setup_openssl() {\n    # warn \"start mac_setup_openssl\"\n       \n    # if the currently installed openssl doesn't meet our requirements,\n    # install or upgrade with brew\n    local openssl_path=$(which openssl)\n    if [[ -n $openssl_path ]]; then\n        if ! openssl_version_ok $openssl_path; then\n           brew_setup_openssl\n        fi\n    fi\n\n    # At this point, the openssl version is okay. It may or may not\n    # be a brew installed program. If it is, set up some compilation \n    # library paths. We append to $LDFLAGS and $CPPFLAGS because some other\n    # things put flags in there too.\n    if is_brew_program openssl; then\n        openssl_ldflags=$(brew_get_flags openssl LDFLAGS)\n        export LDFLAGS=$(trim \"$LDFLAGS $openssl_ldflags\")\n        openssl_cppflags=$(brew_get_flags openssl CPPFLAGS)\n        export CPPFLAGS=$(trim \"$CPPFLAGS $openssl_cppflags\")\n        # Some stackoverflow answers use this too? \n        export CFLAGS=$CPPFLAGS\n    fi\n\n    return 0;\n}\n\n\nbrew_setup_openssl() {\n    # So now we know there either wasn't an openssl, or it wasn't\n    # a version good enough. Time for brew!   \n \n    # is the brew openssl installed? if not, install\n    brew_openssl_path=$(brew list openssl | grep -e '/openssl$')\n    # warn \"brew openssl path = $brew_openssl_path\"\n    if [[ -z $brew_openssl_path ]]; then\n        warn \"Installing openssl...\"\n        brew_write install openssl\n        brew_openssl_path=$(brew list openssl | grep -e '/openssl$')\n    fi \n    # warn \"brew openssl path = $brew_openssl_path\"\n\n    # is the brew openssl the right version? if not, upgrade\n    if ! openssl_version_ok $brew_openssl_path; then\n        warn \"Upgrading openssl...\"\n        brew_write upgrade openssl\n        brew_openssl_path=$(brew list openssl | grep -e '/openssl$')\n    fi\n    # warn \"okay by now $brew_openssl_path should be an acceptable openssl\"\n\n    # for various reasons, brew will refuse to simultaneously \n    # be root and link the brew openssl binary somewhere useful. \n    # So we do it manually. We assume that the brew --prefix will be \n    # in the user's $PATH, and will take precedence over system openssl. \n    brew_link_path=$(brew --prefix)/bin/openssl\n    # warn \"brew link path is $brew_link_path\"\n    if [[ -e brew_link_path ]]; then\n        # warn \"removing existing link\"\n        rm brew_link_path;\n    fi\n    warn \"Linking $brew_openssl_path $brew_link_path.\"\n    ln -s $brew_openssl_path $brew_link_path\n\n    # let's see if we succeeded: the openssl in our path should now be ready!\n    new_openssl_path=$(which openssl)\n    # warn \"new path is $new_openssl_path\"\n    if ! openssl_version_ok $new_openssl_path; then\n        warn \"We tried to install an openssl >$MINIMUM_OPENSSL_VERSION, but we failed.\"\n        warn \"Check if $brew_link_path is in your \\$PATH ($PATH).\"\n        return 1\n    fi\n    # warn \"success, finally\"\n\n    return 0;\n}\n\nmac_setup_libffi() {\n    warn \"Checking for libffi...\"\n    if ! brew list libffi 2>/dev/null >/dev/null; then\n        warn \"Nope, no libffi. Installing...\"\n        brew_write install libffi\n    fi\n    # set up some compilation library paths (we'll need it later...)\n    local libffi_ldflags=$(brew_get_flags libffi LDFLAGS)\n    export LDFLAGS=$(trim \"$LDFLAGS $libffi_ldflags\")\n}\n\nmac_setup_python() {\n    if exists pip; then\n        pip_version=$(pip --version | awk '{ print $2 }')\n        if check_version $REQUIRED_PIP_VERSION $pip_version; then\n            warn \"pip version $pip_version looks okay.\"\n            return 0;\n        fi\n    fi\n    brew_write install python\n}\n\nmac_setup_libimobiledevice() {\n    if exists ideviceinstaller; then\n        return 0;\n    fi\n    brew_write install libimobiledevice\n}\n\nmac_setup() {\n    get_ok_to_upgrade\n    setup_brew\n    mac_setup_openssl\n    mac_setup_libffi\n    mac_setup_python\n    mac_setup_libimobiledevice\n}\n\nlinux_setup() {\n    #apt-get install ideviceinstaller\n    #apt-get install libimobiledevice-utils\n    echo \"Skipping apt-get installs, we use yum\"\n}\n\n\nunamestr=`uname`\nif [[ \"$unamestr\" == 'Darwin' ]]; then\n    mac_setup\nelif [[ \"$unamestr\" == 'Linux' ]]; then\n    linux_setup\nelse\n    warn \"Sorry, I don't know how to install on $unamestr.\";\n    exit 1;\nfi;\n\necho \"--- Flags ---\"\necho \"LDFLAGS=$LDFLAGS\"\necho \"CPPFLAGS=$CPPFLAGS\"\necho \"CFLAGS=$CFLAGS\"\necho\n\nif [[ \"$DEVELOP\" == true ]]; then\n    python setup.py develop\nelse\n    python setup.py install\nfi\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "Copyright 2015 Sauce Labs\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "MANIFEST.in",
    "content": "include isign/version.json\ninclude isign/apple_credentials/applecerts.pem\ninclude isign/code_resources_template.xml\n"
  },
  {
    "path": "PKG-INFO",
    "content": "Name: isign\nVersion: 1.6.16\n"
  },
  {
    "path": "PREREQUISITES.rst",
    "content": "Prerequisites\n=============\n\nFor Linux or Mac platforms, the ``INSTALL.sh`` script should take care of \neverything you need.  \n\nIf you don't want to run that script on the machine where you want to re-sign apps, \nthis will explain what you need.\n\nFirst, on the machine where you're going to re-sign apps, ensure \n`openssl <https://www.openssl.org>`__ is at version 1.0.1 or better, like\nthis:\n\n.. code::\n\n  $ openssl version\n  OpenSSL 1.0.1 14 Mar 2012\n\nIf that looks okay, you can probably install. If not:\n\n.. _Linux:\n\nLinux\n~~~~~\n\nYou can probably easily update this with your package manager, such as \n``apt-get upgrade openssl``.\n\n.. _Mac OS X:\n\nMac OS X\n~~~~~~~~\n\nWith OS X 10.11 \"El Capitan\", Apple stopped shipping some programs, libraries, and \nheaders that we'll need. You can use `homebrew <http://brew.sh>`__ to install them:\n\n.. code::\n\n  $ brew install openssl libffi\n\nYou will also have to put ``brew``'s openssl into your path somehow, probably like this:\n\n.. code::\n  \n  $ brew list openssl\n  ... \n  /usr/local/Cellar/openssl/1.0.2e/bin/openssl    <-- you want this\n  ...\n\n  $ ln -s /usr/local/Cellar/openssl/1.0.2e/bin/openssl /usr/local/bin/openssl\n\nIf you really don't want to alter the default ``openssl``, you can put the path to brew's \n``openssl`` in an environment variable, ``$OPENSSL``, e.g.\n\n.. code::\n\n  $ export OPENSSL=/usr/local/Cellar/openssl/1.0.2e/bin/openssl \n\nIf ``isign`` sees that, it will use that for its ``openssl`` instead.\n\nAnyway, no matter how you install the binary, to complete the installation of ``isign``\nyou need to add some library paths to your environment. The procedure will \nlook something like this.\n\n.. code::\n  \n  $ brew info openssl\n  ...\n  build variables:\n\n    LDFLAGS:  -L/usr/local/opt/openssl/lib\n    CPPFLAGS: -I/usr/local/opt/openssl/include\n\n  $ brew info libffi\n  ...\n  build variables:\n\n    LDFLAGS:  -L/usr/local/opt/libffi/lib\n\nThen, take the flags from above, and put them into appropriate environment\nvariables:\n\n.. code::\n\n  $ export LDFLAGS=\"-L/usr/local/opt/openssl/lib -L/usr/local/opt/libffi/lib\"\n  $ export CPPFLAGS=\"-I/usr/local/opt/openssl/include\"\n\nFinally, be aware that the ``python`` that ships with Mac OS X doesn't have the package \nmanager ``pip``. You can probably use ``easy_install`` instead of ``pip``. Or, you can get a more\nup-to-date python with ``brew install python``.\n\nNow you're probably ready to install ``isign``. A simple ``pip install isign`` should succeed.\n"
  },
  {
    "path": "README.rst",
    "content": "isign\n=====\n\nA tool and library to re-sign iOS applications, without proprietary Apple software.\n\nFor example, an iOS app in development would probably only run on the developer's iPhone. \n``isign`` can alter the app so that it can run on another developer's iPhone.\n\nApple tools already exist to do this. But with ``isign``, now you can do this on operating\nsystems like Linux.\n\n\nTable of contents\n-----------------\n\n- `Installing`_\n- `How to get started`_\n- `How to use isign`_\n- `isign command line arguments`_\n- `Contributing`_\n- `More documentation`_\n- `Authors`_\n\n\n.. _Installing:\n\nInstalling\n----------\n\nLinux\n~~~~~\n\nThe latest version of ``isign`` can be installed via `PyPi <https://pypi.python.org/pypi/isign/>`__:\n\n.. code::\n\n  $ pip install isign\n\nMac OS X\n~~~~~~~~\n\nOn Mac OS X, there are a lot of prerequisites, so the ``pip`` method probably won't work.\nThe easiest method is to use ``git`` to clone the `source code repository <https://github.com/saucelabs/isign>`__ and \nrun the install script:\n\n.. code::\n\n  $ git clone https://github.com/saucelabs/isign.git\n  $ cd isign\n  $ sudo ./INSTALL.sh\n\n.. _How to get started:\n\nHow to get started\n------------------\n\nAll the libraries and tools that ``isign`` needs to run will work on both Linux \nand Mac OS X. However, you will need a Mac to export your Apple developer \ncredentials. \n\nIf you're like most iOS developers, credentials are confusing -- if so check out \nthe `documentation on credentials <https://github.com/saucelabs/isign/blob/master/docs/credentials.rst>`__ on Github.\n\nYou should have a key and certificate in \n`Keychain Access <https://en.wikipedia.org/wiki/Keychain_(software)>`__,\nand a provisioning profile associated with that certificate, that you \ncan use to sign iOS apps for one or more of your own iOS devices.\n\nIn Keychain Access, open the *Certificates*. Find the certificate you use to sign apps. \nRight click on it and export the key as a ``.p12`` file, let's say ``Certificates.p12``. If Keychain \nasks you for a password to protect this file, just leave it blank. \n\nNext, let's extract the key and certificate you need, into a standard PEM format.\n\n.. code::\n\n  $ isign_export_creds.sh ~/Certificates.p12\n\nIf you get prompted for a password, just press ``Return``.\n\nBy default, ``isign_export_creds.sh`` will put these files into ``~/.isign``, which is\nthe standard place to put ``isign`` configuration files.\n\nFinally, you need a provisioning profile from the Apple Developer Portal that uses\nthe same certificate. If you've never dealt with this, the provisioning profile is \nwhat tells the phone that you Apple has okayed you installing apps onto this particular phone.\n\nIf you develop with XCode, you might have a provisioning profile already. \nOn the Mac where you develop with XCode, try running the ``isign_guess_mobileprovision.sh`` script. \nIf you typically have only a few provisioning profiles and install on one phone, it might find it. \n\nAnyway, once you have a ``.mobileprovision`` file, move it to ``~/.isign/isign.mobileprovision``.\n\nThe end result should look like this:\n\n.. code::\n\n  $ ls -l ~/.isign\n  -r--r--r--    1 alice  staff  2377 Sep  4 14:17 certificate.pem\n  -r--r--r--    1 alice  staff  9770 Nov 23 13:30 isign.mobileprovision\n  -r--------    1 alice  staff  1846 Sep  4 14:17 key.pem\n\nAnd now you're ready to start re-signing apps!\n\n.. _How to use isign:\n\nHow to use isign\n----------------\n\nIf you've installed all the files in the proper locations above, then ``isign`` can be now invoked\non any iOS ``.app`` directory, or ``.ipa`` archive, or ``.app.zip`` zipped directory. For example:\n\n.. code::\n\n  $ isign -o resigned.ipa my.ipa\n  archived Ipa to /home/alice/resigned.ipa\n\nYou can also call it from Python:\n\n.. code:: python\n\n  from isign import isign\n\n  isign.resign(\"my.ipa\", output_path=\"resigned.ipa\")\n\n.. _isign command line arguments:\n\nisign command line arguments\n----------------------------\n\n.. code::\n\n  # Resigning by specifying all credentials, input file, and output file\n  $ isign -c /path/to/mycert.pem -k ~/mykey.pem -p path/to/my.mobileprovision \\\n          -o resigned.ipa original.ipa\n\n  # Resigning, with credentials under default filenames in ~/.isign - less to type!\n  $ isign -o resigned.ipa original.ipa\n\n  # Modify Info.plist properties in resigned app\n  $ isign -i CFBundleIdentifier=com.example.myapp,CFBundleName=MyApp -o resigned.ipa original.ipa\n\n  # Display Info.plist properties from an app as JSON\n  $ isign -d my.ipa\n\n  # Get help\n  $ isign -h\n\n**-a <path>, --apple-cert <path>**\n\nPath to Apple certificate in PEM format. This is already included in the library, so you will likely\nnever need it. In the event that the certificates need to be changed, See the `Apple Certificate documentation <docs/applecerts.rst>`__.\n\n**-c <path>, --certificate <path>**\n\nPath to your certificate in PEM format. Defaults to ``$HOME/.isign/certificate.pem``.\n\n**-d, --display**\n\nFor the application path, display the information property list (Info.plist) as JSON.\n\n**-h, --help**\n\nShow a help message and exit.\n\n**-i, --info**\n\nWhile resigning, add or update info in the application's information property list (Info.plist). \nTakes a comma-separated list of key=value pairs, such as \n``CFBundleIdentifier=com.example.app,CFBundleName=ExampleApp``. Use with caution!\nSee Apple documentation for `valid Info.plist keys <https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Introduction/Introduction.html>`_.\n\n**-k <path>, --key <path>**\n\nPath to your private key in PEM format. Defaults to ``$HOME/.isign/key.pem``.\n\n**-n <directory>, --credentials <directory>**\n\nEquivalent to:\n\n.. code::\n\n   -k <directory>/key.pem \n   -c <directory>/certificate.pem \n   -p <directory>/isign.mobileprovision\n\n**-o <path>, --output <path>**\n\nPath to write the re-signed application. Defaults to ``out`` in your current working directory.\n\n**-p <path>, --provisioning-profile <path>**\n\nPath to your provisioning profile. This should be associated with your certificate. Defaults to \n``$HOME/.isign/isign.mobileprovision``.\n\n**-v, --verbose**\n\nMore verbose logs will be printed to STDERR.\n\n**Application path**\n\nThe app to be resigned is specified on the command line after other arguments. The application path is \ntypically an IPA, but can also be a ``.app`` directory or even a zipped ``.app`` directory. When\nresigning, ``isign`` will always create an archive of the same type as the original.\n\n\n.. _Contributing:\n\nContributing\n------------\n\nSauce Labs open source projects have a `Code of Conduct <CONDUCT.md>`__. In short, we try to respect each other, \nlisten, and be helpful.\n\nDevelopment happens on `our Github repository <https://github.com/saucelabs/isign>`__. File an issue, or fork the code!\n\nYou'll probably want to create some kind of python virtualenv, so you don't have to touch your system python or its \nlibraries. `virtualenvwrapper <https://virtualenvwrapper.readthedocs.org/en/latest/>`__ is a good tool for this.\n\nThen, just do the following:\n\n.. code::\n\n  $ git clone https://github.com/saucelabs/isign.git\n  $ cd isign\n  $ dev/setup.sh \n  $ ./run_tests.sh\n\nIf the tests don't pass please `file an issue <https://github.com/saucelabs/isign/issues>`__. Please keep the tests up to date as you develop.\n\nNote: some tests require Apple's\n`codesign <https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/codesign.1.html>`__\nto run, so they are skipped unless you run them on a Macintosh computer with developer tools.\n\nOkay, if all the tests passed, you now have an 'editable' install of isign. Any edits to this repo will affect (for instance)\nhow the `isign` command line tool works.\n\nSauce Labs supports ongoing public ``isign`` development. ``isign`` is a part of our infrastructure\nfor the `iOS Real Device Cloud <https://saucelabs.com/press-room/press-releases/sauce-labs-expands-mobile-test-automation-cloud-with-the-addition-of-real-devices-1>`__,\nwhich allows customers to test apps and websites on real iOS devices. ``isign`` has been successfully re-signing submitted customer apps in production\nsince June 2015.\n\n.. _More documentation:\n\nMore documentation\n------------------\n\nSee the `docs <docs>`__ directory of this repository for random stuff that didn't fit here.\n\n.. _Authors:\n\n\nAuthors\n-------\n\n`Neil Kandalgaonkar <https://github.com/neilk>`__ is the main developer and maintainer.\n\nProof of concept by `Steven Hazel <https://github.com/sah>`__ and Neil Kandalgaonkar.\n\nReference scripts using Apple tools by `Michael Han <https://github.com/mhan>`__.\n"
  },
  {
    "path": "apple/README.rst",
    "content": "These scripts will re-provision (aka resign, code sign, etc) an app,\nusing Apple tools. The isign tools emulate what these do, on Linux.\n\nprovisions.sh is the original script that Mike Han (@mikehan) wrote.\n\nprovisions.py is a python port.\n"
  },
  {
    "path": "apple/provisions.py",
    "content": "#!/usr/bin/env python\n\n# Port of @mikehan's provisions.sh\n\nimport argparse\nimport glob\nimport os\nimport os.path\nimport shutil\nfrom subprocess import call, Popen\nimport tempfile\n\nCODESIGN_BIN = '/usr/bin/codesign'\nPLIST_BUDDY_BIN = '/usr/libexec/PlistBuddy'\nSECURITY_BIN = '/usr/bin/security'\nZIP_BIN = '/usr/bin/zip'\nUNZIP_BIN = '/usr/bin/unzip'\n\n\nclass ReceivedApp(object):\n    def __init__(self, path):\n        self.path = path\n\n    def unpack_to_dir(self, unpack_dir):\n        app_name = os.path.basename(self.path)\n        target_dir = os.path.join(unpack_dir, app_name)\n        shutil.copytree(self.path, target_dir)\n        return App(target_dir)\n\n\nclass ReceivedIpaApp(ReceivedApp):\n    def unpack_to_dir(self, target_dir):\n        call([UNZIP_BIN, \"-qu\", self.path, \"-d\", target_dir])\n        return IpaApp(target_dir)\n\n\nclass App(object):\n    def __init__(self, path):\n        self.path = path\n        self.entitlements_path = os.path.join(self.path,\n                                              'Entitlements.plist')\n        self.app_dir = self.get_app_dir()\n        self.provision_path = os.path.join(self.app_dir,\n                                           'embedded.mobileprovision')\n\n    def get_app_dir(self):\n        return self.path\n\n    def provision(self, provision_path):\n        print \"provision_path: {0}\".format(provision_path)\n        shutil.copyfile(provision_path, self.provision_path)\n\n    def create_entitlements(self):\n        # we decode part of the provision path, then extract the\n        # Entitlements part, then write that to a file in the app.\n\n        # piping to Plistbuddy doesn't seem to work :(\n        # hence, temporary intermediate file\n\n        decoded_provision_fh, decoded_provision_path = tempfile.mkstemp()\n        decoded_provision_fh = open(decoded_provision_path, 'w')\n        decode_args = [SECURITY_BIN, 'cms', '-D', '-i', self.provision_path]\n        process = Popen(decode_args, stdout=decoded_provision_fh)\n        # if we don't wait for this to complete, it's likely\n        # the next part will see a zero-length file\n        process.wait()\n\n        get_entitlements_cmd = [\n            PLIST_BUDDY_BIN,\n            '-x',\n            '-c',\n            'print :Entitlements ',\n            decoded_provision_path]\n        entitlements_fh = open(self.entitlements_path, 'w')\n        process2 = Popen(get_entitlements_cmd, stdout=entitlements_fh)\n        process2.wait()\n        entitlements_fh.close()\n\n        # should destroy the file\n        decoded_provision_fh.close()\n\n    def codesign(self, certificate, path, extra_args=[]):\n        call([CODESIGN_BIN, '-f', '-s', certificate] + extra_args + [path])\n\n    def sign(self, certificate):\n        # first sign all the dylibs\n        frameworks_path = os.path.join(self.app_dir, 'Frameworks')\n        if os.path.exists(frameworks_path):\n            dylibs = glob.glob(os.path.join(frameworks_path, '*.dylib'))\n            for dylib in dylibs:\n                self.codesign(certificate, dylib)\n        # then sign the app\n        self.codesign(certificate,\n                      self.app_dir,\n                      ['--entitlements', self.entitlements_path])\n\n    def package(self, output_path):\n        if not output_path.endswith('.app'):\n            output_path = output_path + '.app'\n        os.rename(self.app_dir, output_path)\n        return output_path\n\n\nclass IpaApp(App):\n    def _get_payload_dir(self):\n        return os.path.join(self.path, \"Payload\")\n\n    def get_app_dir(self):\n        glob_path = os.path.join(self._get_payload_dir(), '*.app')\n        apps = glob.glob(glob_path)\n        count = len(apps)\n        if count != 1:\n            err = \"Expected 1 app in {0}, found {1}\".format(glob_path, count)\n            raise Exception(err)\n        return apps[0]\n\n    def package(self, output_path):\n        if not output_path.endswith('.ipa'):\n            output_path = output_path + '.ipa'\n        temp = \"out.ipa\"\n        # need to chdir and use relative paths, because zip is stupid\n        old_cwd = os.getcwd()\n        os.chdir(self.path)\n        relative_payload_path = os.path.relpath(self._get_payload_dir(),\n                                                self.path)\n        call([ZIP_BIN, \"-qr\", temp, relative_payload_path])\n        os.rename(temp, output_path)\n        os.chdir(old_cwd)\n        return output_path\n\n\ndef absolute_path_argument(path):\n    return os.path.abspath(path)\n\n\ndef exists_absolute_path_argument(path):\n    if not os.path.exists(path):\n        raise argparse.ArgumentTypeError(\"%s does not exist!\" % path)\n    return absolute_path_argument(path)\n\n\ndef app_argument(path):\n    path = exists_absolute_path_argument(path)\n    _, extension = os.path.splitext(path)\n    if extension == '.app':\n        app = ReceivedApp(path)\n    elif extension == '.ipa':\n        app = ReceivedIpaApp(path)\n    else:\n        raise argparse.ArgumentTypeError(\n                \"{0} doesn't seem to be an .app or .ipa\".format(path))\n    return app\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(\n            description='Resign an iOS application with a new identity '\n                        'and provisioning profile.')\n    parser.add_argument(\n            '-p', '--provisioning-profile',\n            dest='provisioning_profile',\n            required=True,\n            metavar='<your.mobileprovision>',\n            type=exists_absolute_path_argument,\n            help='Path to provisioning profile')\n    parser.add_argument(\n            '-c', '--certificate',\n            dest='certificate',\n            required=True,\n            metavar='<certificate>',\n            help='Identifier for the certificate in your keychain. '\n                 'See `security find-identity` for a list, or '\n                 '`man codesign` for valid ways to specify it.')\n    parser.add_argument(\n            '-s', '--staging',\n            dest='stage_dir',\n            required=False,\n            metavar='<path>',\n            type=absolute_path_argument,\n            default=os.path.join(os.getcwd(), 'stage'),\n            help='Path to stage directory.')\n    parser.add_argument(\n            '-o', '--output',\n            dest='output_path',\n            required=False,\n            metavar='<path>',\n            type=absolute_path_argument,\n            default=os.path.join(os.getcwd(), 'out'),\n            help='Path to output file or directory')\n    parser.add_argument(\n            'app',\n            nargs=1,\n            metavar='<path>',\n            type=app_argument,\n            help='Path to application to re-sign, typically a '\n                 'directory ending in .app or file ending in .ipa.')\n    return parser.parse_args()\n\n\nif __name__ == '__main__':\n    args = parse_args()\n    received_app = args.app[0]\n\n    if os.path.exists(args.stage_dir):\n        shutil.rmtree(args.stage_dir)\n    os.mkdir(args.stage_dir)\n\n    app = received_app.unpack_to_dir(args.stage_dir)\n\n    app.provision(args.provisioning_profile)\n\n    app.create_entitlements()\n\n    app.sign(args.certificate)\n\n    output_path = app.package(args.output_path)\n\n    if os.path.exists(args.stage_dir):\n        shutil.rmtree(args.stage_dir)\n\n    print \"Re-signed package: {0}\".format(output_path)\n"
  },
  {
    "path": "apple/provisions.sh",
    "content": "#!/bin/bash\n\nusage() {\n    echo \"./provisions -p [PATH_TO_NEW_PROVISIONING_PROFILE] -c \\\"CERT NAME: MUST BE IN KEYCHAIN\\\" ipa_file\"\n    exit\n}\n\nwhile getopts \":p:c:\" opt; do\n    case $opt in\n        p  )  PRO_PROFILE=$OPTARG ;;\n        c  )  CERT_NAME=$OPTARG ;;\n        /? )  usage\n    esac\ndone\n\nshift $(($OPTIND - 1))\nif [[ -z \"$@\" ]]; then\n    usage\nelse\n    APP=$@\nfi\n\nverify_args() {\n    if [[ ! -e $APP ]]; then\n        echo \"$APP does not exist\"\n        exit 1\n    elif [[ ! -e $PRO_PROFILE ]]; then\n        echo \"$PRO_PROFILE does not exist\"\n        exit 1\n    elif [[ -z $CERT_NAME ]]; then\n        echo \"Must specify a certificate to use\"\n        exit 1\n    fi\n}\n\nis_app() {\n    [[ $APP =~ \\.app$ ]]\n}\n\nis_ipa() {\n    [[ $APP =~ \\.ipa$ ]]\n}\n\nsetup_dir() {\n    STAGE_DIR=./stage\n    ENTITLEMENTS_FILE=$STAGE_DIR/Entitlements.plist\n    if [[ -e $STAGE_DIR ]]; then\n        rm -r $STAGE_DIR\n    fi\n    mkdir $STAGE_DIR\n    if is_app; then\n        cp -r $APP $STAGE_DIR\n        APP_NAME=$(basename $APP)\n        PAYLOAD_DIR=\"\"\n        APP_DIR=$STAGE_DIR/$APP_NAME\n    elif is_ipa; then\n        unzip -qu $APP -d $STAGE_DIR\n        PAYLOAD_DIR=$STAGE_DIR/Payload\n        APP_DIR=$PAYLOAD_DIR/*.app\n    else\n        echo \"Must provide either an .app or .ipa file\"\n        exit 1\n    fi\n}\n\ncopy_profile() {\n    cp \"$PRO_PROFILE\" $APP_DIR/embedded.mobileprovision\n}\n\ncreate_entitlements() {\n    /usr/libexec/PlistBuddy -x -c \"print :Entitlements \" /dev/stdin <<< $(security cms -D -i ${APP_DIR}/embedded.mobileprovision) > $ENTITLEMENTS_FILE\n}\n\nsign_app() {\n    if [ -e $APP_DIR/Frameworks ]; then\n        for dylib in \"$APP_DIR/Frameworks/*\"\n        do\n            echo \"signing $dylib\"\n            # entitlements are irrelevant to dylibs\n            /usr/bin/codesign -f -s \"$CERT_NAME\" $dylib\n        done\n    fi \n    echo \"signing $APP_DIR\";\n    /usr/bin/codesign -f -s \"$CERT_NAME\" --entitlements $ENTITLEMENTS_FILE $APP_DIR 2>/dev/null\n}\n\npackage_app() {\n    if is_ipa; then\n        (cd $STAGE_DIR; zip -qr out.ipa Payload)\n        echo \"Re-provisioned ipa at $STAGE_DIR/out.ipa\"\n    else\n        echo \"Re-provisioned app at $APP_DIR\"\n    fi\n}\n\nverify_args\nsetup_dir\ncopy_profile\ncreate_entitlements\nsign_app\npackage_app\n"
  },
  {
    "path": "bin/isign",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nimport argparse\nfrom isign import isign\nfrom os.path import abspath, expanduser\nimport logging\n\nFORMATTER = logging.Formatter('%(message)s')\n\n\ndef log_to_stderr(level=logging.INFO):\n    root = logging.getLogger()\n    root.setLevel(level)\n    handler = logging.StreamHandler()\n    handler.setFormatter(FORMATTER)\n    root.addHandler(handler)\n\n\ndef absolute_path_argument(path):\n    return abspath(expanduser(path))\n\n\ndef parse_args():\n    # note that for arguments which eventually get fed into\n    # isign.resign, we deliberately don't set defaults. The kwarg\n    # defaults in isign.resign will be used\n    parser = argparse.ArgumentParser(\n        description='Resign an iOS application with a new identity '\n                    'and provisioning profile. See documentation for '\n                    'how to obtain properly formatted credentials.')\n    parser.add_argument(\n        '-p', '--provisioning-profile',\n        dest='provisioning_profile',\n        required=False,\n        metavar='<your.mobileprovision path>',\n        type=absolute_path_argument,\n        help='Path to provisioning profile'\n    )\n    parser.add_argument(\n        '-a', '--apple-cert',\n        dest='apple_cert',\n        required=False,\n        metavar='<apple cert>',\n        type=absolute_path_argument,\n        help='Path to Apple certificate in PEM form. You only need to specify '\n             'this if the Apple certificate in the isign package is out of '\n             'date.'\n    )\n    parser.add_argument(\n        '-k', '--key',\n        dest='key',\n        required=False,\n        metavar='<key path>',\n        type=absolute_path_argument,\n        help='Path to your organization\\'s key in PEM format.'\n    )\n    parser.add_argument(\n        '-c', '--certificate',\n        dest='certificate',\n        required=False,\n        metavar='<certificate path>',\n        type=absolute_path_argument,\n        help='Path to your organization\\'s certificate in PEM format'\n    )\n    parser.add_argument(\n        '-n', '--credentials',\n        dest='credentials_dir',\n        required=False,\n        metavar='<directory>',\n        help='Equivalent to '\n             '-k <directory>/key.pem '\n             '-c <directory>/certificate.pem '\n             '-p <directory>/isign.mobileprovision'\n    )\n    parser.add_argument(\n        '-o', '--output',\n        dest='output_path',\n        required=False,\n        metavar='<output path>',\n        type=absolute_path_argument,\n        help='Path to output file or directory'\n    )\n    parser.add_argument(\n        'app_paths',\n        nargs=1,\n        metavar='<app path>',\n        type=absolute_path_argument,\n        help='Path to application to re-sign, typically a '\n             'directory ending in .app or file ending in .ipa.'\n    )\n    parser.add_argument(\n        '-v', '--verbose',\n        dest='verbose',\n        action='store_true',\n        default=False,\n        required=False,\n        help='Set logging level to debug.'\n    )\n    parser.add_argument(\n        '-i', '--info',\n        dest='info_props',\n        required=False,\n        metavar='<Info.plist properties>',\n        help='List of comma-delimited key=value pairs of Info.plist properties to override'\n    )\n    parser.add_argument(\n        '-d', '--display',\n        dest='display_only',\n        action='store_true',\n        default=False,\n        required=False,\n        help='Display information about the app without resigning'\n    )\n    parser.add_argument(\n        '-e', '--entitlements',\n        dest='alternate_entitlements_path',\n        required=False,\n        metavar='<alternate entitlements path>',\n        type=absolute_path_argument,\n        help='Sign with these entitlements, rather than ones extracted from provisioning profile'\n    )\n    return parser.parse_args()\n\n\ndef filter_args(args, interested):\n    \"\"\" Filter all args to args that we are interested in \"\"\"\n    # We want the unused command line args to be\n    # missing in kwargs, so the defaults are used\n    kwargs = {}\n    for k, v in vars(args).iteritems():\n        if k in interested and v is not None:\n            kwargs[k] = v\n    return kwargs\n\n\nif __name__ == '__main__':\n    args = parse_args()\n\n    if args.verbose:\n        level = logging.DEBUG\n    else:\n        level = logging.INFO\n    log_to_stderr(level)\n\n    if args.display_only:\n        # Only show information\n        import json\n        bundle_info = isign.view(args.app_paths[0])\n        print json.dumps(bundle_info, indent=4, separators=(',', ': '))\n\n    else:\n        # Handle the various kinds of resign operations\n        kwargs = {}\n\n        # There's only one output path, so it doesn't make sense\n        # to have multiple input paths\n        app_path = args.app_paths[0]\n\n        # Convert the Info.plist property pairs to a dict format\n        if args.info_props:\n            info_props = {}\n            for arg in args.info_props.split(','):\n                i = arg.find('=')\n                if i < 0:\n                    raise Exception('Invalid Info.plist argument: ' + arg)\n                info_props[arg[0:i]] = arg[i + 1:]\n            if info_props:\n                kwargs['info_props'] = info_props\n\n        if args.credentials_dir:\n            # Handle a resign with credentials directory.\n            # First check they haven't over-specified credential paths\n            incompatible_args = ['certificate', 'key', 'provisioning_profile']\n            args_dict = vars(args)\n            for k, v in vars(args).iteritems():\n                if k in incompatible_args and v is not None:\n                    raise Exception(\"Incompatible arguments. Do not use any of \" +\n                                    \", \".join(['--' + s for s in incompatible_args]) + \" \"\n                                    \"with the --credentials argument.\")\n            # looks good, now massage args into method arguments\n            resign_args = ['apple_cert',\n                           'output_path']\n            kwargs.update(filter_args(args, resign_args))\n            isign.resign_with_creds_dir(app_path,\n                                        args.credentials_dir,\n                                        **kwargs)\n        else:\n            # Handle standard resign. User may have specified all, some\n            # or none of the credential files, in which case we rely on\n            # isign.resign() to supply defaults.\n            # Massage args into method arguments\n            resign_args = ['certificate',\n                           'key',\n                           'apple_cert',\n                           'provisioning_profile',\n                           'output_path',\n                           'alternate_entitlements_path']\n            kwargs.update(filter_args(args, resign_args))\n            isign.resign(app_path, **kwargs)\n"
  },
  {
    "path": "bin/isign_export_creds.sh",
    "content": "#!/usr/bin/env bash\n\n# Export a certificate and key from a .p12 file into PEM form, and place\n# them where isign expects them to be.\n#\n# The .p12 file is typically exported from Apple's Keychain Access.\n\nif [[ $# -eq 0 ]]; then\n    echo \"Usage: $0 exported.p12 [target_directory]\"\n    exit 1;\nfi\n\np12_path=$1\n\nif [[ ! -e $p12_path ]]; then\n    echo \"Can't find $p12_path!\";\n    exit 1;\nfi\n\ntarget_dir=${2-$HOME/.isign}\n\ntarget_cert_path=$target_dir/certificate.pem\ntarget_key_path=$target_dir/key.pem\n\nchmod 600 $p12_path\n\nmkdir -p $target_dir\nopenssl pkcs12 -in $p12_path -out $target_cert_path -clcerts -nokeys\nopenssl pkcs12 -in $p12_path -out $target_key_path -nocerts -nodes\nchmod 600 $target_key_path\n\nread -p \"Done exporting $p12_path. Remove it? [Y/n]:\" -n 1 -r\necho\nif [[ $REPLY =~ ^[Yy]$ ]]; then\n    rm $p12_path\nfi\necho \"Exported credentials from $p12_path to $target_dir\"\n\n\nread -p \"Find matching provisioning profile? [Y/n]:\" -n 1 -r\necho\nif [[ $REPLY =~ ^[Yy]$ ]]; then\n    ./guess_mobileprovision.sh $target_cert_path\nfi\n"
  },
  {
    "path": "bin/isign_guess_mobileprovision.sh",
    "content": "#!/usr/bin/env bash\n\n# given the filename certificate in PEM form, find potentially matching .mobileprovision files\n# in the usual directory on Mac OS X\n\nPROVISIONING_PROFILE_DIR=\"$HOME/Library/MobileDevice/Provisioning Profiles\"\n\ncert_path=${1-$HOME/.isign/certificate.pem}\n\necho \"Looking for provisioning profiles signed with $cert_path...\"\n\nget_cert() {\n    cert_path=$1\n    in_certificate=1\n    certificate=''\n    while read line; do\n        if [[ $line =~ 'BEGIN CERTIFICATE' ]]; then\n            in_certificate=0\n            continue\n        fi\n        if [[ $line =~ 'END CERTIFICATE' ]]; then\n            in_certificate=1\n            continue\n        fi\n        if [[ $in_certificate -eq 0 ]]; then\n            # trim leading/trailing whitespace\n            line=\"$(echo -e $line | sed -e 's/^[[:space:]]*//' | sed -e 's/[[:space:]]*$//')\"\n            certificate=\"${certificate}${line}\"\n        fi\n    done < $cert_path\n    echo $certificate\n}\n\ntarget_cert=$(get_cert $cert_path)\nfind \"$PROVISIONING_PROFILE_DIR/mobdev1.mobileprovision\" -type f -print0 | while IFS= read -r -d '' mobileprovision; do\n    # extract the cert from the mobileprovision with `security`\n    mobileprovision_data=$(security cms -D -i \"$mobileprovision\")\n    # PlistBuddy doesn't give array lengths, so we don't know how many certs this mobileprovision might have. Try a few\n    for i in `seq 0 10`; do\n        # because Plistbuddy is dumb, we have to use a convoluted shell syntax to read from stdin \n        # finally base64 it so we can do an easy string comparison\n        # TODO: can't quite figure out why, but I need to pipe it to base64, can't do that encoding later.\n        # But this means I can't figure out if the PlistBuddy succeeded or failed, by checking $?\n        # Have to swallow the error, iterate more times than necessary :(\n        cert=$(/usr/libexec/PlistBuddy -c \"Print :DeveloperCertificates:$i\" /dev/stdin <<< $(echo $mobileprovision_data) 2>/dev/null | base64)\n        # Examine a long prefix (there are some issues with padding & zeroes at the end).\n        # if first thousand match it is almost certainly a match\n        if [[ ${cert:0:1000} = ${target_cert:0:1000} ]]; then\n            echo \"\\\"$mobileprovision\\\" was signed with this certificate.\"\n        fi\n    done\ndone\n\n\n\n"
  },
  {
    "path": "bin/make_seal",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom optparse import OptionParser\nimport isign.code_resources\nimport logging\n\nFORMATTER = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')\n\n\ndef log_to_stderr(level=logging.INFO):\n    root = logging.getLogger()\n    root.setLevel(level)\n    handler = logging.StreamHandler()\n    handler.setFormatter(FORMATTER)\n    root.addHandler(handler)\n\n\nif __name__ == '__main__':\n    log_to_stderr()\n    parser = OptionParser()\n    options, args = parser.parse_args()\n    source_app, target_dir = args\n    isign.code_resources.make_seal(source_app, target_dir)\n"
  },
  {
    "path": "bin/multisign",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# From a single IPA, generate multiple re-signed IPAs simultaneously.\n# Why? Because you might want to distribute an app to a lot of organizations at once,\n# or perhaps you need to sign for an enterprise and a local debug deployment all at\n# the same time, and you want it to be fast.\n\n# Depends on the existence of external `zip` and `unzip` programs.\n\nimport argparse\nfrom os.path import abspath, basename, dirname, expanduser, join\nfrom isign.multisign import multisign\nimport logging\n\nFORMATTER = logging.Formatter('%(message)s')\nlog = logging.getLogger(__name__)\n\n\ndef log_to_stderr(level=logging.INFO):\n    root = logging.getLogger()\n    root.setLevel(level)\n    handler = logging.StreamHandler()\n    handler.setFormatter(FORMATTER)\n    root.addHandler(handler)\n\n\ndef absolute_path_argument(path):\n    return abspath(expanduser(path))\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(\n        description='From a single IPA, generate multiple re-signed IPAs simultaneously')\n    parser.add_argument(\n        '-a', '--app',\n        dest='app',\n        required=True,\n        metavar='<file>',\n        type=absolute_path_argument,\n        help='Path to input app'\n    )\n    parser.add_argument(\n        'credential_dirs',\n        nargs='+',\n        metavar='<directory>',\n        type=absolute_path_argument,\n        help='Paths to directories containing credentials with standardized names'\n    )\n    parser.add_argument(\n        '-i', '--info',\n        dest='info_props',\n        required=False,\n        metavar='<Info.plist properties>',\n        help='List of comma-delimited key=value pairs of Info.plist properties to override'\n    )\n    parser.add_argument(\n        '-v', '--verbose',\n        dest='verbose',\n        action='store_true',\n        default=False,\n        required=False,\n        help='Set logging level to debug.'\n    )\n    return parser.parse_args()\n\ndef get_output_path(original_path, credential_dir):\n    \"\"\" Create some filename based on the credential directory and original path \"\"\"\n    original_name = basename(original_path)\n    original_dir = dirname(original_path)\n    resigned_name = basename(credential_dir) + '_' + original_name\n    return join(original_dir, resigned_name)\n\n\nif __name__ == '__main__':\n    args = parse_args()\n\n    if args.verbose:\n        level = logging.DEBUG\n    else:\n        level = logging.INFO\n    log_to_stderr(level)\n\n    # Convert the Info.plist property pairs to a dict format\n    info_props = None\n    if args.info_props:\n        info_props = {}\n        for arg in args.info_props.split(','):\n            i = arg.find('=')\n            if i < 0:\n                raise Exception('Invalid Info.plist argument: ' + arg)\n            info_props[arg[0:i]] = arg[i + 1:]\n\n    log.debug('got credential paths: {}'.format(', '.join(args.credential_dirs)))\n    log.debug('got incoming app: {}'.format(args.app))\n\n    # ensure basenames are unique\n    unique_basenames = set([basename(p) for p in args.credential_dirs])\n    if len(args.credential_dirs) != len(unique_basenames):\n        raise Exception('Credential directories do not have unique basenames. '\n                        'Cannot name output archives automatically. Sorry!')\n\n    credential_dirs_to_output_paths = {}\n    for d in args.credential_dirs:\n        credential_dirs_to_output_paths[d] = get_output_path(args.app, d)\n\n    results = multisign(args.app, credential_dirs_to_output_paths, info_props)\n    for credentials_dir, resigned_app_path in results:\n        log.info(\"resigned with %s to %s\", credentials_dir, resigned_app_path)\n"
  },
  {
    "path": "bin/pprint_codesig",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nimport argparse\nimport isign.archive\nfrom isign.exceptions import NotSignable\nfrom isign.signable import Executable\nimport logging\nfrom os.path import abspath, expanduser, isdir\nimport shutil\n\nFORMATTER = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')\nlog = logging.getLogger(__name__)\n\n\ndef log_to_stderr(level=logging.INFO):\n    root = logging.getLogger()\n    root.setLevel(level)\n    handler = logging.StreamHandler()\n    handler.setFormatter(FORMATTER)\n    root.addHandler(handler)\n\n\ndef absolute_path_argument(path):\n    return abspath(expanduser(path))\n\n\ndef print_codesig(path):\n    temp_dir = None\n    try:\n        archive = isign.archive.archive_factory(path)\n        (temp_dir, bundle) = appArchive.unarchive_to_temp()\n        _print_codesig(bundle)\n    except NotSignable as e:\n        msg = \"Not signable: <{0}> {1}\\n\".format(path, e)\n        log.error(msg)\n        raise\n    finally:\n        if temp_dir is not None and isdir(temp_dir):\n            shutil.rmtree(temp_dir)\n\n\ndef _print_codesig(bundle):\n    executable = Executable(bundle.get_executable_path())\n    for arch in executable.arches:\n        print arch['cmds']['LC_CODE_SIGNATURE']\n\n\ndef parse_args():\n    parser = argparse.ArgumentParser(\n        description='Print the code signature structure of an executable or dylib')\n    parser.add_argument(\n        '-v', '--verbose',\n        dest='verbose',\n        action='store_true',\n        default=False,\n        required=False,\n        help='Set logging level to debug.'\n    )\n    parser.add_argument(\n        'app_paths',\n        nargs=1,\n        metavar='<app path>',\n        type=absolute_path_argument,\n        help='Path(s) to application, typically a '\n             'directory ending in .app or file ending in .ipa.'\n    )\n    return parser.parse_args()\n\nif __name__ == '__main__':\n    args = parse_args()\n    if args.verbose:\n        level = logging.DEBUG\n    else:\n        level = logging.INFO\n    log_to_stderr(level)\n\n    print_codesig(args.app_paths[0])\n"
  },
  {
    "path": "dev/requirements.txt",
    "content": "nose\npytest\ntwine\n"
  },
  {
    "path": "dev/setup.sh",
    "content": "#!/bin/bash\nset -e\n\n# determine local paths\npushd $(dirname \"$0\") >/dev/null\nDEV_DIR=$PWD\ncd ..\nSRC_DIR=$PWD\npopd >/dev/null\n\npip install -U -r ${DEV_DIR}/requirements.txt\n../INSTALL.sh develop\n"
  },
  {
    "path": "docs/applecerts.rst",
    "content": "Apple certificates\n==================\n\nYou probably don't need to change this file, not for a long time.\n\nThe ``applecerts.pem`` file can be constructed by these steps. In theory\nyou can export them from Keychain Access, too, but here's a procedure that\ndoesn't involve an Apple machine. This worked for us in June 2016:\n\n.. code:: bash\n\n        $ curl 'https://www.apple.com/appleca/AppleIncRootCertificate.cer' > AppleIncRootCertificate.cer\n        $ curl 'https://developer.apple.com/certificationauthority/AppleWWDRCA.cer' > AppleWWDRCA.cer\n        $ openssl x509 -inform der -in AppleIncRootCertificate.cer -outform pem -out AppleIncRootCertificate.pem\n        $ openssl x509 -inform der -in AppleWWDRCA.cer -outform pem -out AppleWWDRCA.pem\n        $ cat AppleWWDRCA.pem AppleIncRootCertificate.pem > applecerts.pem\n\nHere's a conceptual explanation of what we're doing:\n\nDownload the following certs from `Apple's Certificate Authority\nPage <https://www.apple.com/certificateauthority/>`__\n\n-  Apple Inc. Root Certificate\n-  Worldwide Developer Relations Certificate\n\nThen convert these to\n`PEM <http://en.wikipedia.org/wiki/Privacy-enhanced_Electronic_Mail>`__\nformat.\n\nThen, concatenate them together. This file can now serve as the 'Apple\ncertificate' for code signing.\n\n"
  },
  {
    "path": "docs/codedirectory.rst",
    "content": "CodeDirectory slots\n===================\n\nA signature is mostly composed of hashes of blocks of the file's\ncontents. However, at some point, Apple added special hashes so the\nstate of other resources in the app could be captured in the signature.\nFor instance, the Info.plist gets its own hash, and ultimately the\nhashes of all the other files are also captured in the ResourceDirectory\nhash. Together, all these special hashes are called the CodeDirectory.\n\nPerhaps to indicate that these are special hashes, they were given\nnegative offsets in the list of hashes.\n\nFor instance, if you do ``codesign -d -r- --verbose=20 some.app``\n\n::\n\n    Executable=...\n    Identifier=com.somecompany.someapp\n    Format=bundle with Mach-O universal (armv7 arm64)\n    CodeDirectory v=20200 size=874 flags=0x0(none) hashes=35+5 location=embedded\n    Hash type=sha1 size=20\n        -5=0ea763a5bc4d19b0e03315a956deecd97693a661\n        -4=0000000000000000000000000000000000000000\n        -3=b353e6ce8464fd8ae32cfcf09e7c9015b7378054\n        -2=32a5edb9b03a0bea2d7bc30cfdddadab7dab841c\n        -1=46ebe92997b23b2e2187a21714c8cc32c347bf35\n         0=70e024fdab3426c375cf283d384de58ec6fff438\n         1=1ceaf73df40e531df3bfb26b4fb7cd95fb7bff1d\n         2=1ceaf73df40e531df3bfb26b4fb7cd95fb7bff1d\n         ...\n\nThe CodeDirectory hashes have stable negative indices - for instance, -1\nis always the hash of the Info.plist file. The indices for the\nCodeDirectory hashes are sometimes called slots.\n\nWhen building the CodeDirectory, We need to observe these constraints:\n\n-  Executables should have all 5 slots in their codedirectory\n\n-  Dylibs only need 2 slots, but sometimes have been compiled with 5\n\n-  Dylibs should never include the ResourceDir slot, even if they have 5\n   slots\n\n-  We should delay calculating hashes until we know we are going to use\n   them\n\n-  Nobody uses the Application-specific slot anyway\n\n-  At least so far, we don't need to change the Info.plist slot when\n   re-signing\n"
  },
  {
    "path": "docs/credentials.rst",
    "content": "Apple developer credentials\n===========================\n\nMac OS X and iOS aren't like most other operating systems -- security is baked into every\nsingle program. The machine is able to check, before it even executes the program, who\nwrote it, whether Apple approved it, and whether it has the authority to do some things \nthat it's asking to do. On Mac OS X, it's easy to get around those restrictions, but iOS \nis locked down very tight.\n\nThe iOS device is able tell who wrote a program, and whether Apple approved it, without\neven phoning home to Apple. It does this by looking for evidence that is *was* approved \nat some earlier date, using cryptographic signatures embedded right into the application. \n\nUntil now, few people outside Apple had a full understanding of how that worked, or how to\nadd that magic \"code signature\" and other necessary proofs to the app.\n\n``isign`` is able to create those -- with the right credentials.\n\nDefinitions\n-----------\n\nThe **key** is the developer's private key. If you're familiar with Secure Shell keys, this is similar -- it's\nthe private half of a public-private key pair. The private key is used to sign the application. This proves that\nthe developer approved the entire contents of the application.\n\nNote that this key is not revealed to Apple, or anyone else. If you\ndevelop iOS apps, you, or someone in your organization, generated such a key. Hopefully they kept it\nsecret. However, you need it to sign the app -- you probably have it in Keychain Access or something like\nthat.\n\nThe **certificate** is how Apple indicates that the developer is approved to write apps for iOS. At some\npoint, they signed the public half of the developer's keys. Apple will also encode when your developer account\nis going to expire.\n\nThe **organizational unit** is an identifier that Apple assigns to organizations that\ncreate apps on Apple devices. It's an eight character code of letters and numbers. You may need to know your \norganizational unit, so you can sign apps from your organization. ``isign`` can extract this from other files,\nlike your certificate, so you probably don't need to worry about this.\n\nThe **provisioning profile** is where it all comes together. This file is included in the app.\n\nThe provisioning profile includes the contents of the certificate -- possibly many certificates.\nIt also includes the UDIDs of the devices that you have registered with Apple. So, you can often use the same\nprovisioning profile for all your developers and all your iOS devices.\n\nSo, when a phone encounters an app, it will start by reading the provisioning profile, to learn things like:\n\n- Who wrote this app?\n- What organization do they belong to?\n- Are they still an Apple-approved developer?\n- And what's their public key?\n- Is this app approved to run on this particular device?\n\nFrom there it can go on to cryptographically verify each and every part of the app. This ensures that the \napp has not been tampered with, or that an unapproved developer hasn't snuck an app onto your phone (even if \nthat developer is you.)\n\n\nHow to create Apple developer credentials\n-----------------------------------------\n\nFor most developers, XCode takes care of most of these credentials. But with ``isign`` you have to do it more manually.\n \nGetting an account\n~~~~~~~~~~~~~~~~~~\n\nFirst, find an administrator for your developer organization at Apple. (If you're a solo developer, that's you.)\n\nGet them to invite you to your Apple Organizational Unit. \n\nYou'll get email from Apple, which will prompt you to set up your account. Set up passwords and so on as usual.\n\nTroubleshooting: you may have to click on the mailed invite link\nonce to set up your account, and then return to your mail to click\non that invite link again to actually activate your account. Also,\nin general, things on the Apple site work better with Safari, so\nif something doesn't work, try that browser.\n\nSetting up credentials\n~~~~~~~~~~~~~~~~~~~~~~\n\nThe following procedure works as of June 2015, for adding a new\naccount from scratch. You will need a Mac OS X computer. (In theory \nyou could do this entirely from Linux, using the Apple website, but \nyou're on your own there.)\n\nLog into your Apple account.\n\nGo to **Certificates, Identifiers, & Profiles**.\n\nGo to **Certificates > Development** in the left-hand column.\n\nPress the plus icon to add a new certificate.\n\nIt will ask what type of certificate you need. You probably want\n*iOS App Development*.\n\nIt will then instruct you to use Keychain Access to generate a\nCertificate Signing Request. In effect you are going to create a\nprivate/public key pair, and then make a little file that says \"Hey\nApple, please sign the public half and make a certificate for it, and \nassociate that with my Apple account!\"\n\nFollow the instructions and save that CSR to disk. Press **Continue**.\n\nThen, the Apple website will ask you to upload that CSR. Do so, and\nit will create a certificate for your account in your organization.\nThis certificate might need to be approved by an admin before you\ncan download it.\n\nOnce it's approved, download it!\n\nIt will probably be named something generic like ``ios_development.cer``,\nso rename it to something more meaningful and put it somewhere safe.\n\nImport that ``.cer`` into Keychain. Keychain will detect that it\nhas an associated private key, and in views where you see keys, the\ncertificate will be \"inside\" the key, and vice versa.\n\nProvisioning profile\n~~~~~~~~~~~~~~~~~~~~\n\nNow we just need to tell Apple that your user is allowed to deploy on those devices. \n\nFirst, go to **Devices**, and add the UDIDs of all the devices you care about. If you installed `libimobiledevice`, an easy way to get the\nUDID is with ``idevice_id -l``. \n\nIn the Developer portal, go to **Provisioning Profiles**, and create a new development profile. Select those devices and add them.\n\nIn **Select App ID**, you probably want to just create one with a\nwildcard (Something using your Apple Organizational Unit plus domain plus dot-star, maybe, \nlike ``A1B2C3D4.tld.domain.*`` )\n\nNext, in **'Select certificates'**, select the certificates you want, which probably includes the one we just created above.\n\nFinally, download this provisioning profile, and follow the instructions in the main README.\n"
  },
  {
    "path": "docs/speed.rst",
    "content": "So you want to make it go faster\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe *vast* majority of time in isign is not spent signing. It's in zipping and re-zipping. \n\nMost apps are packaged as IPAs. These are just glorified zip files with a particular directory structure. For most situations, we can't avoid the cost of unzipping and re-zipping. So if we're trying to make it faster, we've already lost, since we'll never speed it up even by a factor of 2. \n\nIn theory you could:\n\n- Not use IPAs. isign can also re-sign unzipped \".app\" directories. This is way faster, but then you have to use isign where you created the app, and you have to install the resigned app onto a device from there as well.\n\n- Use IPAs but re-compress them poorly. Basically, change the setting from zip quality of 6 (the default) to something else. Minor speedups can be accomplished that way, at the cost of increasing install time or time to transfer to send it the network. In my tests it wasn't an improvement when you considered typical things you would do with the app next.\n\nIf neither of those approaches is acceptable to you, you can stop reading here. Because everything else that follows will speed it up, but not by much.\n\n\nOkay, so what *else* is taking time?\n\n1) Copying the files. Maybe with some exotic copy-on-write filesystem we could avoid that?\n\n2) Hashing the entire contents of the application. For data that we've never seen before, we can't do better than O(n). So we lose *again*.\n\nBut we could still do better in the general case:\n\n- There are many files within the application. If we don't touch a file (it's not an executable \n  or dylib), and we got a hash in the app's existing CodeResources seal, we could trust it, and \n  reuse it in our CodeResources seal. \n  \n  I tried implementing this and it was super annoying to code, and didn't\n  have a big impact on my test files, so I gave up. The problem is that you have to write wrappers around \n  every method that writes to a file, and keep a tally of what files you touched. If you don't mind a less\n  accurate method (scan directories for files changed since the start of the resigning process) that \n  might work better.\n\n- We could recognize common libraries such as the Swift framework, and keep re-signed versions of \n  those in some persistent storage.\n\n- Use separate processes to hash files, to exploit multiple cores.\n\nBut wait!\n~~~~~~~~~\n\nIncidentally, if what you're looking for is to resign one app with multiple credentials, look into the `multisign` scripts. There can save a significant amount of time by unzipping the original app only once, and using a process pool to exploit multiple cores.\n"
  },
  {
    "path": "isign/__init__.py",
    "content": "# -*- coding: utf-8 -*-\nimport os.path\nimport json\n\npackage_dir = os.path.dirname(os.path.realpath(__file__))\nwith open(os.path.join(package_dir, \"version.json\"), 'r') as f:\n    version = json.load(f)\n\n__version__ = version['version']\n__commit__ = version['commit']\n__build__ = version['build']\n"
  },
  {
    "path": "isign/apple_credentials/README.rst",
    "content": "These Apple credentials are public knowledge (see the docs) so they \nare okay to distribute. Don't put anything else here.\n"
  },
  {
    "path": "isign/archive.py",
    "content": "# -*- coding: utf-8 -*- \n\"\"\" Represents an app archive. This is an app at rest, whether it's a naked\n    app bundle in a directory, or a zipped app bundle, or an IPA. We have a\n    common interface to extract these apps to a temp file, then resign them,\n    and create an archive of the same type \"\"\"\n\nimport abc\nimport biplist\nfrom bundle import App, Bundle, is_info_plist_native\nfrom exceptions import MissingHelpers, NotSignable, NotMatched\nfrom distutils import spawn\nimport logging\nimport os\nfrom os.path import abspath, dirname, exists, isdir, isfile, join, normpath\nimport tempfile\nimport re\nfrom subprocess import call\n\n\nfrom signer import Signer\nimport shutil\nimport zipfile\n\nimport utils\n\nREMOVE_WATCHKIT = True\nhelper_paths = {}\nlog = logging.getLogger(__name__)\n\n\ndef get_helper(helper_name):\n    \"\"\" find paths to executables. Cached in helper_paths \"\"\"\n    if helper_name not in helper_paths or helper_paths[helper_name] is None:\n        # note, find_executable returns None is not found\n        # in other words, we keep retrying until found\n        helper_paths[helper_name] = spawn.find_executable(helper_name)\n    log.debug(\"got executable {} for {}\".format(helper_paths[helper_name],\n                                                helper_name))\n    return helper_paths[helper_name]\n\n\ndef make_temp_dir():\n    return tempfile.mkdtemp(prefix=\"isign-\")\n\n\ndef get_watchkit_paths(root_bundle_path):\n    \"\"\" collect sub-bundles of this bundle that have watchkit \"\"\"\n    # typical structure:\n    #\n    # app_bundle\n    #   ...\n    #   some_directory\n    #     watchkit_extension   <-- this is the watchkit bundle\n    #       Info.plist\n    #       watchkit_bundle    <-- this is the part that runs on the Watch\n    #         Info.plist       <-- WKWatchKitApp=True\n    #\n    watchkit_paths = []\n    for path, _, _ in os.walk(root_bundle_path):\n        if path == root_bundle_path:\n            continue\n        try:\n            bundle = Bundle(path)\n        except NotMatched:\n            # this directory is not a bundle\n            continue\n        if bundle.info.get('WKWatchKitApp') is True:\n            # get the *containing* bundle\n            watchkit_paths.append(dirname(path))\n    return watchkit_paths\n\n\ndef process_watchkit(root_bundle_path, should_remove=False):\n    \"\"\" Unfortunately, we currently can't sign WatchKit. If you don't\n        care about watchkit functionality, it is\n        generally harmless to remove it, so that's the default.\n        Remove when https://github.com/saucelabs/isign/issues/20 is fixed \"\"\"\n    watchkit_paths = get_watchkit_paths(root_bundle_path)\n    if len(watchkit_paths) > 0:\n        if should_remove:\n            for path in watchkit_paths:\n                log.warning(\"Removing WatchKit bundle {}\".format(path))\n                shutil.rmtree(path)\n        else:\n            raise NotSignable(\"Cannot yet sign WatchKit bundles\")\n\n\nclass Archive(object):\n    __metaclass__ = abc.ABCMeta\n    # we use abc.abstractmethod throughout because there are certain class\n    # methods we want to ensure are implemented.\n\n    @abc.abstractmethod\n    def unarchive_to_temp(self):\n        \"\"\" Unarchive and copy to a temp directory \"\"\"\n        pass\n\n    @abc.abstractmethod\n    def archive(cls, path, output_path):\n        \"\"\" Archive a directory to an output path \"\"\"\n        pass\n\n    @abc.abstractmethod\n    def get_info(cls, path):\n        \"\"\" Obtain app metadata from Info.plist without unarchiving \"\"\"\n        pass\n\n    @abc.abstractmethod\n    def precheck(cls, path):\n        \"\"\" Check if this is, in fact, an archive of this type \"\"\"\n        pass\n\n    @abc.abstractmethod\n    def find_bundle_dir(cls, path):\n        \"\"\" Locate the directory of the main app (aka bundle) \"\"\"\n        pass\n\n\nclass AppArchive(Archive):\n    \"\"\" The simplest form of archive -- a naked App Bundle, with no extra directory structure,\n        compression, etc \"\"\"\n\n    @classmethod\n    def find_bundle_dir(cls, path):\n        \"\"\" Included for similarity with the zipped archive classes. In this case, the bundle dir\n            *is* the directory \"\"\"\n        return path\n\n    @classmethod\n    def _get_plist_path(cls, path):\n        return join(cls.find_bundle_dir(path), \"Info.plist\")\n\n    @classmethod\n    def get_info(cls, path):\n        return biplist.readPlist(cls._get_plist_path(path))\n\n    @classmethod\n    def precheck(cls, path):\n        if not isdir(path):\n            return False\n        if not os.path.exists(cls._get_plist_path(path)):\n            return False\n        plist = cls.get_info(path)\n        is_native = is_info_plist_native(plist)\n        log.debug(\"is_native: {}\".format(is_native))\n        return is_native\n\n    @classmethod\n    def archive(cls, path, output_path):\n        if exists(output_path):\n            shutil.rmtree(output_path)\n        shutil.move(path, output_path)\n        log.info(\"archived %s to %s\" % (cls.__name__, output_path))\n\n    def __init__(self, path):\n        self.path = path\n        self.relative_bundle_dir = '.'\n        self.bundle_info = self.get_info(self.path)\n\n    def unarchive_to_temp(self):\n        containing_dir = make_temp_dir()\n        log.debug(\"unarchiving to temp... %s -> %s\", self.path, containing_dir)\n        shutil.rmtree(containing_dir)  # quirk of copytree, top dir can't exist already\n        shutil.copytree(self.path, containing_dir)\n        process_watchkit(containing_dir, REMOVE_WATCHKIT)\n        return UncompressedArchive(containing_dir, '.', self.__class__)\n\n\nclass AppZipArchive(Archive):\n    \"\"\" Just like an app, except it's zipped up, and when repackaged,\n        should be re-zipped. \"\"\"\n    app_dir_pattern = r'^([^/]+\\.app/).*$'\n    extensions = ['.zip']\n    helpers = ['zip', 'unzip']\n\n    @classmethod\n    def is_helpers_present(cls):\n        \"\"\" returns False if any of our helper apps wasn't found in class init \"\"\"\n        is_present = True\n        for helper_name in cls.helpers:\n            if get_helper(helper_name) is None:\n                log.error(\"missing helper for class {}: {}\".format(cls.__name__, helper_name))\n                is_present = False\n                break\n        return is_present\n\n    @classmethod\n    def is_archive_extension_match(cls, path):\n        \"\"\" does this path have the right extension \"\"\"\n        log.debug('extension match')\n        for extension in cls.extensions:\n            log.debug('extension match: %s', extension)\n            if path.endswith(extension):\n                return True\n        return False\n\n    @classmethod\n    def find_bundle_dir(cls, zipfile_obj):\n        relative_bundle_dir = None\n        apps = set()\n        file_list = zipfile_obj.namelist()\n        for file_name in file_list:\n            matched = re.match(cls.app_dir_pattern, file_name)\n            if matched:\n                apps.add(matched.group(1))\n        if len(apps) == 1:\n            log.debug(\"found one app\")\n            relative_bundle_dir = apps.pop()\n        elif len(apps) > 1:\n            log.warning('more than one app found in archive')\n        else:\n            log.warning('no apps found in archive')\n        return relative_bundle_dir\n\n    @classmethod\n    def _get_plist_path(cls, relative_bundle_dir):\n        return join(relative_bundle_dir, \"Info.plist\")\n\n    @classmethod\n    def precheck(cls, path):\n        \"\"\" Checks if an archive looks like this kind of app. Have to examine\n            within the zipfile, b/c we don't want to make temp dirs just yet. This\n            recapitulates a very similar precheck in the Bundle class \"\"\"\n        if not isfile(path):\n            return False\n        if not cls.is_helpers_present():\n            raise MissingHelpers(\"helpers not present\")\n        is_native = False\n        log.debug('precheck')\n        log.debug('path: %s', path)\n        if (cls.is_archive_extension_match(path) and\n                zipfile.is_zipfile(path)):\n            log.debug(\"this is an archive, and a zipfile\")\n            zipfile_obj = zipfile.ZipFile(path)\n            relative_bundle_dir = cls.find_bundle_dir(zipfile_obj)\n            if relative_bundle_dir is not None:\n                plist_path = cls._get_plist_path(relative_bundle_dir)\n                if plist_path not in zipfile_obj.namelist():\n                    return False\n                plist = cls.get_info(relative_bundle_dir, zipfile_obj)\n                is_native = is_info_plist_native(plist)\n                log.debug(\"is_native: {}\".format(is_native))\n        return is_native\n\n    @classmethod\n    def get_info(cls, relative_bundle_dir, zipfile_obj):\n        plist_path = cls._get_plist_path(relative_bundle_dir)\n        plist_bytes = zipfile_obj.read(plist_path)\n        return biplist.readPlistFromString(plist_bytes)\n\n    def __init__(self, path):\n        self.path = path\n        zipfile_obj = zipfile.ZipFile(path)\n        self.relative_bundle_dir = self.find_bundle_dir(zipfile_obj)\n        self.bundle_info = self.get_info(self.relative_bundle_dir,\n                                         zipfile_obj)\n\n    def unarchive_to_temp(self):\n        containing_dir = make_temp_dir()\n        call([get_helper('unzip'), \"-qu\", self.path, \"-d\", containing_dir])\n        app_dir = abspath(join(containing_dir, self.relative_bundle_dir))\n        process_watchkit(app_dir, REMOVE_WATCHKIT)\n        return UncompressedArchive(containing_dir, self.relative_bundle_dir, self.__class__)\n\n    @classmethod\n    def archive(cls, containing_dir, output_path):\n        \"\"\" archive this up into a zipfile. Note this is a classmethod, because\n            the caller will use us on a temp directory somewhere \"\"\"\n        # the temp file is necessary because zip always adds \".zip\" if it\n        # does not have an extension. But we want to respect the desired\n        # output_path's extension, which could be \".ipa\" or who knows.\n        # So we move it to the output_path later.\n        #\n        # We also do a little dance with making another temp directory just\n        # to construct the zip file. This is the best way to ensure the an unused\n        # filename. Also, `zip` won't overwrite existing files, so this is safer.\n        temp_zip_dir = None\n        try:\n            # need to chdir and use relative paths, because zip is stupid\n            temp_zip_dir = tempfile.mkdtemp(prefix=\"isign-zip-\")\n            temp_zip_file = join(temp_zip_dir, 'temp.zip')\n            call([get_helper('zip'), \"-qr\", temp_zip_file, \".\"], cwd=containing_dir)\n            shutil.move(temp_zip_file, output_path)\n            log.info(\"archived %s to %s\" % (cls.__name__, output_path))\n        finally:\n            if temp_zip_dir is not None and isdir(temp_zip_dir):\n                shutil.rmtree(temp_zip_dir)\n\n\nclass IpaArchive(AppZipArchive):\n    \"\"\" IPA is Apple's standard for distributing apps. Much like an AppZip,\n        but slightly different paths \"\"\"\n    extensions = ['.ipa']\n    app_dir_pattern = r'^(Payload/[^/]+\\.app/).*$'\n\n\nclass UncompressedArchive(object):\n    \"\"\" This just keeps track of some state with an unzipped app archive and\n        how to re-zip it back up once re-signed. The bundle is located somewhere\n        inside the containing directory, but might be a few directories down, like in\n        a ContainingDir/Payload/something.app\n\n        This class is also useful if you have an app that's already unzipped and\n        you want to sign it. \"\"\"\n    def __init__(self, path, relative_bundle_dir, archive_class):\n        \"\"\" Path is the \"Containing dir\", the dir at the root level of the unzipped archive\n                (or the dir itself, in the case of an AppArchive archive)\n            relative bundle dir is the dir containing the bundle, e.g. Payload/Foo.app\n            archive class is the kind of archive this was (Ipa, etc.) \"\"\"\n        path = utils.remove_control_char(path)\n        self.path = path\n        self.relative_bundle_dir = relative_bundle_dir\n        self.archive_class = archive_class\n        bundle_path = normpath(join(path, relative_bundle_dir))\n        self.bundle = App(bundle_path)\n\n    def archive(self, output_path):\n        \"\"\" Re-zip this back up, or simply copy it out, depending on what the\n            original archive class did \"\"\"\n        self.archive_class.archive(self.path, output_path)\n\n    def clone(self, target_path):\n        \"\"\" Copy the uncompressed archive somewhere else, return initialized\n            UncompressedArchive \"\"\"\n        shutil.copytree(self.path, target_path)\n        return self.__class__(target_path,\n                              self.relative_bundle_dir,\n                              self.archive_class)\n\n    def remove(self):\n        # the containing dir might be gone already b/c AppArchive simply moves\n        # it to the desired target when done\n        if exists(self.path) and isdir(self.path):\n            log.debug('removing ua: %s', self.path)\n            shutil.rmtree(self.path)\n\n\ndef archive_factory(path):\n    \"\"\" Guess what kind of archive we are dealing with, return an\n        archive object. Returns None if path did not match any archive type \"\"\"\n    archive = None\n    for cls in [IpaArchive, AppZipArchive, AppArchive]:\n        if cls.precheck(path):\n            archive = cls(path)\n            log.debug(\"File %s matched as %s\", path, cls.__name__)\n            break\n    return archive\n\n\ndef view(input_path):\n    if not exists(input_path):\n        raise IOError(\"{0} not found\".format(input_path))\n    ua = None\n    bundle_info = None\n    try:\n        archive = archive_factory(input_path)\n        if archive is None:\n            raise NotMatched('No matching archive type found')\n        ua = archive.unarchive_to_temp()\n        bundle_info = ua.bundle.info\n    finally:\n        if ua is not None:\n            ua.remove()\n    return bundle_info\n\n\ndef resign(input_path,\n           certificate,\n           key,\n           apple_cert,\n           provisioning_profile,\n           output_path,\n           info_props=None,\n           alternate_entitlements_path=None):\n    \"\"\" Unified interface to extract any kind of archive from\n        a temporary file, resign it with these credentials,\n        and create a similar archive for that resigned app \"\"\"\n\n    if not exists(input_path):\n        raise IOError(\"{0} not found\".format(input_path))\n\n    log.debug('Signing with apple_cert: {}'.format(apple_cert))\n    log.debug('Signing with key: {}'.format(key))\n    log.debug('Signing with certificate: {}'.format(certificate))\n    log.debug('Signing with provisioning_profile: {}'.format(provisioning_profile))\n\n    signer = Signer(signer_cert_file=certificate,\n                    signer_key_file=key,\n                    apple_cert_file=apple_cert)\n\n    ua = None\n    bundle_info = None\n    try:\n        archive = archive_factory(input_path)\n        if archive is None:\n            raise NotSignable('No matching archive type found')\n        ua = archive.unarchive_to_temp()\n        if info_props:\n            # Override info.plist props of the parent bundle\n            ua.bundle.update_info_props(info_props)\n        ua.bundle.resign(signer, provisioning_profile, alternate_entitlements_path)\n        bundle_info = ua.bundle.info\n        ua.archive(output_path)\n    except NotSignable as e:\n        msg = \"Not signable: <{0}>: {1}\\n\".format(input_path, e)\n        log.info(msg)\n        raise\n    finally:\n        if ua is not None:\n            ua.remove()\n    return bundle_info\n"
  },
  {
    "path": "isign/bundle.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\" Represents a bundle. In the words of the Apple docs, it's a convenient way to deliver\n    software. Really it's a particular kind of directory structure, with one main executable,\n    well-known places for various data files and libraries,\n    and tracking hashes of all those files for signing purposes.\n\n    For isign, we have two main kinds of bundles: the App, and the Framework (a reusable\n    library packaged along with its data files.) An App may contain many Frameworks, but\n    a Framework has to be re-signed independently.\n\n    See the Apple Developer Documentation \"About Bundles\" \"\"\"\n\nimport biplist\nimport code_resources\nfrom exceptions import NotMatched\nimport copy\nimport glob\nimport logging\nimport os\nfrom os.path import basename, exists, join, splitext\nfrom signer import openssl_command\nimport signable\nimport shutil\nimport utils\n\nlog = logging.getLogger(__name__)\n\n\ndef is_info_plist_native(plist):\n    \"\"\" If an bundle is for native iOS, it has these properties in the Info.plist \"\"\"\n    return (\n        'CFBundleSupportedPlatforms' in plist and\n        'iPhoneOS' in plist['CFBundleSupportedPlatforms']\n    )\n\n\nclass Bundle(object):\n    \"\"\" A bundle is a standard directory structure, a signable, installable set of files.\n        Apps are Bundles, but so are some kinds of Frameworks (libraries) \"\"\"\n    helpers = []\n    signable_class = None\n    entitlements_path = None  # Not set for every bundle type\n\n    def __init__(self, path):\n        # Remove Control character\n        path = utils.remove_control_char(path)\n        self.path = path\n        self.info_path = join(self.path, 'Info.plist')\n        if not exists(self.info_path):\n            raise NotMatched(\"no Info.plist found; probably not a bundle\")\n        self.info = biplist.readPlist(self.info_path)\n        self.orig_info = None\n        if not is_info_plist_native(self.info):\n            # while we should probably not allow this *or* add it ourselves, it appears to work without it\n            log.debug(u\"Missing/invalid CFBundleSupportedPlatforms value in {}\".format(self.info_path))\n        # will be added later\n        self.seal_path = None\n\n    def get_entitlements_path(self):\n        return self.entitlements_path\n\n    def get_executable_path(self):\n        \"\"\" Path to the main executable. For an app, this is app itself. For\n            a Framework, this is the main framework \"\"\"\n        executable_name = None\n        if 'CFBundleExecutable' in self.info:\n            executable_name = self.info['CFBundleExecutable']\n        else:\n            executable_name, _ = splitext(basename(self.path))\n        executable_name = utils.remove_control_char(executable_name)\n        executable = join(self.path, executable_name)\n        if not exists(executable):\n            raise Exception(\n                'could not find executable for {0}'.format(self.path))\n        return executable\n\n    def update_info_props(self, new_props):\n        if self.orig_info is None:\n            self.orig_info = copy.deepcopy(self.info)\n\n        changed = False\n        if ('CFBundleIdentifier' in new_props and\n                'CFBundleURLTypes' in self.info and\n                'CFBundleURLTypes' not in new_props):\n            # The bundle identifier changed. Check CFBundleURLTypes for\n            # CFBundleURLName values matching the old bundle\n            # id if it's not being set explicitly\n            old_bundle_id = self.info['CFBundleIdentifier']\n            new_bundle_id = new_props['CFBundleIdentifier']\n            for url_type in self.info['CFBundleURLTypes']:\n                if 'CFBundleURLName' not in url_type:\n                    continue\n                if url_type['CFBundleURLName'] == old_bundle_id:\n                    url_type['CFBundleURLName'] = new_bundle_id\n                    changed = True\n\n        for key, val in new_props.iteritems():\n            is_new_key = key not in self.info\n            if is_new_key or self.info[key] != val:\n                if is_new_key:\n                    log.warn(\"Adding new Info.plist key: {}\".format(key))\n                self.info[key] = val\n                changed = True\n\n        if changed:\n            biplist.writePlist(self.info, self.info_path, binary=True)\n        else:\n            self.orig_info = None\n\n    def info_props_changed(self):\n        return self.orig_info is not None\n\n    def info_prop_changed(self, key):\n        if not self.orig_info:\n            # No props have been changed\n            return False\n        if key in self.info and key in self.orig_info and self.info[key] == self.orig_info[key]:\n            return False\n        return True\n\n    def get_info_prop(self, key):\n        return self.info[key]\n\n    def sign_dylibs(self, signer, path):\n        \"\"\" Sign all the dylibs in this directory \"\"\"\n        for dylib_path in glob.glob(join(path, '*.dylib')):\n            dylib = signable.Dylib(self, dylib_path, signer)\n            dylib.sign(self, signer)\n\n    def sign(self, signer):\n        \"\"\" Sign everything in this bundle, recursively with sub-bundles \"\"\"\n        # log.debug(\"SIGNING: %s\" % self.path)\n        frameworks_path = join(self.path, 'Frameworks')\n        if exists(frameworks_path):\n            # log.debug(\"SIGNING FRAMEWORKS: %s\" % frameworks_path)\n            # sign all the frameworks\n            for framework_name in os.listdir(frameworks_path):\n                framework_path = join(frameworks_path, framework_name)\n                # log.debug(\"checking for framework: %s\" % framework_path)\n                try:\n                    framework = Framework(framework_path)\n                    # log.debug(\"resigning: %s\" % framework_path)\n                    framework.resign(signer)\n                except NotMatched:\n                    # log.debug(\"not a framework: %s\" % framework_path)\n                    continue\n            # sign all the dylibs under Frameworks\n            self.sign_dylibs(signer, frameworks_path)\n\n        # sign any dylibs in the main directory (rare, but it happens)\n        self.sign_dylibs(signer, self.path)\n\n        plugins_path = join(self.path, 'PlugIns')\n        if exists(plugins_path):\n            # sign the appex executables\n            appex_paths = glob.glob(join(plugins_path, '*.appex'))\n            for appex_path in appex_paths:\n                plist_path = join(appex_path, 'Info.plist')\n                if not exists(plist_path):\n                    continue\n                plist = biplist.readPlist(plist_path)\n                appex_exec_path = join(appex_path, plist['CFBundleExecutable'])\n                appex = signable.Appex(self, appex_exec_path, signer)\n                appex.sign(self, signer)\n\n        # then create the seal\n        # TODO maybe the app should know what its seal path should be...\n        self.seal_path = code_resources.make_seal(self.get_executable_path(),\n                                                  self.path)\n        # then sign the app\n        executable = self.signable_class(self, self.get_executable_path(), signer)\n        executable.sign(self, signer)\n\n    def resign(self, signer):\n        \"\"\" signs bundle, modifies in place \"\"\"\n        self.sign(signer)\n        log.debug(\"Resigned bundle at <%s>\", self.path)\n\n\nclass Framework(Bundle):\n    \"\"\" A bundle that comprises reusable code. Similar to an app in that it has\n        its own resources and metadata. Not like an app because the main executable\n        doesn't have Entitlements, or an Application hash, and it doesn't have its\n        own provisioning profile. \"\"\"\n\n    # the executable in this bundle will be a Framework\n    signable_class = signable.Framework\n\n    def __init__(self, path):\n        super(Framework, self).__init__(path)\n\n\nclass App(Bundle):\n    \"\"\" The kind of bundle that is visible as an app to the user.\n        Contains the provisioning profile, entitlements, etc.  \"\"\"\n\n    # the executable in this bundle will be an Executable (i.e. the main\n    # executable of an app)\n    signable_class = signable.Executable\n\n    def __init__(self, path):\n        super(App, self).__init__(path)\n        self.entitlements_path = join(self.path,\n                                      'Entitlements.plist')\n        self.provision_path = join(self.path,\n                                   'embedded.mobileprovision')\n\n    def provision(self, provision_path):\n        shutil.copyfile(provision_path, self.provision_path)\n\n    @staticmethod\n    def extract_entitlements(provision_path):\n        \"\"\" Given a path to a provisioning profile, return the entitlements\n            encoded therein \"\"\"\n        cmd = [\n            'smime',\n            '-inform', 'der',\n            '-verify',    # verifies content, prints verification status to STDERR,\n                          #  outputs content to STDOUT. In our case, will be an XML plist\n            '-noverify',  # accept self-signed certs. Not the opposite of -verify!\n            '-in', provision_path\n        ]\n        # this command always prints 'Verification successful' to stderr.\n        (profile_text, err) = openssl_command(cmd, data=None, expect_err=True)\n        if err and err.strip() != 'Verification successful':\n            log.error('Received unexpected error from openssl: {}'.format(err))\n        plist_dict = biplist.readPlistFromString(profile_text)\n        if 'Entitlements' not in plist_dict:\n            log.debug('failed to get entitlements in provisioning profile')\n            raise Exception('could not find Entitlements in {}'.format(provision_path))\n        return plist_dict['Entitlements']\n\n    def write_entitlements(self, entitlements):\n        \"\"\" Write entitlements to self.entitlements_path. This actually doesn't matter\n            to the app, it's just used later on by other parts of the signing process. \"\"\"\n        biplist.writePlist(entitlements, self.entitlements_path, binary=False)\n        log.debug(\"wrote Entitlements to {0}\".format(self.entitlements_path))\n\n    def resign(self, signer, provisioning_profile, alternate_entitlements_path=None):\n        \"\"\" signs app in place \"\"\"\n\n        # TODO all this mucking about with entitlements feels wrong. The entitlements_path is\n        # not actually functional, it's just a way of passing it to later stages of signing.\n        # Maybe we should determine entitlements data in isign/archive.py or even isign/isign.py,\n        # and then embed it into Signer?\n\n        # In the typical case, we add entitlements from the pprof into the app's signature\n        if alternate_entitlements_path is None:\n            # copy the provisioning profile in\n            self.provision(provisioning_profile)\n\n            entitlements = self.extract_entitlements(provisioning_profile)\n        else:\n            log.info(\"signing with alternative entitlements: {}\".format(alternate_entitlements_path))\n            entitlements = biplist.readPlist(alternate_entitlements_path)\n        self.write_entitlements(entitlements)\n\n        # actually resign this bundle now\n        super(App, self).resign(signer)\n"
  },
  {
    "path": "isign/code_resources.py",
    "content": "# -*- coding: utf-8 -*-\nimport binascii\nimport copy\nimport hashlib\nimport logging\nfrom memoizer import memoize\nimport os\nimport plistlib\nfrom plistlib import PlistWriter\nimport re\n\nOUTPUT_DIRECTORY = '_CodeSignature'\nOUTPUT_FILENAME = 'CodeResources'\nTEMPLATE_FILENAME = 'code_resources_template.xml'\n# DIGEST_ALGORITHM = \"sha1\"\nHASH_BLOCKSIZE = 65536\n\nlog = logging.getLogger(__name__)\n\n\n# have to monkey patch Plist, in order to make the values\n# look the same - no .0 for floats\n# Apple's plist utils work like this:\n#   1234.5 --->  <real>1234.5</real>\n#   1234.0 --->  <real>1234</real>\ndef writeValue(self, value):\n    if isinstance(value, float):\n        rep = repr(value)\n        if value.is_integer():\n            rep = repr(int(value))\n        self.simpleElement(\"real\", rep)\n    else:\n        self.oldWriteValue(value)\n\nPlistWriter.oldWriteValue = PlistWriter.writeValue\nPlistWriter.writeValue = writeValue\n\n\n# Simple reimplementation of ResourceBuilder, in the Apple Open Source\n# file bundlediskrep.cpp\nclass PathRule(object):\n    OPTIONAL = 0x01\n    OMITTED = 0x02\n    NESTED = 0x04\n    EXCLUSION = 0x10  # unused?\n    TOP = 0x20        # unused?\n\n    def __init__(self, pattern='', properties=None):\n        # on Mac OS the FS is case-insensitive; simulate that here\n        self.pattern = re.compile(pattern, re.IGNORECASE)\n        self.flags = 0\n        self.weight = 0\n        if properties is not None:\n            if type(properties) == 'bool':\n                if properties is False:\n                    self.flags |= PathRule.OMITTED\n                # if it was true, this file is required;\n                # do nothing\n            elif isinstance(properties, dict):\n                for key, value in properties.iteritems():\n                    if key == 'optional' and value is True:\n                        self.flags |= PathRule.OPTIONAL\n                    elif key == 'omit' and value is True:\n                        self.flags |= PathRule.OMITTED\n                    elif key == 'nested' and value is True:\n                        self.flags |= PathRule.NESTED\n                    elif key == 'weight':\n                        self.weight = float(value)\n\n    def is_optional(self):\n        return self.flags & PathRule.OPTIONAL != 0\n\n    def is_omitted(self):\n        return self.flags & PathRule.OMITTED != 0\n\n    def is_nested(self):\n        return self.flags & PathRule.NESTED != 0\n\n    def is_exclusion(self):\n        return self.flags & PathRule.EXCLUSION != 0\n\n    def is_top(self):\n        return self.flags & PathRule.TOP != 0\n\n    def matches(self, path):\n        return re.match(self.pattern, path)\n\n    def __str__(self):\n        return 'PathRule:' + str(self.flags) + ':' + str(self.weight)\n\n\nclass ResourceBuilder(object):\n    NULL_PATH_RULE = PathRule()\n\n    def __init__(self, app_path, rules_data, respect_omissions=False, include_sha256=False):\n        self.app_path = app_path\n        self.app_dir = os.path.dirname(app_path)\n        self.rules = []\n        self.respect_omissions = respect_omissions\n        self.include_sha256 = include_sha256\n        for pattern, properties in rules_data.iteritems():\n            self.rules.append(PathRule(pattern, properties))\n\n    def find_rule(self, path):\n        best_rule = ResourceBuilder.NULL_PATH_RULE\n        for rule in self.rules:\n            # log.debug('trying rule ' + str(rule) + ' against ' + path)\n            if rule.matches(path):\n                if rule.flags and rule.is_exclusion():\n                    best_rule = rule\n                    break\n                elif rule.weight > best_rule.weight:\n                    best_rule = rule\n        return best_rule\n\n    def get_rule_and_paths(self, root, path):\n        path = os.path.join(root, path)\n        relative_path = os.path.relpath(path, self.app_dir)\n        rule = self.find_rule(relative_path)\n        return (rule, path, relative_path)\n\n    def scan(self):\n        \"\"\"\n        Walk entire directory, compile mapping\n        path relative to source_dir -> digest and other data\n        \"\"\"\n        file_entries = {}\n        # rule_debug_fmt = \"rule: {0}, path: {1}, relative_path: {2}\"\n        for root, dirs, filenames in os.walk(self.app_dir):\n            # log.debug(\"root: {0}\".format(root))\n            for filename in filenames:\n                rule, path, relative_path = self.get_rule_and_paths(root,\n                                                                    filename)\n                # log.debug(rule_debug_fmt.format(rule, path, relative_path))\n\n                # specifically ignore the CodeResources symlink in base directory if it exists (iOS 11+ fix)\n                if relative_path == \"CodeResources\" and os.path.islink(path):\n                    continue\n\n                if rule.is_exclusion():\n                    continue\n\n                if rule.is_omitted() and self.respect_omissions is True:\n                    continue\n\n                if self.app_path == path:\n                    continue\n\n                # in the case of symlinks, we don't calculate the hash but rather add a key for it being a symlink\n                if os.path.islink(path):\n                    # omit symlinks from files, leave in files2\n                    if not self.respect_omissions:\n                        continue\n                    val = {'symlink': os.readlink(path)}\n                else:\n                    # the Data element in plists is base64-encoded\n                    val = {'hash': plistlib.Data(get_hash_binary(path))}\n                    if self.include_sha256:\n                        val['hash2'] = plistlib.Data(get_hash_binary(path, 'sha256'))\n\n                if rule.is_optional():\n                    val['optional'] = True\n\n                if len(val) == 1 and 'hash' in val:\n                    file_entries[relative_path] = val['hash']\n                else:\n                    file_entries[relative_path] = val\n\n            for dirname in dirs:\n                rule, path, relative_path = self.get_rule_and_paths(root,\n                                                                    dirname)\n\n                if rule.is_nested() and '.' not in path:\n                    dirs.remove(dirname)\n                    continue\n\n                if relative_path == OUTPUT_DIRECTORY:\n                    dirs.remove(dirname)\n\n        return file_entries\n\n\ndef get_template():\n    \"\"\"\n    Obtain the 'template' plist which also contains things like\n    default rules about which files should count\n    \"\"\"\n    current_dir = os.path.dirname(os.path.abspath(__file__))\n    template_path = os.path.join(current_dir, TEMPLATE_FILENAME)\n    fh = open(template_path, 'r')\n    return plistlib.readPlist(fh)\n\n\n@memoize\ndef get_hash_hex(path, hash_type='sha1'):\n    \"\"\" Get the hash of a file at path, encoded as hexadecimal \"\"\"\n    if hash_type == 'sha256':\n        hasher = hashlib.sha256()\n    elif hash_type == 'sha1':\n        hasher = hashlib.sha1()\n    else:\n        raise ValueError(\"Incorrect hash type provided: {}\".format(hash_type))\n\n    with open(path, 'rb') as afile:\n        buf = afile.read(HASH_BLOCKSIZE)\n        while len(buf) > 0:\n            hasher.update(buf)\n            buf = afile.read(HASH_BLOCKSIZE)\n    return hasher.hexdigest()\n\n\n@memoize\ndef get_hash_binary(path, hash_type='sha1'):\n    \"\"\" Get the hash of a file at path, encoded as binary \"\"\"\n    return binascii.a2b_hex(get_hash_hex(path, hash_type))\n\n\ndef write_plist(target_dir, plist):\n    \"\"\" Write the CodeResources file \"\"\"\n    output_dir = os.path.join(target_dir, OUTPUT_DIRECTORY)\n    if not os.path.exists(output_dir):\n        os.makedirs(output_dir)\n    output_path = os.path.join(output_dir, OUTPUT_FILENAME)\n    fh = open(output_path, 'w')\n    plistlib.writePlist(plist, fh)\n    return output_path\n\n\ndef make_seal(source_app_path, target_dir=None):\n    \"\"\"\n    Given a source app, create a CodeResources file for the\n    surrounding directory, and write it into the appropriate path in a target\n    directory\n    \"\"\"\n    if target_dir is None:\n        target_dir = os.path.dirname(source_app_path)\n    template = get_template()\n    # n.b. code_resources_template not only contains a template of\n    # what the file should look like; it contains default rules\n    # deciding which files should be part of the seal\n    rules = template['rules']\n    plist = copy.deepcopy(template)\n    resource_builder = ResourceBuilder(source_app_path, rules, respect_omissions=False)\n    plist['files'] = resource_builder.scan()\n    rules2 = template['rules2']\n    resource_builder2 = ResourceBuilder(source_app_path, rules2, respect_omissions=True, include_sha256=True)\n    plist['files2'] = resource_builder2.scan()\n    return write_plist(target_dir, plist)\n"
  },
  {
    "path": "isign/code_resources_template.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>files</key>\n\t<dict>\n\t</dict>\n\t<key>rules</key>\n\t<dict>\n\t\t<key>^.*</key>\n\t\t<true/>\n\t\t<key>^.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^version.plist$</key>\n\t\t<true/>\n\t</dict>\n\t<key>rules2</key>\n\t<dict>\n\t\t<key>.*\\.dSYM($|/)</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>11</real>\n\t\t</dict>\n\t\t<key>^(.*/)?\\.DS_Store$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>2000</real>\n\t\t</dict>\n\t\t<key>^.*</key>\n\t\t<true/>\n\t\t<key>^.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Base\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>1010</real>\n\t\t</dict>\n\t\t<key>^Info\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^PkgInfo$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^embedded\\.provisionprofile$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^version\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "isign/codesig.py",
    "content": "# -*- coding: utf-8 -*-\nfrom abc import ABCMeta\nimport construct\nimport hashlib\nimport logging\nimport macho_cs\n\nimport utils\n\nlog = logging.getLogger(__name__)\n\n\n# See the documentation for an explanation of how\n# CodeDirectory slots work.\nclass CodeDirectorySlot(object):\n    __metaclass__ = ABCMeta\n    offset = None\n\n    def __init__(self, codesig):\n        self.codesig = codesig\n\n    def get_hash(self, hash_algorithm):\n        if hash_algorithm == \"sha1\":\n            return hashlib.sha1(self.get_contents()).digest()\n        elif hash_algorithm == \"sha256\":\n            return hashlib.sha256(self.get_contents()).digest()\n        else:\n            raise ValueError('Incorrect hash algorith {}'.format(hash_algorithm))\n\nclass DerEntitlementsSlot(CodeDirectorySlot):\n    offset = -7\n\n    def get_contents(self):\n        blobs = self.codesig.get_blobs('CSMAGIC_DER_ENTITLEMENT', min_expected=1, max_expected=1)\n        return self.codesig.get_blob_data(blobs[0])\n\n\nclass EntitlementsSlot(CodeDirectorySlot):\n    offset = -5\n\n    def get_contents(self):\n        blobs = self.codesig.get_blobs('CSMAGIC_ENTITLEMENT', min_expected=1, max_expected=1)\n        return self.codesig.get_blob_data(blobs[0])\n\n\nclass ApplicationSlot(CodeDirectorySlot):\n    offset = -4\n\n    def get_hash(self, hash_algorithm):\n        if hash_algorithm == \"sha1\":\n            hash_length = 20\n        elif hash_algorithm == \"sha256\":\n            hash_length = 32\n        else:\n            raise ValueError('Incorrect hash algorith {}'.format(hash_algorithm))\n        return '\\x00' * hash_length\n\n\nclass ResourceDirSlot(CodeDirectorySlot):\n    offset = -3\n\n    def __init__(self, seal_path):\n        self.seal_path = seal_path\n\n    def get_contents(self):\n        return open(self.seal_path, \"rb\").read()\n\n\nclass RequirementsSlot(CodeDirectorySlot):\n    offset = -2\n\n    def get_contents(self):\n        blobs = self.codesig.get_blobs('CSMAGIC_REQUIREMENTS', min_expected=1, max_expected=1)\n        return self.codesig.get_blob_data(blobs[0])\n\n\nclass InfoSlot(CodeDirectorySlot):\n    offset = -1\n\n    def __init__(self, info_path):\n        self.info_path = info_path\n\n    def get_contents(self):\n        return open(self.info_path, \"rb\").read()\n\n\n# Represents a code signature object, aka the LC_CODE_SIGNATURE,\n# within the Signable\nclass Codesig(object):\n    \"\"\" wrapper around construct for code signature \"\"\"\n    def __init__(self, signable, data):\n        self.signable = signable\n        self.construct = macho_cs.Blob.parse(data)\n        self.is_sha256 = len(self.construct.data.BlobIndex) >= 6\n\n    def is_sha256_signature(self):\n        return self.is_sha256\n\n    def build_data(self):\n        return macho_cs.Blob.build(self.construct)\n\n    def get_blobs(self, magic, min_expected=None, max_expected=None):\n        \"\"\" get the blobs corresponding to the magic value from the blob index \"\"\"\n        blobs = []\n        for index in self.construct.data.BlobIndex:\n            if index.blob.magic == magic:\n                blobs.append(index.blob)\n\n        if min_expected != None and len(blobs) < min_expected:\n            raise KeyError(\"\"\"The number of slots in blob index for magic '{}' was less than\n                the minimum expected ({})\"\"\".format(magic, min_expected))\n\n        if max_expected != None and len(blobs) > max_expected:\n            raise KeyError(\"\"\"The number of slots in blob index for magic '{}' was more than\n                the maximum expected ({})\"\"\".format(magic, max_expected))\n\n\n        return blobs\n\n    def get_blob_data(self, blob):\n        \"\"\" convenience method, if we just want the data \"\"\"\n        return macho_cs.Blob_.build(blob)\n\n    def set_entitlements(self, entitlements_path):\n        # log.debug(\"entitlements:\")\n        try:\n            entitlements_blobs = self.get_blobs('CSMAGIC_ENTITLEMENT', min_expected=1, max_expected=1)\n            entitlements = entitlements_blobs[0]\n            # log.debug(\"found entitlements slot in the image\")\n        except KeyError:\n            # log.debug(\"no entitlements found\")\n            pass\n        else:\n            # make entitlements data if slot was found\n            # libraries do not have entitlements data\n            # so this is actually a difference between libs and apps\n            # entitlements_data = macho_cs.Blob_.build(entitlements)\n            # log.debug(hashlib.sha1(entitlements_data).hexdigest())\n\n            log.debug(\"using entitlements at path: {}\".format(entitlements_path))\n            entitlements.bytes = open(entitlements_path, \"rb\").read()\n            entitlements.length = len(entitlements.bytes) + 8\n\n    def set_requirements(self, signer):\n        # log.debug(\"requirements:\")\n        requirements_blobs = self.get_blobs('CSMAGIC_REQUIREMENTS', min_expected=1, max_expected=1)\n        requirements = requirements_blobs[0]\n        # requirements_data = macho_cs.Blob_.build(requirements)\n        # log.debug(hashlib.sha1(requirements_data).hexdigest())\n\n        signer_cn = signer.get_common_name()\n\n        # this is for convenience, a reference to the first blob\n        # structure within requirements, which contains the data\n        # we are going to change\n        req_blob_0 = requirements.data.BlobIndex[0].blob\n        req_blob_0_original_length = req_blob_0.length\n\n        if self.signable.get_changed_bundle_id():\n            # Set the bundle id if it changed\n            try:\n                bundle_struct = req_blob_0.data.expr.data[0].data\n                bundle_struct.data = self.signable.get_changed_bundle_id()\n                bundle_struct.length = len(bundle_struct.data)\n            except Exception:\n                log.debug(\"could not set bundle id\")\n\n        try:\n            cn = req_blob_0.data.expr.data[1].data[1].data[0].data[2].Data\n        except Exception:\n            log.debug(\"no signer CN rule found in requirements\")\n            log.debug(requirements)\n        else:\n            # if we could find a signer CN rule, make requirements.\n\n            # first, replace old signer CN with our own\n            cn.data = signer_cn\n            cn.length = len(cn.data)\n\n            # req_blob_0 contains that CN, so rebuild it, and get what\n            # the length is now\n            req_blob_0.bytes = macho_cs.Requirement.build(req_blob_0.data)\n            req_blob_0.length = len(req_blob_0.bytes) + 8\n\n            # fix offsets of later blobs in requirements\n            offset_delta = req_blob_0.length - req_blob_0_original_length\n            for bi in requirements.data.BlobIndex[1:]:\n                bi.offset += offset_delta\n\n            # rebuild requirements, and set length for whole thing\n            requirements.bytes = macho_cs.Entitlements.build(requirements.data)\n            requirements.length = len(requirements.bytes) + 8\n\n        # then rebuild the whole data, but just to show the digest...?\n        # requirements_data = macho_cs.Blob_.build(requirements)\n        # log.debug(hashlib.sha1(requirements_data).hexdigest())\n\n    def get_codedirectory_hash_index(self, slot, code_directory):\n        \"\"\" The slots have negative offsets, because they start from the 'top'.\n            So to get the actual index, we add it to the length of the\n            slots. \"\"\"\n        return slot.offset + code_directory.data.nSpecialSlots\n\n    def has_codedirectory_slot(self, slot, code_directory):\n        \"\"\" Some dylibs have all 5 slots, even though technically they only need\n            the first 2. If this dylib only has 2 slots, some of the calculated\n            indices for slots will be negative. This means we don't do\n            those slots when resigning (for dylibs, they don't add any\n            security anyway) \"\"\"\n        return self.get_codedirectory_hash_index(slot, code_directory) >= 0\n\n    def fill_codedirectory_slot(self, slot, code_directory, hash_algorithm):\n        if self.signable.should_fill_slot(self, slot):\n            index = self.get_codedirectory_hash_index(slot, code_directory)\n            code_directory.data.hashes[index] = slot.get_hash(hash_algorithm)\n\n    def set_codedirectories(self, seal_path, info_path, signer):\n        cd = self.get_blobs('CSMAGIC_CODEDIRECTORY', min_expected=1, max_expected=2)\n        changed_bundle_id = self.signable.get_changed_bundle_id()\n\n        hash_size_sha_mapping = { 32: 'sha256', 20: 'sha1' }\n\n        for i, code_directory in enumerate(cd):\n            hash_algorithm = hash_size_sha_mapping.get(code_directory.data.hashSize)\n\n            if self.has_codedirectory_slot(EntitlementsSlot, code_directory):\n                self.fill_codedirectory_slot(EntitlementsSlot(self), code_directory, hash_algorithm)\n\n            if self.has_codedirectory_slot(ResourceDirSlot, code_directory):\n                self.fill_codedirectory_slot(ResourceDirSlot(seal_path), code_directory, hash_algorithm)\n\n            if self.has_codedirectory_slot(RequirementsSlot, code_directory):\n                self.fill_codedirectory_slot(RequirementsSlot(self), code_directory, hash_algorithm)\n\n            if self.has_codedirectory_slot(ApplicationSlot, code_directory):\n                self.fill_codedirectory_slot(ApplicationSlot(self), code_directory, hash_algorithm)\n\n            if self.has_codedirectory_slot(InfoSlot, code_directory):\n                self.fill_codedirectory_slot(InfoSlot(info_path), code_directory, hash_algorithm)\n\n            if self.has_codedirectory_slot(DerEntitlementsSlot, code_directory):\n                self.fill_codedirectory_slot(DerEntitlementsSlot(self), code_directory, hash_algorithm)\n\n            code_directory.data.teamID = signer.team_id\n\n            if changed_bundle_id:\n                offset_change = len(changed_bundle_id) - len(code_directory.data.ident)\n                code_directory.data.ident = changed_bundle_id\n                code_directory.data.hashOffset += offset_change\n                if code_directory.data.teamIDOffset == None:\n                    code_directory.data.teamIDOffset = offset_change\n                else:\n                    code_directory.data.teamIDOffset += offset_change\n                code_directory.length += offset_change\n\n            code_directory.bytes = macho_cs.CodeDirectory.build(code_directory.data)\n            # cd_data = macho_cs.Blob_.build(cd)\n            # log.debug(len(cd_data))\n            # open(\"cdrip\", \"wb\").write(cd_data)\n            # log.debug(\"CDHash:\" + hashlib.sha1(cd_data).hexdigest())\n\n    def set_signature(self, signer):\n        # TODO how do we even know this blobwrapper contains the signature?\n        # seems like this is a coincidence of the structure, where\n        # it's the only blobwrapper at that level...\n        # log.debug(\"sig:\")\n        blob_wrappers = self.get_blobs('CSMAGIC_BLOBWRAPPER', min_expected=1, max_expected=1)\n        sigwrapper = blob_wrappers[0]\n\n        # oldsig = sigwrapper.bytes.value\n        # signer._log_parsed_asn1(sigwrapper.data.data.value)\n        # open(\"sigrip.der\", \"wb\").write(sigwrapper.data.data.value)\n\n        code_directories = self.get_blobs('CSMAGIC_CODEDIRECTORY', min_expected=1, max_expected=2)\n        cd_data = self.get_blob_data(code_directories[0])\n        sig = signer.sign(cd_data, 'sha1')\n        # log.debug(\"sig len: {0}\".format(len(sig)))\n        # log.debug(\"old sig len: {0}\".format(len(oldsig)))\n        # open(\"my_sigrip.der\", \"wb\").write(sig)\n        sigwrapper.data = construct.Container(data=sig)\n        # signer._log_parsed_asn1(sig)\n        # sigwrapper.data = construct.Container(data=\"hahaha\")\n        sigwrapper.length = len(sigwrapper.data.data) + 8\n        sigwrapper.bytes = sigwrapper.data.data\n        # log.debug(len(sigwrapper.bytes))\n\n    def update_offsets(self):\n        # update section offsets, to account for any length changes\n        offset = self.construct.data.BlobIndex[0].offset\n        for blob in self.construct.data.BlobIndex:\n            blob.offset = offset\n            blob_data = macho_cs.Blob.build(blob.blob)\n            offset += len(blob_data)\n\n        superblob = macho_cs.SuperBlob.build(self.construct.data)\n        self.construct.length = len(superblob) + 8\n        self.construct.bytes = superblob\n\n    def resign(self, bundle, signer):\n        \"\"\" Do the actual signing. Create the structre and then update all the\n            byte offsets \"\"\"\n        codedirs = self.get_blobs('CSMAGIC_CODEDIRECTORY', min_expected=1, max_expected=2)\n\n        # TODO - the way entitlements are handled is a code smell\n        # 1 - We're doing a hasattr to detect whether it's a top-level app. isinstance(App, bundle) ?\n        # 2 - unlike the seal_path and info_path, the entitlements_path is not functional. Apps are verified\n        #     based on the entitlements encoded into the code signature and slots and MAYBE the pprof.\n        # Possible refactor - make entitlements data part of Signer rather than Bundle?\n        if hasattr(bundle, 'entitlements_path') and bundle.entitlements_path is not None:\n            self.set_entitlements(bundle.entitlements_path)\n        self.set_requirements(signer)\n        # See docs/codedirectory.rst for some notes on optional hashes\n        self.set_codedirectories(bundle.seal_path, bundle.info_path, signer)\n        self.set_signature(signer)\n        self.update_offsets()\n\n    # TODO make this optional, in case we want to check hashes or something\n    # log.debug(hashes)\n    # cd = codesig_cons.data.BlobIndex[0].blob.data\n    # end_offset = arch_macho.macho_start + cd.codeLimit\n    # start_offset = ((end_offset + 0xfff) & ~0xfff) - (cd.nCodeSlots * 0x1000)\n\n    # for i in xrange(cd.nSpecialSlots):\n    #    expected = cd.hashes[i]\n    #    log.debug(\"special exp=%s\" % expected.encode('hex'))\n\n    # for i in xrange(cd.nCodeSlots):\n    #     expected = cd.hashes[cd.nSpecialSlots + i]\n    #     f.seek(start_offset + 0x1000 * i)\n    #     actual_data = f.read(min(0x1000, end_offset - f.tell()))\n    #     actual = hashlib.sha1(actual_data).digest()\n    #     log.debug('[%s] exp=%s act=%s' % ()\n    #         ('bad', 'ok ')[expected == actual],\n    #         expected.encode('hex'),\n    #         actual.encode('hex')\n    #     )\n"
  },
  {
    "path": "isign/der_encoder.py",
    "content": "\nimport six\n\nfrom pyasn1.codec.der import encoder\nfrom pyasn1.type import univ\nfrom pyasn1.type import char\n\ndef encode(element):\n    der_object = _turn_into_der_structure(element)\n    return encoder.encode(der_object)\n\ndef _turn_into_der_structure(element):\n    if isinstance(element, dict):\n        set_element = univ.SetOf()\n        for set_index, (element_key,element_value) in enumerate(six.iteritems(element)):\n            entry_sequence = univ.Sequence()\n            entry_sequence[0] = _turn_into_der_structure(element_key)\n            entry_sequence[1] = _turn_into_der_structure(element_value)\n            set_element[set_index] = entry_sequence\n        return set_element\n    elif isinstance(element, list):\n        sequence_element = univ.Sequence()\n        for sequence_index, element_item in enumerate(element):\n            sequence_element[sequence_index] = _turn_into_der_structure(element_item)\n        return sequence_element\n    elif isinstance(element, bool):\n        return univ.Boolean(element)\n    elif isinstance(element, int):\n        return univ.Integer(element)\n    elif isinstance(element, str):\n        return char.UTF8String(element)\n    elif isinstance(element, bytes):\n        return univ.OctetString(element)\n    elif element is None:\n        return univ.Null()\n    else:\n        raise ValueError('Unsupported type for DER: {}'.format(type(element)))\n"
  },
  {
    "path": "isign/exceptions.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\" Some common exceptions \"\"\"\n\n\nclass NotSignable(Exception):\n    \"\"\" superclass for any reason why app shouldn't be\n        signable \"\"\"\n    pass\n\n\nclass NotMatched(Exception):\n    \"\"\" thrown if we can't find any app class for\n        this file path \"\"\"\n    pass\n\n\nclass MissingHelpers(NotSignable):\n    \"\"\" thrown if helper apps are missing \"\"\"\n    pass\n\n\nclass MissingCredentials(Exception):\n    \"\"\" thrown if credentials are missing \"\"\"\n    pass\n\n\nclass ImproperCredentials(Exception):\n    \"\"\" thrown if something looks fishy about credentials \"\"\"\n    pass\n\n\nclass OpenSslFailure(Exception):\n    \"\"\" something is wrong with openssl output \"\"\"\n    pass\n"
  },
  {
    "path": "isign/isign.py",
    "content": "# -*- coding: utf-8 -*-\nimport archive\n# import makesig\nimport exceptions\nimport os\nfrom os.path import dirname, exists, join, realpath\n\n# this comes with the repo\nPACKAGE_ROOT = dirname(realpath(__file__))\nDEFAULT_APPLE_CERT_PATH = join(PACKAGE_ROOT, 'apple_credentials', 'applecerts.pem')\nDEFAULT_CREDENTIAL_FILE_NAMES = {\n    'certificate': 'certificate.pem',\n    'key': 'key.pem',\n    'provisioning_profile': 'isign.mobileprovision'\n}\n\n\nclass NotSignable(Exception):\n    \"\"\" This is just so we don't expose other sorts of exceptions \"\"\"\n    pass\n\n\ndef get_credential_paths(directory, file_names=DEFAULT_CREDENTIAL_FILE_NAMES):\n    \"\"\" Given a directory, return dict of paths to standard\n        credential files \"\"\"\n    paths = {}\n    for (k, file_name) in file_names.iteritems():\n        paths[k] = join(directory, file_name)\n    return paths\n\n\n# We will default to using credentials in a particular\n# directory with well-known names. This is complicated because\n# the old way at Sauce Labs (pre-2017) was:\n#   ~/isign-credentials/mobdev.cert.pem, etc.\n# But the new way that everyone should now use:\n#   ~/.isign/certificate.pem, etc.\nif exists(join(os.environ['HOME'], 'isign-credentials')):\n    DEFAULT_CREDENTIAL_PATHS = get_credential_paths(\n        join(os.environ['HOME'], 'isign-credentials'),\n        {\n            'certificate': 'mobdev.cert.pem',\n            'key': 'mobdev.key.pem',\n            'provisioning_profile': 'mobdev1.mobileprovision'\n        }\n    )\nelse:\n    DEFAULT_CREDENTIAL_PATHS = get_credential_paths(\n        join(os.environ['HOME'], '.isign')\n    )\n\n\ndef resign_with_creds_dir(input_path,\n                          credentials_directory,\n                          **kwargs):\n    \"\"\" Do isign.resign(), but with credential files from this directory \"\"\"\n    kwargs.update(get_credential_paths(credentials_directory))\n    return resign(input_path, **kwargs)\n\n\ndef resign(input_path,\n           apple_cert=DEFAULT_APPLE_CERT_PATH,\n           certificate=DEFAULT_CREDENTIAL_PATHS['certificate'],\n           key=DEFAULT_CREDENTIAL_PATHS['key'],\n           provisioning_profile=DEFAULT_CREDENTIAL_PATHS['provisioning_profile'],\n           output_path=join(os.getcwd(), \"out\"),\n           info_props=None,\n           alternate_entitlements_path=None):\n    \"\"\" Mirrors archive.resign(), put here for convenience, to unify exceptions,\n        and to omit default args \"\"\"\n    try:\n        return archive.resign(input_path,\n                              certificate,\n                              key,\n                              apple_cert,\n                              provisioning_profile,\n                              output_path,\n                              info_props,\n                              alternate_entitlements_path)\n    except exceptions.NotSignable as e:\n        # re-raise the exception without exposing internal\n        # details of how it happened\n        raise NotSignable(e)\n\n\ndef view(input_path):\n    \"\"\" Obtain information about the app \"\"\"\n    try:\n        return archive.view(input_path)\n    except exceptions.NotSignable as e:\n        raise NotSignable(e)\n"
  },
  {
    "path": "isign/macho.py",
    "content": "# -*- coding: utf-8 -*-\n#\n# Constructs to represent various structures\n# in a Mach-O binary.\n#\n# As with all Constructs, can be used for both\n# parsing or emitting (aka building)\n#\n\n\nfrom construct import *\nfrom macho_cs import Blob\n\nUInt32 = ULInt32\nUInt64 = ULInt64\n\nCodeSigRef = Struct(\"codesig\",\n                    UInt32('dataoff'),\n                    UInt32('datasize'),\n                    )\n\nSegment = Struct('segment',\n                                                       PaddedStringAdapter(Bytes('segname', 16)),\n                                                       UInt32('vmaddr'),\n                                                       UInt32('vmsize'),\n                                                       UInt32('fileoff'),\n                                                       UInt32('filesize'),\n                                                       UInt32('maxprot'),\n                                                       UInt32('initprot'),\n                                                       UInt32('nsects'),\n                                                       UInt32('flags'),\n                                                       Rename(\"sections\",\n                                                              Array(lambda ctx: ctx['nsects'],\n                                                                    Struct('Section',\n                                                                           PaddedStringAdapter(Bytes('sectname', 16)),\n                                                                           PaddedStringAdapter(Bytes('segname', 16)),\n                                                                           UInt64('addr'),\n                                                                           UInt64('size'),\n                                                                           UInt32('offset'),\n                                                                           UInt32('align'),\n                                                                           UInt32('reloff'),\n                                                                           UInt32('nreloc'),\n                                                                           UInt32('flags'),\n                                                                           UInt32('reserved1'),\n                                                                           UInt32('reserved2'),\n                                                                           UInt32('reserved3'),\n                                                                           ))),\n                                                       )\n\nSegment64 = Struct('segment',\n                                                       PaddedStringAdapter(Bytes('segname', 16)),\n                                                       UInt64('vmaddr'),\n                                                       UInt64('vmsize'),\n                                                       UInt64('fileoff'),\n                                                       UInt64('filesize'),\n                                                       UInt32('maxprot'),\n                                                       UInt32('initprot'),\n                                                       UInt32('nsects'),\n                                                       UInt32('flags'),\n                                                       Rename(\"sections\",\n                                                              Array(lambda ctx: ctx['nsects'],\n                                                                    Struct('Section',\n                                                                           PaddedStringAdapter(Bytes('sectname', 16)),\n                                                                           PaddedStringAdapter(Bytes('segname', 16)),\n                                                                           UInt64('addr'),\n                                                                           UInt64('size'),\n                                                                           UInt32('offset'),\n                                                                           UInt32('align'),\n                                                                           UInt32('reloff'),\n                                                                           UInt32('nreloc'),\n                                                                           UInt32('flags'),\n                                                                           UInt32('reserved1'),\n                                                                           UInt32('reserved2'),\n                                                                           UInt32('reserved3'),\n                                                                           ))),\n                                                       )\n\nLoadCommand = Struct(\"LoadCommand\",\n                     Enum(UInt32(\"cmd\"),\n                          LC_SEGMENT=0x1,\n                          LC_SYMTAB=0x2,\n                          LC_SYMSEG=0x3,\n                          LC_THREAD=0x4,\n                          LC_UNIXTHREAD=0x5,\n                          LC_LOADFVMLIB=0x6,\n                          LC_IDFVMLIB=0x7,\n                          LC_IDENT=0x8,\n                          LC_FVMFILE=0x9,\n                          LC_PREPAGE=0xa,\n                          LC_DYSYMTAB=0xb,\n                          LC_LOAD_DYLIB=0xc,\n                          LC_ID_DYLIB=0xd,\n                          LC_LOAD_DYLINKER=0xe,\n                          LC_ID_DYLINKER=0xf,\n                          LC_PREBOUND_DYLIB=0x10,\n                          LC_ROUTINES=0x11,\n                          LC_SUB_FRAMEWORK=0x12,\n                          LC_SUB_UMBRELLA=0x13,\n                          LC_SUB_CLIENT=0x14,\n                          LC_SUB_LIBRARY=0x15,\n                          LC_TWOLEVEL_HINTS=0x16,\n                          LC_PREBIND_CKSUM=0x17,\n                          LC_LOAD_WEAK_DYLIB=0x80000018,\n                          LC_SEGMENT_64=0x19,\n                          LC_ROUTINES_64=0x1a,\n                          LC_UUID=0x1b,\n                          LC_RPATH=0x8000001c,\n                          LC_CODE_SIGNATURE=0x1d,\n                          LC_SEGMENT_SPLIT_INFO=0x1e,\n                          LC_REEXPORT_DYLIB=0x8000001f,\n                          LC_LAZY_LOAD_DYLIB=0x20,\n                          LC_ENCRYPTION_INFO=0x21,\n                          LC_DYLD_INFO=0x22,\n                          LC_DYLD_INFO_ONLY=0x80000022,\n                          LC_LOAD_UPWARD_DYLIB=0x80000023,\n                          LC_VERSION_MIN_MACOSX=0x24,\n                          LC_VERSION_MIN_IPHONEOS=0x25,\n                          LC_FUNCTION_STARTS=0x26,\n                          LC_DYLD_ENVIRONMENT=0x27,\n                          LC_MAIN=0x80000028,\n                          LC_DATA_IN_CODE=0x29,\n                          LC_SOURCE_VERSION=0x2a,\n                          LC_DYLIB_CODE_SIGN_DRS=0x2b,\n                          LC_ENCRYPTION_INFO_64=0x2c,\n                          LC_LINKER_OPTION=0x2d,\n                          LC_LINKER_OPTIMIZATION_HINT=0x2e,\n                          LC_VERSION_MIN_TVOS=0x2f,\n                          LC_VERSION_MIN_WATCHOS=0x30,\n                          LC_NOTE=0x31,\n                          LC_BUILD_VERSION=0x32,\n                          LC_DYLD_EXPORTS_TRIE = 0x80000033,\n                          LC_DYLD_CHAINED_FIXUPS = 0x80000034,\n                          LC_FILESET_ENTRY = 0x80000035\n                          ),\n\n                     UInt32(\"cmdsize\"),\n                     Peek(Switch(\"data\", lambda ctx: ctx['cmd'],\n                                 {'LC_SEGMENT': Struct('segment',\n                                                       PaddedStringAdapter(Bytes('segname', 16)),\n                                                       UInt32('vmaddr'),\n                                                       UInt32('vmsize'),\n                                                       UInt32('fileoff'),\n                                                       UInt32('filesize'),\n                                                       UInt32('maxprot'),\n                                                       UInt32('initprot'),\n                                                       UInt32('nsects'),\n                                                       UInt32('flags'),\n                                                       Rename(\"sections\",\n                                                              Array(lambda ctx: ctx['nsects'],\n                                                                    Struct('Section',\n                                                                           PaddedStringAdapter(Bytes('sectname', 16)),\n                                                                           PaddedStringAdapter(Bytes('segname', 16)),\n                                                                           UInt32('addr'),\n                                                                           UInt32('size'),\n                                                                           UInt32('offset'),\n                                                                           UInt32('align'),\n                                                                           UInt32('reloff'),\n                                                                           UInt32('nreloc'),\n                                                                           UInt32('flags'),\n                                                                           UInt32('reserved1'),\n                                                                           UInt32('reserved2'),\n                                                                           ))),\n                                                       ),\n                                  'LC_SEGMENT_64': Segment64,\n                                  'LC_DYLIB_CODE_SIGN_DRS': Struct(\"codesign_drs\",\n                                                                   UInt32('dataoff'),\n                                                                   UInt32('datasize'),\n                                                                   Pointer(lambda ctx: ctx['_']['_']['macho_start'] + ctx['dataoff'], Blob),\n                                                                   ),\n                                  'LC_CODE_SIGNATURE': Struct(\"codesig\",\n                                                              UInt32('dataoff'),\n                                                              UInt32('datasize'),\n                                                              Pointer(lambda ctx: ctx['_']['_']['macho_start'] + ctx['dataoff'], Blob),\n                                                              ),\n                                  }, default=Pass)),\n                     OnDemand(Bytes('bytes', lambda ctx: ctx['cmdsize'] - 8)),\n                     #Probe(),\n                     )\n\nMachO = Struct(\"MachO\",\n               Anchor(\"macho_start\"),\n               Enum(UInt32(\"magic\"),\n                    MH_MAGIC=0xfeedface,\n                    MH_MAGIC_64=0xfeedfacf,\n                    MH_CIGAM_64=0xcffaedfe,\n                    ),\n               UInt32(\"cputype\"),\n               UInt32(\"cpusubtype\"),\n               Enum(UInt32(\"filetype\"),\n                    MH_OBJECT=0x1,\n                    MH_EXECUTE=0x2,\n                    MH_FVMLIB=0x3,\n                    MH_CORE=0x4,\n                    MH_PRELOAD=0x5,\n                    MH_DYLIB=0x6,\n                    MH_DYLINKER=0x7,\n                    MH_BUNDLE=0x8,\n                    MH_DYLIB_STUB=0x9,\n                    MH_DSYM=0xa,\n                    MH_KEXT_BUNDLE=0xb,\n                    _default_=Pass,\n                    ),\n               UInt32(\"ncmds\"),\n               UInt32(\"sizeofcmds\"),\n               FlagsEnum(UInt32(\"flags\"),\n                         MH_NOUNDEFS=0x1,\n                         MH_INCRLINK=0x2,\n                         MH_DYLDLINK=0x4,\n                         MH_BINDATLOAD=0x8,\n                         MH_PREBOUND=0x10,\n                         MH_SPLIT_SEGS=0x20,\n                         MH_LAZY_INIT=0x40,\n                         MH_TWOLEVEL=0x80,\n                         MH_FORCE_FLAT=0x100,\n                         MH_NOMULTIDEFS=0x200,\n                         MH_NOFIXPREBINDING=0x400,\n                         MH_PREBINDABLE=0x800,\n                         MH_ALLMODSBOUND=0x1000,\n                         MH_SUBSECTIONS_VIA_SYMBOLS=0x2000,\n                         MH_CANONICAL=0x4000,\n                         MH_WEAK_DEFINES=0x8000,\n                         MH_BINDS_TO_WEAK=0x10000,\n                         MH_ALLOW_STACK_EXECUTION=0x20000,\n                         MH_ROOT_SAFE=0x40000,\n                         MH_SETUID_SAFE=0x80000,\n                         MH_NO_REEXPORTED_DYLIBS=0x100000,\n                         MH_PIE=0x200000,\n                         MH_DEAD_STRIPPABLE_DYLIB=0x400000,\n                         MH_HAS_TLV_DESCRIPTORS=0x00800000,\n                         MH_NO_HEAP_EXECUTION=0x01000000,\n                         MH_APP_EXTENSION_SAFE=0x02000000,\n                         MH_UNUSED_1=0x04000000,\n                         MH_UNUSED_2=0x08000000,\n                         MH_UNUSED_3=0x10000000,\n                         MH_UNUSED_4=0x20000000,\n                         MH_UNUSED_5=0x40000000,\n                         MH_UNUSED_6=0x80000000,\n                         ),\n               If(lambda ctx: ctx['magic'] in ('MH_MAGIC_64', 'MH_CIGAM_64'), UInt32('reserved')), Rename('commands', Array(lambda ctx: ctx['ncmds'], LoadCommand)))\n\nFatArch = Struct(\"FatArch\",\n                 UBInt32(\"cputype\"),\n                 UBInt32(\"cpusubtype\"),\n                 UBInt32(\"offset\"),\n                 UBInt32(\"size\"),\n                 UBInt32(\"align\"),\n                 Pointer(lambda ctx: ctx['offset'], MachO),\n                 )\n\nFat = Struct(\"Fat\",\n             Const(UBInt32(\"magic\"), 0xcafebabe),\n             UBInt32(\"nfat_arch\"),\n             Array(lambda ctx: ctx['nfat_arch'], FatArch),\n             )\n\nMachoFile = Struct(\"MachoFile\",\n                   Peek(UInt32(\"magic\")),\n                   Switch(\"data\", lambda ctx: ctx['magic'], {0xfeedface: MachO,\n                                                             0xfeedfacf: MachO,\n                                                             0xcffaedfe: MachO,\n                                                             0xcafebabe: Fat,\n                                                             0xbebafeca: Fat,\n                                                             0xc10cdefa: Blob,\n                                                             })\n                   )\n"
  },
  {
    "path": "isign/macho_cs.py",
    "content": "# -*- coding: utf-8 -*-\n#\n# This is a Construct library which represents an\n# LC_CODE_SIGNATURE structure. Like all Construct\n# libraries, can be used for parsing or emitting\n# (Construct calls it 'building')\n#\n\n\nfrom construct import *\nimport plistlib\n\n\nclass PlistAdapter(Adapter):\n    def _encode(self, obj, context):\n        return plistlib.writePlistToString(obj)\n\n    def _decode(self, obj, context):\n        return plistlib.readPlistFromString(obj)\n\n# talk about overdesign.\n# magic is in the blob struct\n\nExpr = LazyBound(\"expr\", lambda: Expr_)\nBlob = LazyBound(\"blob\", lambda: Blob_)\n\nHashes = LazyBound(\"hashes\", lambda: Hashes_)\nHashes_ = Array(lambda ctx: ctx['nSpecialSlots'] + ctx['nCodeSlots'], Bytes(\"hash\", lambda ctx: ctx['hashSize']))\n\nCodeDirectory = Struct(\"CodeDirectory\",\n                       Anchor(\"cd_start\"),\n                       UBInt32(\"version\"),\n                       UBInt32(\"flags\"),\n                       UBInt32(\"hashOffset\"),\n                       UBInt32(\"identOffset\"),\n                       UBInt32(\"nSpecialSlots\"),\n                       UBInt32(\"nCodeSlots\"),\n                       UBInt32(\"codeLimit\"),\n                       UBInt8(\"hashSize\"),\n                       UBInt8(\"hashType\"),\n                       UBInt8(\"spare1\"),\n                       UBInt8(\"pageSize\"),\n                       UBInt32(\"spare2\"),\n                       Pointer(lambda ctx: ctx['cd_start'] - 8 + ctx['identOffset'], CString('ident')),\n                       If(lambda ctx: ctx['version'] >= 0x20100, UBInt32(\"scatterOffset\")),\n                       If(lambda ctx: ctx['version'] >= 0x20200, UBInt32(\"teamIDOffset\")),\n                       If(lambda ctx: ctx['version'] >= 0x20200, Pointer(lambda ctx: ctx['cd_start'] - 8 + ctx['teamIDOffset'], CString('teamID'))),\n\n                       If(lambda ctx: ctx['version'] >= 0x20300, UBInt32(\"spare3\")),\n                       If(lambda ctx: ctx['version'] >= 0x20300, UBInt64(\"codeLimit64\")),\n\n                       If(lambda ctx: ctx['version'] >= 0x20400,UBInt64(\"execSegBase\")),\n                       If(lambda ctx: ctx['version'] >= 0x20400,UBInt64(\"execSegLimit\")),\n                       If(lambda ctx: ctx['version'] >= 0x20400,UBInt64(\"execSegFlags\")),\n\n                       Pointer(lambda ctx: ctx['cd_start'] - 8 + ctx['hashOffset'] - ctx['hashSize'] * ctx['nSpecialSlots'], Hashes)\n                       )\n\nData = Struct(\"Data\",\n              UBInt32(\"length\"),\n              Bytes(\"data\", lambda ctx: ctx['length']),\n              Padding(lambda ctx: -ctx['length'] & 3),\n              )\n\nCertSlot = Enum(UBInt32(\"slot\"),\n                anchorCert=-1,\n                leafCert=0,\n                _default_=Pass,\n                )\n\nMatch = Struct(\"Match\",\n               Enum(UBInt32(\"matchOp\"),\n                    matchExists=0,\n                    matchEqual=1,\n                    matchContains=2,\n                    matchBeginsWith=3,\n                    matchEndsWith=4,\n                    matchLessThan=5,\n                    matchGreaterThan=6,\n                    matchLessEqual=7,\n                    matchGreaterEqual=8,\n                    ),\n               If(lambda ctx: ctx['matchOp'] != 'matchExists', Data)\n               )\n\nexpr_args = {\n    'opIdent': Data,\n    'opAnchorHash': Sequence(\"AnchorHash\", CertSlot, Data),\n    'opInfoKeyValue': Data,\n    'opAnd': Sequence(\"And\", Expr, Expr),\n    'opOr': Sequence(\"Or\", Expr, Expr),\n    'opNot': Expr,\n    'opCDHash': Data,\n    'opInfoKeyField': Sequence(\"InfoKeyField\", Data, Match),\n    'opEntitlementField': Sequence(\"EntitlementField\", Data, Match),\n    'opCertField': Sequence(\"CertField\", CertSlot, Data, Match),\n    'opCertGeneric': Sequence(\"CertGeneric\", CertSlot, Data, Match),\n    'opTrustedCert': CertSlot,\n}\n\nExpr_ = Struct(\"Expr\",\n               Enum(UBInt32(\"op\"),\n                    opFalse=0,\n                    opTrue=1,\n                    opIdent=2,\n                    opAppleAnchor=3,\n                    opAnchorHash=4,\n                    opInfoKeyValue=5,\n                    opAnd=6,\n                    opOr=7,\n                    opCDHash=8,\n                    opNot=9,\n                    opInfoKeyField=10,\n                    opCertField=11,\n                    opTrustedCert=12,\n                    opTrustedCerts=13,\n                    opCertGeneric=14,\n                    opAppleGenericAnchor=15,\n                    opEntitlementField=16,\n                    ),\n               Switch(\"data\", lambda ctx: ctx['op'],\n                      expr_args,\n                      default=Pass),\n               )\n\nRequirement = Struct(\"Requirement\",\n                     Const(UBInt32(\"kind\"), 1),\n                     Expr,\n                     )\n\nEntitlement = Struct(\"Entitlement\",\n                     # actually a plist\n                     PlistAdapter(Bytes(\"data\", lambda ctx: ctx['_']['length'] - 8)),\n                     )\n\nDerEntitlement = Struct(\"DerEntitlement\",\n                     # actually a plist in binary format\n                     Bytes(\"data\", lambda ctx: ctx['_']['length'] - 8),\n                     )\n\nEntitlementsBlobIndex = Struct(\"BlobIndex\",\n                               Enum(UBInt32(\"type\"),\n                                    kSecHostRequirementType=1,\n                                    kSecGuestRequirementType=2,\n                                    kSecDesignatedRequirementType=3,\n                                    kSecLibraryRequirementType=4,\n                                    ),\n                               UBInt32(\"offset\"),\n                               Pointer(lambda ctx: ctx['_']['sb_start'] - 8 + ctx['offset'], Blob),\n                               )\n\nEntitlements = Struct(\"Entitlements\",  # actually a kind of super blob\n                      Anchor(\"sb_start\"),\n                      UBInt32(\"count\"),\n                      Array(lambda ctx: ctx['count'], EntitlementsBlobIndex),\n                      )\n\nBlobWrapper = Struct(\"BlobWrapper\",\n                     OnDemand(Bytes(\"data\", lambda ctx: ctx['_']['length'] - 8)),\n                     )\n\nBlobIndex = Struct(\"BlobIndex\",\n                   UBInt32(\"type\"),\n                   UBInt32(\"offset\"),\n                   If(lambda ctx: ctx['offset'], Pointer(lambda ctx: ctx['_']['sb_start'] - 8 + ctx['offset'], Blob)),\n                   )\n\nSuperBlob = Struct(\"SuperBlob\",\n                   Anchor(\"sb_start\"),\n                   UBInt32(\"count\"),\n                   Array(lambda ctx: ctx['count'], BlobIndex),\n                   )\n\nBlob_ = Struct(\"Blob\",\n               Enum(UBInt32(\"magic\"),\n                    CSMAGIC_REQUIREMENT=0xfade0c00,\n                    CSMAGIC_REQUIREMENTS=0xfade0c01,\n                    CSMAGIC_CODEDIRECTORY=0xfade0c02,\n                    CSMAGIC_ENTITLEMENT=0xfade7171,  # actually, this is kSecCodeMagicEntitlement, and not defined in the C version\n                    CSMAGIC_DER_ENTITLEMENT=0xfade7172,\n                    CSMAGIC_BLOBWRAPPER=0xfade0b01,  # and this isn't even defined in libsecurity_codesigning; it's in _utilities\n                    CSMAGIC_EMBEDDED_SIGNATURE=0xfade0cc0,\n                    CSMAGIC_DETACHED_SIGNATURE=0xfade0cc1,\n                    CSMAGIC_CODE_SIGN_DRS=0xfade0c05,\n                    _default_=Pass,\n                    ),\n               UBInt32(\"length\"),\n               Peek(Switch(\"data\", lambda ctx: ctx['magic'],\n                           {'CSMAGIC_REQUIREMENT': Requirement,\n                            'CSMAGIC_REQUIREMENTS': Entitlements,\n                            'CSMAGIC_CODEDIRECTORY': CodeDirectory,\n                            'CSMAGIC_ENTITLEMENT': Entitlement,\n                            'CSMAGIC_DER_ENTITLEMENT': DerEntitlement,\n                            'CSMAGIC_BLOBWRAPPER': BlobWrapper,\n                            'CSMAGIC_EMBEDDED_SIGNATURE': SuperBlob,\n                            'CSMAGIC_DETACHED_SIGNATURE': SuperBlob,\n                            'CSMAGIC_CODE_SIGN_DRS': SuperBlob,\n                            })),\n               OnDemand(Bytes('bytes', lambda ctx: ctx['length'] - 8)),\n               )\n"
  },
  {
    "path": "isign/makesig.py",
    "content": "# -*- coding: utf-8 -*-\n# Library to construct an LC_CODE_SIGNATURE construct\n# from scratch. Does not work yet.\n#\n# Abandoned development May 2015 when it became clear that most\n# apps that were uploaded to us would already be signed. But\n# we may need this someday, so preserving here.\n#\n\nimport plistlib\nimport io\nimport construct\nimport hashlib\nimport logging\nimport math\nimport macho\nimport macho_cs\nimport utils\n\nimport der_encoder\n\nlog = logging.getLogger(__name__)\n\n\ndef make_arg(data_type, arg):\n    if data_type.name == 'Data':\n        return construct.Container(data=arg,\n                                   length=len(arg))\n    elif data_type.name.lower() == 'expr':\n        if isinstance(arg, construct.Container):\n            # preserve expressions that are already containerized\n            return arg\n        return make_expr(*arg)\n    elif data_type.name == 'slot':\n        if arg == 'leafCert':\n            return 0\n        return arg\n    elif data_type.name == 'Match':\n        matchOp = arg[0]\n        data = None\n        if len(arg) > 1:\n            data = construct.Container(data=arg[1],\n                                       length=len(arg[1]))\n        return construct.Container(matchOp=matchOp, Data=data)\n    log.debug(data_type)\n    log.debug(data_type.name)\n    log.debug(arg)\n    assert 0\n\n\ndef make_expr(op, *args):\n    full_op = \"op\" + op\n    data = None\n    data_type = macho_cs.expr_args.get(full_op)\n    if isinstance(data_type, macho_cs.Sequence):\n        if len(data_type.subcons) == len(args):\n            data = [make_arg(dt, arg) for dt, arg in zip(data_type.subcons, args)]\n        else:\n            # automatically nest binary operations to accept >2 args\n            data = [make_arg(data_type.subcons[0], args[0]),\n                    make_expr(op, *args[1:])]\n    elif data_type:\n        data = make_arg(data_type, args[0])\n    return construct.Container(op=full_op,\n                               data=data)\n\n\ndef make_requirements(drs, ident, common_name):\n    expr = make_expr(\n        'And',\n        ('Ident', ident),\n        ('AppleGenericAnchor',),\n        ('CertField', 'leafCert', 'subject.CN', ['matchEqual', common_name]),\n        ('CertGeneric', 1, '*\\x86H\\x86\\xf7cd\\x06\\x02\\x01', ['matchExists']))\n    des_req = construct.Container(kind=1, expr=expr)\n    des_req_data = macho_cs.Requirement.build(des_req)\n\n    reqs = construct.Container(\n        sb_start=0,\n        count=1,\n        BlobIndex=[construct.Container(type='kSecDesignatedRequirementType',\n                                       offset=28,\n                                       blob=construct.Container(magic='CSMAGIC_REQUIREMENT',\n                                                                length=len(des_req_data) + 8,\n                                                                data=des_req,\n                                                                bytes=des_req_data))])\n\n    if drs:\n        dr_exprs = []\n        for dr in drs.data.BlobIndex:\n            if dr.blob is not None:\n                dr_exprs.append(dr.blob.data.expr)\n        # make_expr expects at least 2 arguments, need to verify that we pass those in, otherwise just return\n        if len(dr_exprs) > 1:\n            expr = make_expr('Or', *dr_exprs)\n            lib_req = construct.Container(kind=1, expr=expr)\n            lib_req_data = macho_cs.Requirement.build(lib_req)\n\n            reqs.BlobIndex.append(construct.Container(type='kSecLibraryRequirementType',\n                                                      offset=28 + len(des_req_data) + 8,\n                                                      blob=construct.Container(magic='CSMAGIC_REQUIREMENT',\n                                                                               length=len(lib_req_data) + 8,\n                                                                               data=lib_req,\n                                                                               bytes=lib_req_data)))\n            reqs.count += 1\n\n    return reqs\n\n\ndef build_code_directory_blob(hash_algorithm, teamID, ident_for_signature, code_limit, hashes,\n                              exec_segment_offset, exec_segment_limit, is_main_binary):\n    if hash_algorithm == 'sha1':\n        hash_type_value = 1\n        hash_size = 20\n    elif hash_algorithm == 'sha256':\n        hash_type_value = 2\n        hash_size = 32\n    else:\n        raise ValueError(\"Incorrect hash type provided: {}\".format(hash_algorithm))\n\n    for hash in hashes:\n        if len(hash) != hash_size:\n            raise Exception('Incorrect hash {} for length {} ({})'.format(hash, hash_size, len(hash)))\n\n    empty_hash = \"\\x00\" * hash_size\n    special_slots_length = 7\n    # The length of the fields in the CodeDirectory is at least these fiels which are always present.\n    #     CD Magic (4)\n    #     length (4)\n    #     version (4)\n    #     flags (4)\n    #     hashOffset (4)\n    #     identOffset (4)\n    #     nSpecialSlots (4)\n    #     nCodeSlots (4)\n    #     codeLimit (4)\n    #     hashSize (1)\n    #     hashType (1)\n    #     spare1 (1)\n    #     pageSize (1)\n    #     spare (4)\n    #     scatterOffset (4)\n    #     teamIDOffset (4)\n    #     spare3 (4)\n    #     codeLimit64 (8)\n    #     execSegBase (8)\n    #     execSegLimit (8)\n    #     execSegFlags (8)\n    # which in total are 88\n    FIXED_FIELDS_SIZE = 88\n    cd = construct.Container(cd_start=None,\n                             version=0x20400,\n                             flags=0,\n                             identOffset= FIXED_FIELDS_SIZE,\n                             nSpecialSlots=special_slots_length,\n                             nCodeSlots=len(hashes),\n                             codeLimit=code_limit,\n                             hashSize=hash_size,\n                             hashType=hash_type_value,\n                             spare1=0,\n                             pageSize=12, # Page size is indicated as a log in base 2. The size is 0x1000 = 2 ^ 12\n                             spare2=0,\n                             ident=ident_for_signature,\n                             scatterOffset=0,\n                             teamIDOffset= FIXED_FIELDS_SIZE + len(ident_for_signature),\n                             teamID=teamID,\n                             hashOffset= FIXED_FIELDS_SIZE + (hash_size * special_slots_length) + len(ident_for_signature) + len(teamID),\n                             hashes=([empty_hash] * special_slots_length) + hashes,\n                             spare3=0,\n                             codeLimit64=0, # 0 means fallback to codeLimit\n                             execSegBase=exec_segment_offset,\n                             execSegLimit=exec_segment_limit,\n                             execSegFlags=1 if is_main_binary else 0,\n                             )\n    return cd\n\ndef make_basic_codesig(entitlements_file, drs, code_limit, hashes_sha1, hashes_sha256, signer, ident,\n                       exec_segment_offset, exec_segment_limit, is_main_binary):\n    common_name = signer.get_common_name()\n    log.debug(\"ident: {}\".format(ident))\n    log.debug(\"codelimit: {}\".format(code_limit))\n    teamID = signer._get_team_id() + '\\x00'\n    ident_for_signature = ident + '\\x00'\n\n    cd = build_code_directory_blob(\n        hash_algorithm='sha1',\n        teamID=teamID,\n        ident_for_signature=ident_for_signature,\n        code_limit=code_limit,\n        hashes=hashes_sha1,\n        exec_segment_offset=exec_segment_offset,\n        exec_segment_limit=exec_segment_limit,\n        is_main_binary=is_main_binary)\n\n    cd_data = macho_cs.CodeDirectory.build(cd)\n\n    # SHA256 codesignature disabled for now, as it is not correctly implemented and fails on iOS 15.1. For now we are\n    # just adding this switch so we can enable it again once it is properly done. At least, the current signature is not\n    # including a signed attribute with OID 1.2.840.113635.100.9.1 containing a plist with a \"cdhashes\" list (on which\n    # it has the base64 of the SHA1 and first 20 bytes of SHA256). That missing part is probably what is missing.\n    sha256_codesignature_enabled = False\n\n    # Superblob has\n    # magic (4)\n    # size (4)\n    # num of blobs (4)\n    # [blob[n], offset to n ] (4 + 4) repeated for each blob\n    number_of_blobs = 3\n    if sha256_codesignature_enabled:\n        number_of_blobs = 4\n    if entitlements_file != None:\n        number_of_blobs += 2\n    offset = 4 + 4 + 4 + (8 * number_of_blobs)\n\n    cd_index = construct.Container(type=0,\n                                   offset=offset,\n                                   blob=construct.Container(magic='CSMAGIC_CODEDIRECTORY',\n                                                            length=len(cd_data) + 8,\n                                                            data=cd,\n                                                            bytes=cd_data,\n                                                            ))\n\n    offset += cd_index.blob.length\n    reqs_sblob = make_requirements(drs, ident, common_name)\n    reqs_sblob_data = macho_cs.Entitlements.build(reqs_sblob)\n    requirements_index = construct.Container(type=2,\n                                             offset=offset,\n                                             blob=construct.Container(magic='CSMAGIC_REQUIREMENTS',\n                                                                      length=len(reqs_sblob_data) + 8,\n                                                                      data=\"\",\n                                                                      bytes=reqs_sblob_data,\n                                                                      ))\n    offset += requirements_index.blob.length\n\n    entitlements_index = None\n    der_entitlements_index = None\n    if entitlements_file != None:\n        entitlements_bytes = open(entitlements_file, \"rb\").read()\n        entitlements_index = construct.Container(type=5,\n                                                 offset=offset,\n                                                 blob=construct.Container(magic='CSMAGIC_ENTITLEMENT',\n                                                                          length=len(entitlements_bytes) + 8,\n                                                                          data=\"\",\n                                                                          bytes=entitlements_bytes\n                                                                          ))\n        offset += entitlements_index.blob.length\n\n        xml_entitlements_dict = plistlib.readPlist(io.BytesIO(entitlements_bytes))\n        der_entitlements_bytes = der_encoder.encode(xml_entitlements_dict)\n\n        der_entitlements_index = construct.Container(type=7,\n                                                     offset=offset,\n                                                     blob=construct.Container(magic='CSMAGIC_DER_ENTITLEMENT',\n                                                                              length=len(der_entitlements_bytes) + 8,\n                                                                              data=\"\",\n                                                                              bytes=der_entitlements_bytes\n                                                                          ))\n        offset += der_entitlements_index.blob.length\n\n    cd_sha256_index = None\n    if sha256_codesignature_enabled:\n        cd_sha256 = build_code_directory_blob(\n            hash_algorithm='sha256',\n            teamID=teamID,\n            ident_for_signature=ident_for_signature,\n            code_limit=code_limit,\n            hashes=hashes_sha256,\n            exec_segment_offset=exec_segment_offset,\n            exec_segment_limit=exec_segment_limit,\n            is_main_binary=is_main_binary)\n\n        cd_sha256_data = macho_cs.CodeDirectory.build(cd_sha256)\n        cd_sha256_index = construct.Container(type=0x1000,\n                                    offset=offset,\n                                    blob=construct.Container(magic='CSMAGIC_CODEDIRECTORY',\n                                                                length=len(cd_sha256_data) + 8,\n                                                                data=cd_sha256,\n                                                                bytes=cd_sha256_data,\n                                                                ))\n\n        offset += cd_sha256_index.blob.length\n\n    sigwrapper_index = construct.Container(type=65536,\n                                           offset=offset,\n                                           blob=construct.Container(magic='CSMAGIC_BLOBWRAPPER',\n                                                                    length=0 + 8,\n                                                                    data=\"\",\n                                                                    bytes=\"\",\n                                                                    ))\n    indicies = filter(None, [cd_index,\n                requirements_index,\n                entitlements_index,\n                der_entitlements_index,\n                cd_sha256_index,\n                sigwrapper_index])\n\n    superblob = construct.Container(\n        sb_start=0,\n        count=len(indicies),\n        BlobIndex=indicies)\n    data = macho_cs.SuperBlob.build(superblob)\n\n    chunk = macho_cs.Blob.build(construct.Container(\n        magic=\"CSMAGIC_EMBEDDED_SIGNATURE\",\n        length=len(data) + 8,\n        data=data,\n        bytes=data))\n    return macho_cs.Blob.parse(chunk)\n\n\ndef make_signature(arch_macho, arch_offset, arch_size, cmds, f, entitlements_file, codesig_data_length, signer, ident):\n    # NB: arch_offset is absolute in terms of file start.  Everything else is relative to arch_offset!\n\n    # sign from scratch\n    log.debug(\"signing from scratch\")\n\n    drs = None\n    drs_lc = cmds.get('LC_DYLIB_CODE_SIGN_DRS')\n    if drs_lc:\n        drs = drs_lc.data.blob\n\n    codesig_offset = utils.round_up(arch_size, 16)\n\n    # generate code hashes\n    log.debug(\"codesig offset: {}\".format(codesig_offset))\n    codeLimit = codesig_offset\n    log.debug(\"new cL: {}\".format(hex(codeLimit)))\n    nCodeSlots = int(math.ceil(float(codesig_offset) / 0x1000))\n    log.debug(\"new nCS: {}\".format(nCodeSlots))\n\n\n    # generate placeholder LC_CODE_SIGNATURE (like what codesign_allocate does)\n    fake_hashes_sha1 = [\"\\x00\" * 20] * nCodeSlots\n    fake_hashes_sha256 = [\"\\x00\" * 32] * nCodeSlots\n\n    # Initially set to 0 (for fake signature, later on populated).\n    exec_segment_found = False\n    exec_segment_offset = 0\n    exec_segment_limit = 0\n    is_main_binary = 'MH_EXECUTE' in arch_macho.filetype\n    log.debug(\"is_main_binary: {}\".format(nCodeSlots))\n\n    codesig_cons = make_basic_codesig(entitlements_file,\n            drs,\n            codeLimit,\n            fake_hashes_sha1,\n            fake_hashes_sha256,\n            signer,\n            ident,\n            exec_segment_offset,\n            exec_segment_limit,\n            is_main_binary)\n    codesig_data = macho_cs.Blob.build(codesig_cons)\n\n    cmd_data = construct.Container(dataoff=codesig_offset,\n            datasize=codesig_data_length)\n    cmd = construct.Container(cmd='LC_CODE_SIGNATURE',\n            cmdsize=16,\n            data=cmd_data,\n            bytes=macho.CodeSigRef.build(cmd_data))\n\n    log.debug(\"CS blob before: {}\".format(utils.print_structure(codesig_cons, macho_cs.Blob)))\n    log.debug(\"len(codesig_data): {}\".format(len(codesig_data)))\n\n    codesig_length = codesig_data_length\n    log.debug(\"codesig length: {}\".format(codesig_length))\n\n    log.debug(\"old ncmds: {}\".format(arch_macho.ncmds))\n    arch_macho.ncmds += 1\n    log.debug(\"new ncmds: {}\".format(arch_macho.ncmds))\n\n    log.debug(\"old sizeofcmds: {}\".format(arch_macho.sizeofcmds))\n    arch_macho.sizeofcmds += cmd.cmdsize\n    log.debug(\"new sizeofcmds: {}\".format(arch_macho.sizeofcmds))\n\n    arch_macho.commands.append(cmd)\n\n    hashes_sha1 = []\n    hashes_sha256 = []\n    if codesig_data_length > 0:\n        # Patch __LINKEDIT\n        for lc in arch_macho.commands:\n            if lc.cmd == 'LC_SEGMENT_64' or lc.cmd == 'LC_SEGMENT':\n                if (not exec_segment_found) and lc.data.segname == '__TEXT':\n                    # Exec segment offset and limit refer to the first text segment.\n                    exec_segment_offset = lc.data.fileoff\n                    exec_segment_limit = lc.data.filesize\n                    exec_segment_found = True\n                    log.debug('Exec segment found: Offset:{}, limit:{}'.format(exec_segment_offset, exec_segment_limit))\n                if lc.data.segname == '__LINKEDIT':\n                    log.debug(\"found __LINKEDIT, old filesize {}, vmsize {}\".format(lc.data.filesize, lc.data.vmsize))\n\n                    lc.data.filesize = utils.round_up(lc.data.filesize, 16) + codesig_length\n                    if (lc.data.filesize > lc.data.vmsize):\n                        lc.data.vmsize = utils.round_up(lc.data.filesize, 4096)\n\n                    if lc.cmd == 'LC_SEGMENT_64':\n                        lc.bytes = macho.Segment64.build(lc.data)\n                    else:\n                        lc.bytes = macho.Segment.build(lc.data)\n\n                    log.debug(\"new filesize {}, vmsize {}\".format(lc.data.filesize, lc.data.vmsize))\n\n\n        actual_data = macho.MachO.build(arch_macho)\n        log.debug(\"actual_data length with codesig LC {}\".format(len(actual_data)))\n\n        # Now seek to the start of the actual data and read until the end of the arch.\n        f.seek(arch_offset + len(actual_data))\n        bytes_to_read = codesig_offset + arch_offset - f.tell()\n        file_slice = f.read(bytes_to_read)\n        if len(file_slice) < bytes_to_read:\n            log.warn(\"expected {} bytes but got {}, zero padding.\".format(bytes_to_read, len(file_slice)))\n            file_slice += (\"\\x00\" * (bytes_to_read - len(file_slice)))\n        actual_data += file_slice\n\n        for i in xrange(nCodeSlots):\n            actual_data_slice = actual_data[(0x1000 * i):(0x1000 * i + 0x1000)]\n\n            actual_sha1 = hashlib.sha1(actual_data_slice).digest()\n            log.debug(\"Slot {} (File page @{} sha1): {}\".format(i, hex(0x1000 * i), actual_sha1.encode('hex')))\n            hashes_sha1.append(actual_sha1)\n\n            actual_sha256 = hashlib.sha256(actual_data_slice).digest()\n            log.debug(\"Slot {} (File page @{} sha256): {}\".format(i, hex(0x1000 * i), actual_sha256.encode('hex')))\n            hashes_sha256.append(actual_sha256)\n    else:\n        hashes_sha1 = fake_hashes_sha1\n        hashes_sha256 = fake_hashes_sha256\n\n    # Replace placeholder with real one.\n    codesig_cons = make_basic_codesig(entitlements_file,\n            drs,\n            codeLimit,\n            hashes_sha1,\n            hashes_sha256,\n            signer,\n            ident,\n            exec_segment_offset,\n            exec_segment_limit,\n            is_main_binary)\n    codesig_data = macho_cs.Blob.build(codesig_cons)\n    cmd_data = construct.Container(dataoff=codesig_offset,\n            datasize=len(codesig_data))\n    cmd = construct.Container(cmd='LC_CODE_SIGNATURE',\n            cmdsize=16,\n            data=cmd_data,\n            bytes=macho.CodeSigRef.build(cmd_data))\n    arch_macho.commands[-1] = cmd\n    cmds['LC_CODE_SIGNATURE'] = cmd\n    return codesig_data\n"
  },
  {
    "path": "isign/multisign.py",
    "content": "# -*- coding: utf-8 -*-\nfrom os.path import isdir\nimport isign\nfrom archive import archive_factory\nfrom signer import Signer\nimport logging\nimport multiprocessing\n\nlog = logging.getLogger(__name__)\n\nMAX_PROCESSES = multiprocessing.cpu_count()\n\n\ndef resign(args):\n    \"\"\" Given a tuple consisting of a path to an uncompressed archive,\n        credential directory, and desired output path, resign accordingly.\n\n        Returns a tuple of (cred_dir, path to resigned app) \"\"\"\n    ua, cred_dir, resigned_path = args\n\n    try:\n        log.debug('resigning with %s %s -> %s', ua.path, cred_dir, resigned_path)\n        # get the credential files, create the 'signer'\n        credential_paths = isign.get_credential_paths(cred_dir)\n        signer = Signer(signer_cert_file=credential_paths['certificate'],\n                        signer_key_file=credential_paths['key'],\n                        apple_cert_file=isign.DEFAULT_APPLE_CERT_PATH)\n\n        # sign it (in place)\n        ua.bundle.resign(signer, credential_paths['provisioning_profile'])\n\n        log.debug(\"outputing %s\", resigned_path)\n        # and archive it there\n        ua.archive(resigned_path)\n\n    finally:\n        ua.remove()\n\n    return (cred_dir, resigned_path)\n\n\ndef clone_ua(args):\n    original_ua, target_ua_path = args\n    log.debug('cloning %s to %s', original_ua.path, target_ua_path)\n    ua = original_ua.clone(target_ua_path)\n    log.debug('done cloning to %s', original_ua.path)\n    return ua\n\n\ndef multisign(original_path, cred_dirs_to_output_paths, info_props=None):\n    \"\"\" Given a path to an app,\n        a mapping of credential directories to desired output paths,\n        optional info.plist properties to overwrite,\n\n        produce re-signed versions of the app as desired.\n\n        See: multisign_archive, which this wraps.\n\n        Returns an array of tuples of [(credentials_dir, resigned app path)...]\n    \"\"\"\n\n    archive = archive_factory(original_path)\n    if archive is None:\n        log.debug(\"%s didn't look like an app...\", original_path)\n        return None\n\n    return multisign_archive(archive, cred_dirs_to_output_paths, info_props)\n\n\ndef multisign_archive(archive, cred_dirs_to_output_paths, info_props=None):\n    \"\"\" Given an isign.archive object,\n        a mapping of credential directories to desired output paths,\n        optional info.plist properties to overwrite,\n\n        produce re-signed versions of the IPA.\n\n        If info_props are provided, it will overwrite those properties in\n        the app's Info.plist.\n\n        Returns an array of tuples of [(credentials_dir, resigned app path)...]\n    \"\"\"\n\n    # get ready for multiple processes...\n    p = multiprocessing.Pool(MAX_PROCESSES)\n\n    # ua is potentially an isign.archive.UncompressedArchive\n    ua = None\n\n    results = []\n\n    try:\n        ua = archive.unarchive_to_temp()\n        if info_props:\n            # Override info.plist props\n            ua.bundle.update_info_props(info_props)\n\n        # Since the signing process rewrites files, we must first create uncompressed archives\n        # for each credentials_directory.\n        # The first is simply the uncompressed archive we just made\n        uas = [ua]\n\n        # But the rest need to be copied. This might take a while, so let's do it in parallel\n        # this will copy them to /path/to/uncompressedArchive_1, .._2, and so on\n        # and make UncompressedArchive objects that can be used for resigning\n        target_ua_paths = []\n        for i in range(1, len(cred_dirs_to_output_paths)):\n            target_ua_paths.append((ua, ua.path + '_' + str(i)))\n        uas += p.map(clone_ua, target_ua_paths)\n\n        # now we should have one UncompressedArchive for every credential directory\n        assert len(uas) == len(cred_dirs_to_output_paths)\n\n        # We will now construct arguments for all the resignings\n        resign_args = []\n        for i, (cred_dir, output_path) in enumerate(cred_dirs_to_output_paths.items()):\n            resign_args.append((uas[i], cred_dir, output_path))\n        log.debug('resign args: %s', resign_args)\n\n        # In parallel, resign each uncompressed archive with supplied credentials,\n        # and make archives in the desired paths.\n        results = p.map(resign, resign_args)\n\n    except isign.NotSignable as e:\n        msg = \"Not signable: <{0}>: {1}\\n\".format(archive.path, e)\n        log.error(msg)\n        raise\n\n    finally:\n        if ua is not None and isdir(ua.path):\n            ua.remove()\n\n    return results\n"
  },
  {
    "path": "isign/signable.py",
    "content": "# -*- coding: utf-8 -*-\n#\n# Represents a file that can be signed. A file that\n# conforms to the Mach-O ABI.\n#\n# Executable, dylib, or framework.\n#\n\nfrom abc import ABCMeta\nfrom codesig import (Codesig,\n                     EntitlementsSlot,\n                     ResourceDirSlot,\n                     RequirementsSlot,\n                     ApplicationSlot,\n                     DerEntitlementsSlot,\n                     InfoSlot)\nimport logging\nimport macho\nfrom makesig import make_signature\nimport os\nimport tempfile\nimport utils\nimport shutil\n\nlog = logging.getLogger(__name__)\n\n\nclass Signable(object):\n    __metaclass__ = ABCMeta\n\n    slot_classes = []\n\n    def __init__(self, bundle, path, signer):\n        log.debug(\"working on {0}\".format(path))\n        self.bundle = bundle\n        self.path = path\n        self.signer = signer\n\n        self.f = open(self.path, \"rb\")\n        self.f.seek(0, os.SEEK_END)\n        self.file_end = self.f.tell()\n        self.f.seek(0)\n\n        self.m = macho.MachoFile.parse_stream(self.f)\n        self.sign_from_scratch = False\n\n        # may set sign_from_scratch to True\n        self.arches = self._parse_arches()\n\n    def _parse_arches(self):\n        \"\"\" parse architectures and associated Codesig \"\"\"\n        arch_macho = self.m.data\n        arches = []\n        if 'FatArch' in arch_macho:\n            log.debug('found fat binary')\n            for i, arch in enumerate(arch_macho.FatArch):\n                log.debug('found fat slice: cputype {}, cpusubtype {}'.format(arch.cputype, arch.cpusubtype))\n                this_arch_macho = arch.MachO\n                log.debug('slice {}: arch offset: {}, size: {}'.format(i, arch.offset, arch.size))\n                arch_object = self._get_arch(this_arch_macho,\n                                             arch.offset,\n                                             arch.size)\n                arch_object['fat_index'] = i\n                arches.append(arch_object)\n        else:\n            log.debug('found thin binary: cputype {}, cpusubtype {}'.format(arch_macho.cputype, arch_macho.cpusubtype))\n            arches.append(self._get_arch(arch_macho,\n                                         0,\n                                         self.file_end))\n\n        return arches\n\n    def _get_arch(self, macho, arch_offset, arch_size):\n        arch = {'macho': macho, 'arch_offset': arch_offset, 'arch_size': arch_size}\n\n        arch['cmds'] = {}\n        for cmd in macho.commands:\n            name = cmd.cmd\n            arch['cmds'][name] = cmd\n\n        codesig_data = None\n\n        if 'LC_CODE_SIGNATURE' in arch['cmds']:\n            arch['lc_codesig'] = arch['cmds']['LC_CODE_SIGNATURE']\n            codesig_offset = arch['macho'].macho_start + arch['lc_codesig'].data.dataoff\n            self.f.seek(codesig_offset)\n            codesig_data = self.f.read(arch['lc_codesig'].data.datasize)\n            # log.debug(\"codesig len: {0}\".format(len(codesig_data)))\n        else:\n            log.info(\"signing from scratch!\")\n            self.sign_from_scratch = True\n            entitlements_file = self.bundle.get_entitlements_path()  # '/path/to/some/entitlements.plist'\n\n            # Stage 1: Fake signature\n            fake_codesig_data = make_signature(macho, arch_offset, arch_size, arch['cmds'], self.f, entitlements_file,\n                                               0, self.signer, self.bundle.get_info_prop('CFBundleIdentifier'))\n\n            # We're stripping out the fake LC_CODE_SIGNATURE command, which we know has a size of 16, so we need to\n            # decrement the overall sizeofcmds\n            macho.ncmds -= 1\n            macho.commands = macho.commands[:-1]\n            macho.sizeofcmds -= 16\n\n            # Get the length\n            fake_codesig = Codesig(self, fake_codesig_data)\n            fake_codesig.set_signature(self.signer)\n            fake_codesig.update_offsets()\n            fake_codesig_length = len(fake_codesig.build_data())\n\n            log.debug(\"fake codesig length: {}\".format(fake_codesig_length))\n\n            # stage 2: real signature\n            codesig_data = make_signature(macho, arch_offset, arch_size, arch['cmds'], self.f, entitlements_file,\n                                          fake_codesig_length, self.signer,\n                                          self.bundle.get_info_prop('CFBundleIdentifier'))\n\n            arch['lc_codesig'] = arch['cmds']['LC_CODE_SIGNATURE']\n\n        arch['codesig'] = Codesig(self, codesig_data)\n        arch['codesig_len'] = len(codesig_data)\n\n        if self.sign_from_scratch:\n            arch['codesig_data'] = codesig_data\n\n        return arch\n\n    def _sign_arch(self, arch, app, signer):\n        # Returns slice-relative offset, code signature blob\n        arch['codesig'].resign(app, signer)\n\n        new_codesig_data = arch['codesig'].build_data()\n        new_codesig_len = len(new_codesig_data)\n        log.debug(\"new codesig len is: {0}\".format(new_codesig_len))\n\n        padding_length = arch['codesig_len'] - new_codesig_len\n        new_codesig_data += \"\\x00\" * padding_length\n        # log.debug(\"padded len: {0}\".format(len(new_codesig_data)))\n        # log.debug(\"----\")\n\n        cmd = arch['lc_codesig']\n        cmd.data.datasize = len(new_codesig_data)\n        cmd.bytes = macho.CodeSigRef.build(arch['lc_codesig'].data)\n\n        offset = cmd.data.dataoff\n        return offset, new_codesig_data\n\n    def should_fill_slot(self, codesig, slot):\n\n        slot_class = slot.__class__\n        if slot_class not in self.slot_classes:\n            # This signable does not have this slot\n            return False\n\n        if self.sign_from_scratch:\n            return True\n\n        if slot_class == InfoSlot and not self.bundle.info_props_changed():\n            # No Info.plist changes, don't fill\n            return False\n\n        if slot_class == ApplicationSlot and not codesig.is_sha256_signature():\n            # Application slot only needs to be zeroed out when there's a sha256 layer\n            return False\n\n        return True\n\n    def get_changed_bundle_id(self):\n        # Return a bundle ID to assign if Info.plist's CFBundleIdentifier value was changed\n        if self.bundle.info_prop_changed('CFBundleIdentifier'):\n            return self.bundle.get_info_prop('CFBundleIdentifier')\n        else:\n            return None\n\n    def sign(self, app, signer):\n\n        temp = tempfile.NamedTemporaryFile('wb', delete=False)\n\n        # If signing fat binary from scratch, need special handling\n\n        # TODO: we assume that if any slice is unsigned, all slices are.  This should be true in practice but\n        # we should still guard against this.\n        if self.sign_from_scratch and 'FatArch' in self.m.data:\n            # Fat binaries have more than 2 architectures, but thin ones only have one, so we assert that\n            assert len(self.arches) >= 1\n\n            # todo(markwang): Update fat headers and mach_start for each slice if needewd\n            log.debug('signing fat binary from scratch')\n\n            sorted_archs = sorted(self.arches, key=lambda arch: arch['arch_offset'])\n\n            prev_arch_end = 0\n            for arch in sorted_archs:\n                fatentry = arch['macho']  # has pointert to container\n\n                codesig_arch_offset, new_codesig_data = self._sign_arch(arch, app, signer)\n                codesig_file_offset = arch['arch_offset'] + codesig_arch_offset\n                log.debug('existing arch slice: cputype {}, cpusubtype {}, offset {}, size {}'\n                          .format(fatentry.cputype, fatentry.cpusubtype, arch['arch_offset'], arch['arch_size']))\n                log.debug(\"codesig arch offset: {2}, file offset: {0}, len: {1}\"\n                          .format(codesig_file_offset, len(new_codesig_data), codesig_arch_offset))\n                assert codesig_file_offset >= (arch['arch_offset'] + arch['arch_size'])\n\n                # Store the old slice offset/sizes because we need them when we copy the data slices from self.f to temp\n                arch['old_arch_offset'] = arch['arch_offset']\n                arch['old_arch_size'] = arch['arch_size']\n\n                arch['codesig_arch_offset'] = codesig_arch_offset\n                arch['codesig_data'] = new_codesig_data\n\n                new_arch_size = codesig_arch_offset + len(new_codesig_data)\n\n                if prev_arch_end > arch['arch_offset']:\n                    arch['arch_offset'] = utils.round_up(prev_arch_end, 16384)\n\n                prev_arch_end = arch['arch_offset'] + new_arch_size\n                arch['arch_size'] = new_arch_size\n\n                log.debug('new arch slice after codesig: offset {}, size {}'.format(arch['arch_offset'],\n                                                                                    arch['arch_size']))\n\n            # write slices and code signatures in reverse order\n            for arch in reversed(sorted_archs):\n                self.f.seek(arch['old_arch_offset'])\n                temp.seek(arch['arch_offset'])\n                temp.write(self.f.read(arch['old_arch_size']))\n\n                temp.seek(arch['arch_offset'] + arch['codesig_arch_offset'])\n                temp.write(arch['codesig_data'])\n\n                fatarch_info = self.m.data.FatArch[arch['fat_index']]\n                fatarch_info.size = arch['arch_size']\n                fatarch_info.offset = arch['arch_offset']\n\n        else:\n            # copy self.f into temp, reset to beginning of file\n            self.f.seek(0)\n            temp.write(self.f.read())\n            temp.seek(0)\n\n            # write new codesign blocks for each arch\n            offset_fmt = (\"offset: {2}, write offset: {0}, \"\n                          \"new_codesig_data len: {1}\")\n            for arch in self.arches:\n                offset, new_codesig_data = self._sign_arch(arch, app, signer)\n                write_offset = arch['macho'].macho_start + offset\n                log.debug(offset_fmt.format(write_offset,\n                                            len(new_codesig_data),\n                                            offset))\n                temp.seek(write_offset)\n                temp.write(new_codesig_data)\n\n        # write new headers\n        temp.seek(0)\n        macho.MachoFile.build_stream(self.m, temp)\n        temp.close()\n\n        # make copy have same permissions\n        mode = os.stat(self.path).st_mode\n        os.chmod(temp.name, mode)\n        # log.debug(\"moving temporary file to {0}\".format(self.path))\n        shutil.move(temp.name, self.path)\n\n\nclass Executable(Signable):\n    \"\"\" The main executable of an app. \"\"\"\n    slot_classes = [EntitlementsSlot,\n                    DerEntitlementsSlot,\n                    ResourceDirSlot,\n                    RequirementsSlot,\n                    ApplicationSlot,\n                    InfoSlot]\n\n\nclass Dylib(Signable):\n    \"\"\" A dynamic library that isn't part of its own bundle, e.g.\n        the Swift libraries.\n\n        TODO: Dylibs have an info slot, however the Info.plist is embedded in the __TEXT section\n              of the file (__info_plist) instead of being a seperate file.\n              Add read/write of the embedded Info.plist so we can include InfoSlot below.\n    \"\"\"\n    slot_classes = [EntitlementsSlot,\n                    DerEntitlementsSlot,\n                    RequirementsSlot]\n\n\nclass Appex(Signable):\n    \"\"\" An app extension  \"\"\"\n    slot_classes = [EntitlementsSlot,\n                    DerEntitlementsSlot,\n                    RequirementsSlot,\n                    InfoSlot]\n\n\nclass Framework(Signable):\n    \"\"\" The main executable of a Framework, which is a library of sorts\n        but is bundled with both files and code \"\"\"\n    slot_classes = [ResourceDirSlot,\n                    RequirementsSlot,\n                    InfoSlot]\n"
  },
  {
    "path": "isign/signer.py",
    "content": "# -*- coding: utf-8 -*-\n#\n# Small object that can be passed around easily, that represents\n# our signing credentials, and can sign data.\n#\n# Unfortunately the installed python OpenSSL library doesn't\n# offer what we need for cms, so we also need to shell out to the openssl\n# tool, and make sure it's the right version.\n\nfrom distutils import spawn\nfrom exceptions import (ImproperCredentials,\n                        MissingCredentials,\n                        OpenSslFailure)\nimport logging\nfrom OpenSSL import crypto\nimport os\nimport os.path\nimport subprocess\nimport re\n\nOPENSSL = os.getenv('OPENSSL', spawn.find_executable('openssl'))\n# modern OpenSSL versions look like '0.9.8zd'. Use a regex to parse\nOPENSSL_VERSION_RE = re.compile(r'(\\d+).(\\d+).(\\d+)(\\w*)')\nMINIMUM_OPENSSL_VERSION = '1.0.1'\n\nlog = logging.getLogger(__name__)\n\n\ndef openssl_command(args, data=None, expect_err=False):\n    \"\"\" Given array of args, and optionally data to write,\n        return results of openssl command.\n        Some commands always write something to stderr, so allow\n        for that with the expect_err param. \"\"\"\n    cmd = [OPENSSL] + args\n    cmd_str = ' '.join(cmd)\n    # log.debug('running command ' + cmd_str)\n    proc = subprocess.Popen(cmd,\n                            stdin=subprocess.PIPE,\n                            stderr=subprocess.PIPE,\n                            stdout=subprocess.PIPE)\n    if data is not None:\n        proc.stdin.write(data)\n    out, err = proc.communicate()\n\n    if not expect_err:\n        if err is not None and err != '':\n            log.error(\"Command `{0}` returned error:\\n{1}\".format(cmd_str, err))\n\n    if proc.returncode != 0:\n        msg = \"openssl command `{0}` failed, see log for error\".format(cmd_str)\n        raise OpenSslFailure(msg)\n\n    if expect_err:\n        return (out, err)\n    else:\n        return out\n\n\ndef get_installed_openssl_version():\n    version_line = openssl_command(['version'])\n    # e.g. 'OpenSSL 0.9.8zd 8 Jan 2015'\n    return re.split(r'\\s+', version_line)[1]\n\n\ndef is_openssl_version_ok(version, minimum):\n    \"\"\" check that the openssl tool is at least a certain version \"\"\"\n    version_tuple = openssl_version_to_tuple(version)\n    minimum_tuple = openssl_version_to_tuple(minimum)\n    return version_tuple >= minimum_tuple\n\n\ndef openssl_version_to_tuple(s):\n    \"\"\" OpenSSL uses its own versioning scheme, so we convert to tuple,\n        for easier comparison \"\"\"\n    search = re.search(OPENSSL_VERSION_RE, s)\n    if search is not None:\n        return search.groups()\n    return ()\n\n\nclass Signer(object):\n    \"\"\" collaborator, holds the keys, identifiers for signer,\n        and knows how to sign data \"\"\"\n    def __init__(self,\n                 signer_key_file=None,\n                 signer_cert_file=None,\n                 apple_cert_file=None,\n                 team_id=None):\n        \"\"\" signer_key_file = your org's key .pem\n            signer_cert_file = your org's cert .pem\n            apple_cert_file = apple certs in .pem form\n            team_id = your Apple Organizational Unit code \"\"\"\n        for filename in [signer_key_file, signer_cert_file, apple_cert_file]:\n            if not os.path.exists(filename):\n                msg = \"Can't find {0}\".format(filename)\n                log.warn(msg)\n                raise MissingCredentials(msg)\n        self.signer_key_file = signer_key_file\n        self.signer_cert_file = signer_cert_file\n        self.apple_cert_file = apple_cert_file\n        team_id = self._get_team_id()\n        if team_id is None:\n            raise ImproperCredentials(\"Cert file does not contain Subject line\"\n                                      \"with Apple Organizational Unit (OU)\")\n        self.team_id = team_id\n        self.check_openssl_version()\n\n    def check_openssl_version(self):\n        openssl_version = get_installed_openssl_version()\n        if not is_openssl_version_ok(openssl_version, MINIMUM_OPENSSL_VERSION):\n            msg = \"Signing may not work: OpenSSL version is {0}, need {1} !\"\n            log.warn(msg.format(openssl_version, MINIMUM_OPENSSL_VERSION))\n\n    def sign(self, data, digest_algorithm = \"sha1\"):\n        \"\"\" sign data, return filehandle \"\"\"\n        cmd = [\n            \"cms\",\n            \"-sign\", \"-binary\", \"-nosmimecap\",\n            \"-certfile\", self.apple_cert_file,\n            \"-signer\", self.signer_cert_file,\n            \"-inkey\", self.signer_key_file,\n            \"-keyform\", \"pem\",\n            \"-outform\", \"DER\",\n            \"-md\", digest_algorithm\n        ]\n        signature = openssl_command(cmd, data)\n        log.debug(\"in length: {}, out length: {}\".format(len(data), len(signature)))\n        # in some cases we've seen this return a zero length file.\n        # Misconfigured machines?\n        if len(signature) < 128:\n            too_small_msg = \"Command `{0}` returned success, but signature \"\n            \"seems too small ({1} bytes)\"\n            raise OpenSslFailure(too_small_msg.format(' '.join(cmd),\n                                                      len(signature)))\n        return signature\n\n    def get_common_name(self):\n        \"\"\" read in our cert, and get our Common Name \"\"\"\n        with open(self.signer_cert_file, 'rb') as fh:\n            cert = crypto.load_certificate(crypto.FILETYPE_PEM, fh.read())\n        subject = cert.get_subject()\n        return dict(subject.get_components())['CN']\n\n    def _log_parsed_asn1(self, data):\n        cmd = ['asn1parse', '-inform', 'DER' '-i']\n        parsed_asn1 = openssl_command(cmd)\n        log.debug(parsed_asn1)\n\n    def _get_team_id(self):\n        \"\"\" Same as Apple Organizational Unit. Should be in the cert \"\"\"\n        team_id = None\n        cmd = [\n            'x509',\n            '-in', self.signer_cert_file,\n            '-text',\n            '-noout'\n        ]\n        certificate_info = openssl_command(cmd)\n        subject_with_ou_match = re.compile(r'\\s+Subject:.*OU\\s?=\\s?(\\w+)')\n        for line in certificate_info.splitlines():\n            match = subject_with_ou_match.match(line)\n            if match is not None:\n                team_id = match.group(1)\n                break\n        return team_id\n"
  },
  {
    "path": "isign/utils.py",
    "content": "# -*- coding: utf-8 -*- \nimport binascii\nimport re\n\n\ndef print_data(data):\n    hexstring = binascii.hexlify(data)\n    n = 80\n    split_string = \"\\n\".join([hexstring[i:i+n] for i in range(0, len(hexstring), n)])\n    print split_string\n\n\ndef round_up(x, k):\n    return ((x + k - 1) & -k)\n\n\ndef print_structure(container, struct):\n    actual_data = struct.build(container)\n    return \"{}\".format(struct.parse(actual_data))\n# remove control character in string\n# This will affect the executable_name part in path\ndef remove_control_char(str):\n    return re.compile('[\\\\x00-\\\\x08\\\\x0b-\\\\x0c\\\\x0e-\\\\x1f]').sub('', str)"
  },
  {
    "path": "jenkins.sh",
    "content": "#!/bin/bash\n\n# figure out our package name from the name of repo\npushd $(dirname $0) >/dev/null\npackage_name=$(basename $PWD)\npackage=$(echo $package_name | sed 's/-/_/g')\npopd >/dev/null\n\nversion=$(./version.sh)\n\n# this communicates to setup.py to use the version \n# number we just made, rather than generating another\nexport PYTHON_PACKAGE_VERSION=${version}\n\nmake_venv() {\n    # For some reason mkvirtualenv returns with exit code 1 on success.  So we\n    # have to just continue.\n    virtualenv $TMPDIR || true\n    source $TMPDIR/bin/activate\n    pip install -r dev/requirements.txt\n}\n\nbuild_release() {\n    python setup.py sdist\n    release=${package_name}-${version}.tar.gz\n}\n\ntest_release() {\n    rm -rf dist-release && mkdir -p dist-release  \n\n    echo \"pip install dist/$release\"\n    pip install dist/$release\n    echo -e \"\\nInstalled packages:\"\n    pip freeze -l\n    echo\n    mv $package ${package}.testing\n    ./run_tests.sh\n    mv dist/$release dist-release/\n}\n\n# to push tags: add the repo to the \"bots\" team\ntag_release() {\n    tag=\"v$version\"\n    echo \"Tagging $head as $tag\"\n    git tag $tag $head\n    git push origin $tag\n}\n\nupdate_pypi() {\n    # always succeed with upload - transient errors with pypi \n    # should not cause red build\n    twine upload dist-release/$release || true\n}\n\ncleanup() {\n    rm -rf $TMPDIR\n\n    if [[ -d ${package}.testing ]]; then\n        mv ${package}.testing $package\n    fi\n}\n\n\nset -e\nTMPDIR=$(mktemp -d /tmp/${package_name}.XXXXXXXX)\ntrap cleanup 0\n\nmake_venv\nbuild_release\ntest_release\ntag_release\nupdate_pypi\ncleanup\n"
  },
  {
    "path": "run_tests.sh",
    "content": "#!/bin/bash -e\nname=$(basename $PWD)\npackage=$(echo $name | sed 's/-/_/g')\n\n# look for required apps\nfor app in unzip zip; do\n    if ! which $app >/dev/null; then\n        echo \"Missing application: $app\"\n        exit 1\n    fi\ndone\n\n# run test suite\nfind . -name '*.pyc' -delete\npushd tests >/dev/null\nversion=$(python -c \"import $package; print ${package}.__version__\")\necho \"Testing $name v${version}\"\nnosetests\npopd >/dev/null\n"
  },
  {
    "path": "setup.cfg",
    "content": "[metadata]\ndescription-file = README.rst\n"
  },
  {
    "path": "setup.py",
    "content": "# encoding: utf-8\nfrom setuptools import setup, find_packages\nfrom codecs import open  # to use a consistent encoding\nfrom subprocess import check_output\nfrom os import path, environ\n\nhere = path.abspath(path.dirname(__file__))\n\nif path.exists(path.join(here, \"version.sh\")):  # development\n    if 'PYTHON_PACKAGE_VERSION' in environ:\n        version = environ['PYTHON_PACKAGE_VERSION']\n    else:\n        version = check_output(path.join(here, \"version.sh\")).strip()\n    package_name = path.basename(here)\nelse:  # source package\n    with open(path.join(here, \"PKG-INFO\")) as f:\n        for line in f.readlines():\n            if line.startswith(\"Version:\"):\n                version = line.split(\":\")[1].strip()\n            elif line.startswith(\"Name:\"):\n                package_name = line.split(\":\")[1].strip()\npackage = package_name.replace('-', '_')\n\nsetup(\n    name=package_name,\n    version=version,\n    description='Re-signing iOS apps without Apple tools',\n    url='https://github.com/saucelabs/{}'.format(package_name),\n    download_url='https://github.com/saucelabs/{}/tarball/v{}'.format(package_name, version),\n    author='Sauce Labs',\n    author_email='dev@saucelabs.com',\n    classifiers=[\n        'Development Status :: 5 - Production/Stable',\n        'Intended Audience :: Developers',\n        'Topic :: Utilities',\n        'License :: OSI Approved :: Apache Software License',\n        'Programming Language :: Python :: 2.7',\n    ],\n    keywords=['ios', 'app', 'signature', 'codesign', 'sign', 'resign'],\n    packages=find_packages(),\n    install_requires=[\n        'biplist==1.0.3',\n        'construct==2.5.2',\n        'memoizer==0.0.1',\n        'pyOpenSSL==18.0.0',\n        'pyasn1==0.4.8',\n        'six>=1.10.0'\n    ],\n    package_data={\n        package: ['apple_credentials/applecerts.pem',\n                  'code_resources_template.xml',\n                  'version.json'],\n    },\n    scripts=['bin/isign',\n             'bin/multisign',\n             'bin/isign_export_creds.sh',\n             'bin/isign_guess_mobileprovision.sh']\n)\n"
  },
  {
    "path": "tests/NotAnApp.txt",
    "content": "This file isn't actually an app.\n"
  },
  {
    "path": "tests/NotAnAppDir/README.md",
    "content": "This is a directory which isign shouldn't accept as being an AppArchive\n"
  },
  {
    "path": "tests/README.md",
    "content": "To test isign, we need to actually sign some apps. This directory contains\nthe tests and the test data AND the source files to generate that test data.\n\nThis directory includes a lot of stuff. It could probably be better organized.\n\nTest data: to check that the library can detect non-apps:\n* NotAnApp.ipa\n* NotAnApp.txt\n\nTest data - compiled apps:\n* Test.app\n* Test.app.zip\n* Test.ipa\n* TestSimulator.app.zip\n* TestWithFrameworks.ipa\n\nExpected data from apps:\n* Test.app.codesig.construct.txt\n\nA short program to generate that expected data:\n* generate_codesig_construct_txt.py\n\nA test file, to see what happens when \"helper\" apps go wrong:\n* bad_openssl\n\nSelf-signed/fake credentials, to make these tests even work\n* credentials\n\nSource to build the test apps:\n* isignTestApp\n* isignTestAppWithFrameworks\n\nHelper for tests:\n* `monitor_temp_file.py`\n* `helpers.py`\n\nActual test code:\n* `isign_base_test.py`\n* `test_*.py:`   \n"
  },
  {
    "path": "tests/Test.app/PkgInfo",
    "content": "APPL????"
  },
  {
    "path": "tests/Test.app/_CodeSignature/CodeResources",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>files</key>\n\t<dict>\n\t\t<key>Assets.car</key>\n\t\t<data>\n\t\tJTRsnG3T7BKKYvgn8rcVKnVf67c=\n\t\t</data>\n\t\t<key>Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\teMYxMmbROeqxPMenCgfCsYRPQKs=\n\t\t\t</data>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>Base.lproj/LaunchScreen.storyboardc/Info.plist</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\tn2t8gsDpfE6XkhG31p7IQJRxTxU=\n\t\t\t</data>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\tesMacQh55MAAFCgvM1T6IE5te+s=\n\t\t\t</data>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>Base.lproj/Main.storyboardc/8rJ-Kc-sve-view-QS5-Rx-YEW.nib</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\teIL8TQj/c89wIYSRBONbQO58A0k=\n\t\t\t</data>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>Base.lproj/Main.storyboardc/9pv-A4-QxB-view-tsR-hK-woN.nib</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\tuMIVkX919bfq77m9Y4eVapG/uAI=\n\t\t\t</data>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>Base.lproj/Main.storyboardc/Info.plist</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\t/BgmwrRK8ElRpzfemriLZvm3U/Y=\n\t\t\t</data>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>Base.lproj/Main.storyboardc/UITabBarController-49e-Tb-3d3.nib</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\t3Z4RvYT6WblSIhmHjkV4OCT0478=\n\t\t\t</data>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>Frameworks/libswiftContacts.dylib</key>\n\t\t<data>\n\t\tXAUF5AOf/FKJ0FOaBryoXydYPkg=\n\t\t</data>\n\t\t<key>Frameworks/libswiftCore.dylib</key>\n\t\t<data>\n\t\toPSCk2x86K18iCXpKgzk+xPXrUM=\n\t\t</data>\n\t\t<key>Frameworks/libswiftCoreGraphics.dylib</key>\n\t\t<data>\n\t\tlFIRixuLPuPvyFEA/4UmWEoWsT4=\n\t\t</data>\n\t\t<key>Frameworks/libswiftCoreImage.dylib</key>\n\t\t<data>\n\t\t8w2X9ce86i4QEh2pxcwWJOw/hmY=\n\t\t</data>\n\t\t<key>Frameworks/libswiftDarwin.dylib</key>\n\t\t<data>\n\t\tdkfj0DypEBEArQE2yWzHKZXxeHM=\n\t\t</data>\n\t\t<key>Frameworks/libswiftDispatch.dylib</key>\n\t\t<data>\n\t\tjyXJbh2S33qT0cSQuNl8KYPMzBE=\n\t\t</data>\n\t\t<key>Frameworks/libswiftFoundation.dylib</key>\n\t\t<data>\n\t\tk5QXs7u4hyTXE+5NlHlz9KmMigg=\n\t\t</data>\n\t\t<key>Frameworks/libswiftObjectiveC.dylib</key>\n\t\t<data>\n\t\tZ1hjxXaY8/0BWfiaYAtBLah9NdQ=\n\t\t</data>\n\t\t<key>Frameworks/libswiftUIKit.dylib</key>\n\t\t<data>\n\t\t+mEoScPMQf+x9JhE1vClNhvkZIc=\n\t\t</data>\n\t\t<key>Info.plist</key>\n\t\t<data>\n\t\tyBg+lr48gYGDv7irgz8Co91E2c8=\n\t\t</data>\n\t\t<key>PkgInfo</key>\n\t\t<data>\n\t\tn57qDP4tZfLD1rCS43W0B4LQjzE=\n\t\t</data>\n\t\t<key>embedded.mobileprovision</key>\n\t\t<data>\n\t\tVHqTakGK9srUKBbgpbbbYG6u4bk=\n\t\t</data>\n\t</dict>\n\t<key>files2</key>\n\t<dict>\n\t\t<key>Assets.car</key>\n\t\t<data>\n\t\tJTRsnG3T7BKKYvgn8rcVKnVf67c=\n\t\t</data>\n\t\t<key>Base.lproj/LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\teMYxMmbROeqxPMenCgfCsYRPQKs=\n\t\t\t</data>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>Base.lproj/LaunchScreen.storyboardc/Info.plist</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\tn2t8gsDpfE6XkhG31p7IQJRxTxU=\n\t\t\t</data>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>Base.lproj/LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\tesMacQh55MAAFCgvM1T6IE5te+s=\n\t\t\t</data>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>Base.lproj/Main.storyboardc/8rJ-Kc-sve-view-QS5-Rx-YEW.nib</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\teIL8TQj/c89wIYSRBONbQO58A0k=\n\t\t\t</data>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>Base.lproj/Main.storyboardc/9pv-A4-QxB-view-tsR-hK-woN.nib</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\tuMIVkX919bfq77m9Y4eVapG/uAI=\n\t\t\t</data>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>Base.lproj/Main.storyboardc/Info.plist</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\t/BgmwrRK8ElRpzfemriLZvm3U/Y=\n\t\t\t</data>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>Base.lproj/Main.storyboardc/UITabBarController-49e-Tb-3d3.nib</key>\n\t\t<dict>\n\t\t\t<key>hash</key>\n\t\t\t<data>\n\t\t\t3Z4RvYT6WblSIhmHjkV4OCT0478=\n\t\t\t</data>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>Frameworks/libswiftContacts.dylib</key>\n\t\t<data>\n\t\tXAUF5AOf/FKJ0FOaBryoXydYPkg=\n\t\t</data>\n\t\t<key>Frameworks/libswiftCore.dylib</key>\n\t\t<data>\n\t\toPSCk2x86K18iCXpKgzk+xPXrUM=\n\t\t</data>\n\t\t<key>Frameworks/libswiftCoreGraphics.dylib</key>\n\t\t<data>\n\t\tlFIRixuLPuPvyFEA/4UmWEoWsT4=\n\t\t</data>\n\t\t<key>Frameworks/libswiftCoreImage.dylib</key>\n\t\t<data>\n\t\t8w2X9ce86i4QEh2pxcwWJOw/hmY=\n\t\t</data>\n\t\t<key>Frameworks/libswiftDarwin.dylib</key>\n\t\t<data>\n\t\tdkfj0DypEBEArQE2yWzHKZXxeHM=\n\t\t</data>\n\t\t<key>Frameworks/libswiftDispatch.dylib</key>\n\t\t<data>\n\t\tjyXJbh2S33qT0cSQuNl8KYPMzBE=\n\t\t</data>\n\t\t<key>Frameworks/libswiftFoundation.dylib</key>\n\t\t<data>\n\t\tk5QXs7u4hyTXE+5NlHlz9KmMigg=\n\t\t</data>\n\t\t<key>Frameworks/libswiftObjectiveC.dylib</key>\n\t\t<data>\n\t\tZ1hjxXaY8/0BWfiaYAtBLah9NdQ=\n\t\t</data>\n\t\t<key>Frameworks/libswiftUIKit.dylib</key>\n\t\t<data>\n\t\t+mEoScPMQf+x9JhE1vClNhvkZIc=\n\t\t</data>\n\t\t<key>embedded.mobileprovision</key>\n\t\t<data>\n\t\tVHqTakGK9srUKBbgpbbbYG6u4bk=\n\t\t</data>\n\t</dict>\n\t<key>rules</key>\n\t<dict>\n\t\t<key>^</key>\n\t\t<true/>\n\t\t<key>^.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^version.plist$</key>\n\t\t<true/>\n\t</dict>\n\t<key>rules2</key>\n\t<dict>\n\t\t<key>.*\\.dSYM($|/)</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>11</real>\n\t\t</dict>\n\t\t<key>^</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^(.*/)?\\.DS_Store$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>2000</real>\n\t\t</dict>\n\t\t<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^.*</key>\n\t\t<true/>\n\t\t<key>^.*\\.lproj/</key>\n\t\t<dict>\n\t\t\t<key>optional</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1000</real>\n\t\t</dict>\n\t\t<key>^.*\\.lproj/locversion.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>1100</real>\n\t\t</dict>\n\t\t<key>^Info\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^PkgInfo$</key>\n\t\t<dict>\n\t\t\t<key>omit</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^[^/]+$</key>\n\t\t<dict>\n\t\t\t<key>nested</key>\n\t\t\t<true/>\n\t\t\t<key>weight</key>\n\t\t\t<real>10</real>\n\t\t</dict>\n\t\t<key>^embedded\\.provisionprofile$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t\t<key>^version\\.plist$</key>\n\t\t<dict>\n\t\t\t<key>weight</key>\n\t\t\t<real>20</real>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/Test.app/build.sh",
    "content": "#!/bin/bash\n\n# ./build.sh /path/to/isign\n\n# builds various archival formats of the isign test app\n# and puts them in the test directory of isign. You have to specify\n# isign's source directory on the command line\n\n\nproject=isignTestApp\nisign_dir=$1\nisign_test_dir=$isign_dir/tests\n\nwarn() {\n    echo \"$@\" 1>&2;\n}\n\nbuild_app() {\n    local platform=$1;\n    local build_dir=build/Release-$(echo $platform | tr -d \"0-9.\");\n    xcodebuild -project $project.xcodeproj -sdk $platform;\n}\n\ncopy_app() {\n    local platform=$1;\n    local target=$2;\n    local build_dir=$(build_app $platform)\n    cp -r $build_dir/$project.app $target;\n}\n\ncopy_app_zip() {\n    local platform=$1;\n    local target=$2;\n    local build_dir=$(build_app $platform)\n    pushd $build_dir;\n    rm -f app.zip;\n    zip -r app.zip $project.app;\n    popd;\n    mv $build_dir/app.zip $target;\n}\n\n\nbuild_ipa() {\n    local platform=$1\n    local target=$2\n\n    xcodebuild clean -project $project.xcodeproj -configuration Release -sdk $platform;\n    xcodebuild archive -project $project.xcodeproj -scheme $project -archivePath $project.xcarchive\n    xcodebuild -exportArchive \\\n               -archivePath $projectname.xcarchive \\\n               -exportPath $projectname \\\n               -exportFormat ipa \\\n               -exportProvisioningProfile \"Neil Kandalgaonkar\"\n}\n\n\n\ncopy_app     iphoneos9.2        $isign_test_dir/Test.app;\ncopy_app_zip iphoneos9.2        $isign_test_dir/Test.app.zip;\n# build_ipa     iphoneos9.2        $isign_test_dir/Test.ipa;\n# build_app_zip iphonesimulator9.2 $isign_test_dir/TestSimulator.app.zip;\n\n"
  },
  {
    "path": "tests/Test.app/isignTestApp.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t88F49D571C21E0220007422C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D561C21E0220007422C /* AppDelegate.swift */; };\n\t\t88F49D591C21E0220007422C /* FirstViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D581C21E0220007422C /* FirstViewController.swift */; };\n\t\t88F49D5B1C21E0220007422C /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D5A1C21E0220007422C /* SecondViewController.swift */; };\n\t\t88F49D5E1C21E0220007422C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88F49D5C1C21E0220007422C /* Main.storyboard */; };\n\t\t88F49D601C21E0220007422C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 88F49D5F1C21E0220007422C /* Assets.xcassets */; };\n\t\t88F49D631C21E0220007422C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88F49D611C21E0220007422C /* LaunchScreen.storyboard */; };\n\t\t88F49D6E1C21E0220007422C /* isignTestAppTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D6D1C21E0220007422C /* isignTestAppTests.swift */; };\n\t\t88F49D791C21E0220007422C /* isignTestAppUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D781C21E0220007422C /* isignTestAppUITests.swift */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t88F49D6A1C21E0220007422C /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 88F49D4B1C21E0220007422C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 88F49D521C21E0220007422C;\n\t\t\tremoteInfo = isignTestApp;\n\t\t};\n\t\t88F49D751C21E0220007422C /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 88F49D4B1C21E0220007422C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 88F49D521C21E0220007422C;\n\t\t\tremoteInfo = isignTestApp;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t88F49D531C21E0220007422C /* isignTestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = isignTestApp.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t88F49D561C21E0220007422C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\t88F49D581C21E0220007422C /* FirstViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstViewController.swift; sourceTree = \"<group>\"; };\n\t\t88F49D5A1C21E0220007422C /* SecondViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondViewController.swift; sourceTree = \"<group>\"; };\n\t\t88F49D5D1C21E0220007422C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\t88F49D5F1C21E0220007422C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t88F49D621C21E0220007422C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = \"<group>\"; };\n\t\t88F49D641C21E0220007422C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t88F49D691C21E0220007422C /* isignTestAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = isignTestAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t88F49D6D1C21E0220007422C /* isignTestAppTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = isignTestAppTests.swift; sourceTree = \"<group>\"; };\n\t\t88F49D6F1C21E0220007422C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t88F49D741C21E0220007422C /* isignTestAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = isignTestAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t88F49D781C21E0220007422C /* isignTestAppUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = isignTestAppUITests.swift; sourceTree = \"<group>\"; };\n\t\t88F49D7A1C21E0220007422C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t88F49D501C21E0220007422C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D661C21E0220007422C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D711C21E0220007422C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t88F49D4A1C21E0220007422C = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D551C21E0220007422C /* isignTestApp */,\n\t\t\t\t88F49D6C1C21E0220007422C /* isignTestAppTests */,\n\t\t\t\t88F49D771C21E0220007422C /* isignTestAppUITests */,\n\t\t\t\t88F49D541C21E0220007422C /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D541C21E0220007422C /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D531C21E0220007422C /* isignTestApp.app */,\n\t\t\t\t88F49D691C21E0220007422C /* isignTestAppTests.xctest */,\n\t\t\t\t88F49D741C21E0220007422C /* isignTestAppUITests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D551C21E0220007422C /* isignTestApp */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D561C21E0220007422C /* AppDelegate.swift */,\n\t\t\t\t88F49D581C21E0220007422C /* FirstViewController.swift */,\n\t\t\t\t88F49D5A1C21E0220007422C /* SecondViewController.swift */,\n\t\t\t\t88F49D5C1C21E0220007422C /* Main.storyboard */,\n\t\t\t\t88F49D5F1C21E0220007422C /* Assets.xcassets */,\n\t\t\t\t88F49D611C21E0220007422C /* LaunchScreen.storyboard */,\n\t\t\t\t88F49D641C21E0220007422C /* Info.plist */,\n\t\t\t);\n\t\t\tpath = isignTestApp;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D6C1C21E0220007422C /* isignTestAppTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D6D1C21E0220007422C /* isignTestAppTests.swift */,\n\t\t\t\t88F49D6F1C21E0220007422C /* Info.plist */,\n\t\t\t);\n\t\t\tpath = isignTestAppTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D771C21E0220007422C /* isignTestAppUITests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D781C21E0220007422C /* isignTestAppUITests.swift */,\n\t\t\t\t88F49D7A1C21E0220007422C /* Info.plist */,\n\t\t\t);\n\t\t\tpath = isignTestAppUITests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t88F49D521C21E0220007422C /* isignTestApp */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 88F49D7D1C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestApp\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t88F49D4F1C21E0220007422C /* Sources */,\n\t\t\t\t88F49D501C21E0220007422C /* Frameworks */,\n\t\t\t\t88F49D511C21E0220007422C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = isignTestApp;\n\t\t\tproductName = isignTestApp;\n\t\t\tproductReference = 88F49D531C21E0220007422C /* isignTestApp.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\t88F49D681C21E0220007422C /* isignTestAppTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 88F49D801C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t88F49D651C21E0220007422C /* Sources */,\n\t\t\t\t88F49D661C21E0220007422C /* Frameworks */,\n\t\t\t\t88F49D671C21E0220007422C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t88F49D6B1C21E0220007422C /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = isignTestAppTests;\n\t\t\tproductName = isignTestAppTests;\n\t\t\tproductReference = 88F49D691C21E0220007422C /* isignTestAppTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\t88F49D731C21E0220007422C /* isignTestAppUITests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 88F49D831C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppUITests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t88F49D701C21E0220007422C /* Sources */,\n\t\t\t\t88F49D711C21E0220007422C /* Frameworks */,\n\t\t\t\t88F49D721C21E0220007422C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t88F49D761C21E0220007422C /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = isignTestAppUITests;\n\t\t\tproductName = isignTestAppUITests;\n\t\t\tproductReference = 88F49D741C21E0220007422C /* isignTestAppUITests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.ui-testing\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t88F49D4B1C21E0220007422C /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastSwiftUpdateCheck = 0720;\n\t\t\t\tLastUpgradeCheck = 0720;\n\t\t\t\tORGANIZATIONNAME = \"Sauce Labs\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t88F49D521C21E0220007422C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t};\n\t\t\t\t\t88F49D681C21E0220007422C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t\tTestTargetID = 88F49D521C21E0220007422C;\n\t\t\t\t\t};\n\t\t\t\t\t88F49D731C21E0220007422C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t\tTestTargetID = 88F49D521C21E0220007422C;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 88F49D4E1C21E0220007422C /* Build configuration list for PBXProject \"isignTestApp\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 88F49D4A1C21E0220007422C;\n\t\t\tproductRefGroup = 88F49D541C21E0220007422C /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t88F49D521C21E0220007422C /* isignTestApp */,\n\t\t\t\t88F49D681C21E0220007422C /* isignTestAppTests */,\n\t\t\t\t88F49D731C21E0220007422C /* isignTestAppUITests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t88F49D511C21E0220007422C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D631C21E0220007422C /* LaunchScreen.storyboard in Resources */,\n\t\t\t\t88F49D601C21E0220007422C /* Assets.xcassets in Resources */,\n\t\t\t\t88F49D5E1C21E0220007422C /* Main.storyboard in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D671C21E0220007422C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D721C21E0220007422C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t88F49D4F1C21E0220007422C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D5B1C21E0220007422C /* SecondViewController.swift in Sources */,\n\t\t\t\t88F49D571C21E0220007422C /* AppDelegate.swift in Sources */,\n\t\t\t\t88F49D591C21E0220007422C /* FirstViewController.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D651C21E0220007422C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D6E1C21E0220007422C /* isignTestAppTests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D701C21E0220007422C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D791C21E0220007422C /* isignTestAppUITests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t88F49D6B1C21E0220007422C /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 88F49D521C21E0220007422C /* isignTestApp */;\n\t\t\ttargetProxy = 88F49D6A1C21E0220007422C /* PBXContainerItemProxy */;\n\t\t};\n\t\t88F49D761C21E0220007422C /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 88F49D521C21E0220007422C /* isignTestApp */;\n\t\t\ttargetProxy = 88F49D751C21E0220007422C /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\t88F49D5C1C21E0220007422C /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D5D1C21E0220007422C /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D611C21E0220007422C /* LaunchScreen.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D621C21E0220007422C /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t88F49D7B1C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D7C1C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t88F49D7E1C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tINFOPLIST_FILE = isignTestApp/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestApp;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D7F1C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tINFOPLIST_FILE = isignTestApp/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestApp;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t88F49D811C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tINFOPLIST_FILE = isignTestAppTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/isignTestApp.app/isignTestApp\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D821C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tINFOPLIST_FILE = isignTestAppTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/isignTestApp.app/isignTestApp\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t88F49D841C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = isignTestAppUITests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppUITests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_TARGET_NAME = isignTestApp;\n\t\t\t\tUSES_XCTRUNNER = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D851C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = isignTestAppUITests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppUITests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_TARGET_NAME = isignTestApp;\n\t\t\t\tUSES_XCTRUNNER = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t88F49D4E1C21E0220007422C /* Build configuration list for PBXProject \"isignTestApp\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D7B1C21E0220007422C /* Debug */,\n\t\t\t\t88F49D7C1C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t88F49D7D1C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestApp\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D7E1C21E0220007422C /* Debug */,\n\t\t\t\t88F49D7F1C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t};\n\t\t88F49D801C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D811C21E0220007422C /* Debug */,\n\t\t\t\t88F49D821C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t};\n\t\t88F49D831C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppUITests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D841C21E0220007422C /* Debug */,\n\t\t\t\t88F49D851C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 88F49D4B1C21E0220007422C /* Project object */;\n}\n"
  },
  {
    "path": "tests/Test.app/isignTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:isignTestApp.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "tests/Test.app/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/isignTestApp.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0720\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n               BuildableName = \"isignTestApp.app\"\n               BlueprintName = \"isignTestApp\"\n               ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"88F49D681C21E0220007422C\"\n               BuildableName = \"isignTestAppTests.xctest\"\n               BlueprintName = \"isignTestAppTests\"\n               ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"88F49D731C21E0220007422C\"\n               BuildableName = \"isignTestAppUITests.xctest\"\n               BlueprintName = \"isignTestAppUITests\"\n               ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n            BuildableName = \"isignTestApp.app\"\n            BlueprintName = \"isignTestApp\"\n            ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n            BuildableName = \"isignTestApp.app\"\n            BlueprintName = \"isignTestApp\"\n            ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n            BuildableName = \"isignTestApp.app\"\n            BlueprintName = \"isignTestApp\"\n            ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "tests/Test.app/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/xcschememanagement.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>SchemeUserState</key>\n\t<dict>\n\t\t<key>isignTestApp.xcscheme</key>\n\t\t<dict>\n\t\t\t<key>orderHint</key>\n\t\t\t<integer>0</integer>\n\t\t</dict>\n\t</dict>\n\t<key>SuppressBuildableAutocreation</key>\n\t<dict>\n\t\t<key>88F49D521C21E0220007422C</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>88F49D681C21E0220007422C</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>88F49D731C21E0220007422C</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/Test.app/isignTestAppTests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/Test.app/isignTestAppTests/isignTestAppTests.swift",
    "content": "//\n//  isignTestAppTests.swift\n//  isignTestAppTests\n//\n//  Created by Neil Kandalgaonkar on 12/16/15.\n//  Copyright © 2015 Sauce Labs. All rights reserved.\n//\n\nimport XCTest\n@testable import isignTestApp\n\nclass isignTestAppTests: XCTestCase {\n    \n    override func setUp() {\n        super.setUp()\n        // Put setup code here. This method is called before the invocation of each test method in the class.\n    }\n    \n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n    \n    func testExample() {\n        // This is an example of a functional test case.\n        // Use XCTAssert and related functions to verify your tests produce the correct results.\n    }\n    \n    func testPerformanceExample() {\n        // This is an example of a performance test case.\n        self.measureBlock {\n            // Put the code you want to measure the time of here.\n        }\n    }\n    \n}\n"
  },
  {
    "path": "tests/Test.app/isignTestAppUITests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/Test.app/isignTestAppUITests/isignTestAppUITests.swift",
    "content": "//\n//  isignTestAppUITests.swift\n//  isignTestAppUITests\n//\n//  Created by Neil Kandalgaonkar on 12/16/15.\n//  Copyright © 2015 Sauce Labs. All rights reserved.\n//\n\nimport XCTest\n\nclass isignTestAppUITests: XCTestCase {\n        \n    override func setUp() {\n        super.setUp()\n        \n        // Put setup code here. This method is called before the invocation of each test method in the class.\n        \n        // In UI tests it is usually best to stop immediately when a failure occurs.\n        continueAfterFailure = false\n        // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.\n        XCUIApplication().launch()\n\n        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.\n    }\n    \n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n    \n    func testExample() {\n        // Use recording to get started writing UI tests.\n        // Use XCTAssert and related functions to verify your tests produce the correct results.\n    }\n    \n}\n"
  },
  {
    "path": "tests/Test.app.codesig.construct.txt",
    "content": "Container:\n    cmd = 'LC_CODE_SIGNATURE'\n    cmdsize = 16\n    data = Container:\n        dataoff = 71920\n        datasize = 10304\n        blob = Container:\n            magic = 'CSMAGIC_EMBEDDED_SIGNATURE'\n            length = 5671\n            data = Container:\n                sb_start = 88312\n                count = 4\n                BlobIndex = [\n                    Container:\n                        type = 0\n                        offset = 44\n                        blob = Container:\n                            magic = 'CSMAGIC_CODEDIRECTORY'\n                            length = 550\n                            data = Container:\n                                cd_start = 88356\n                                version = 131584\n                                flags = 0\n                                hashOffset = 190\n                                identOffset = 52\n                                nSpecialSlots = 5\n                                nCodeSlots = 18\n                                codeLimit = 71920\n                                hashSize = 20\n                                hashType = 1\n                                spare1 = 0\n                                pageSize = 12\n                                spare2 = 0\n                                ident = 'com.saucelabs.isignTestApp'\n                                scatterOffset = 0\n                                teamIDOffset = 79\n                                teamID = 'L37S4Z6BE9'\n                                hashes = [\n                                    ':\\x02\\xd0\\x07\\x8az\\xfa<.\\xf7\\x1ed8\\x7f\\xa4\\xf1\\xc1s\\xeda'\n                                    '\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n                                    'TE\\x05\\xaa\\x81<\\xbc,\\xb6\\xd3\\xf8\\x05\\xebM\\xe1|\\x1a\\xb5O\\x00'\n                                    \"\\xc1,\\xf7\\x8b34\\xa8\\xe5\\xfa\\x92\\xd69\\x9d\\xe2\\x89Z'\\xafo\\x9b\"\n                                    '\\xc8\\x18>\\x96\\xbe<\\x81\\x81\\x83\\xbf\\xb8\\xab\\x83?\\x02\\xa3\\xddD\\xd9\\xcf'\n                                    '\\x0c\\x02\\x83\\xf9\\xfd\\xa6\\xb1\\x9fC\\x0b\\xa3\\x00\\x135\\xd8{\\xb06\\xeb\\x92'\n                                    '\\x1c\\xea\\xf7=\\xf4\\x0eS\\x1d\\xf3\\xbf\\xb2kO\\xb7\\xcd\\x95\\xfb{\\xff\\x1d'\n                                    '\\x1c\\xea\\xf7=\\xf4\\x0eS\\x1d\\xf3\\xbf\\xb2kO\\xb7\\xcd\\x95\\xfb{\\xff\\x1d'\n                                    '\\x1c\\xea\\xf7=\\xf4\\x0eS\\x1d\\xf3\\xbf\\xb2kO\\xb7\\xcd\\x95\\xfb{\\xff\\x1d'\n                                    '\\x1c\\xea\\xf7=\\xf4\\x0eS\\x1d\\xf3\\xbf\\xb2kO\\xb7\\xcd\\x95\\xfb{\\xff\\x1d'\n                                    '[\\xd6\\x8e\\xe2\\xfc\\xed\\x83\\xbf5\\x9b\\x1fa{F`\\x92\\xba\\x0b\\xbfe'\n                                    'w\\x99\\xa6\\x1cp\\xc6,<N\\xe2\\tGO\\x89\\xec\\x0f\\xd9\\x93\\x05\\xf2'\n                                    '\\xa2\\x14\\xbe\\x04\\x0f\\xd9#u\\xa6;D\\xa7\\xc1WV|\\x16\\xa9\\xa7C'\n                                    \"\\xd0z\\x1c\\x84w\\xab\\nV\\xe2\\x88zX'\\x92\\xb8\\x8a\\x90^\\xddA\"\n                                    '\\x1c\\xea\\xf7=\\xf4\\x0eS\\x1d\\xf3\\xbf\\xb2kO\\xb7\\xcd\\x95\\xfb{\\xff\\x1d'\n                                    '\\x1c\\xea\\xf7=\\xf4\\x0eS\\x1d\\xf3\\xbf\\xb2kO\\xb7\\xcd\\x95\\xfb{\\xff\\x1d'\n                                    '\\x1c\\xea\\xf7=\\xf4\\x0eS\\x1d\\xf3\\xbf\\xb2kO\\xb7\\xcd\\x95\\xfb{\\xff\\x1d'\n                                    'Fs\\xa0!\\xb4\\xfa\\xca\\xc2\\xb9\\x8awf#\\xed\\x10\\x15\\xc7\\x9e\\x19#'\n                                    \"\\xa8Rx\\xbe\\xd9cC\\xc0\\xb2\\xcf^A'\\xf3\\x88\\t\\xde\\x01;\\xd0\"\n                                    '\\xbd\\x83\\x045(\\xf1\\x9c37\\xc4\\xa4\\x9cn\\xf0\\xe3h\\x16\\xd9\\x8d\\x97'\n                                    'R!\\xf6\\x8f\\x95\\xf1i\\xc8ZE\\xff\\x1e-O\\x91-\\x94h\\n\\x19'\n                                    '\\x1b\\x1d\\xb6S\\xa5\\xaeP\\xf3\\xc94O\\xcd\\x12u\\xd3\\r\\xd3\\xb7\\x11.'\n                                    '\\xa0\\xeb\\x02\\xa9\\xa3O\\x90\\xa5?\\xf4M\\xe1\\x16rE\\xec\\xc9\\xe7\\xc01'\n                                ]\n                            bytes = LazyContainer: <unread>\n                    Container:\n                        type = 2\n                        offset = 594\n                        blob = Container:\n                            magic = 'CSMAGIC_REQUIREMENTS'\n                            length = 196\n                            data = Container:\n                                sb_start = 88906\n                                count = 1\n                                BlobIndex = [\n                                    Container:\n                                        type = 'kSecDesignatedRequirementType'\n                                        offset = 20\n                                        blob = Container:\n                                            magic = 'CSMAGIC_REQUIREMENT'\n                                            length = 176\n                                            data = Container:\n                                                kind = 1\n                                                expr = Container:\n                                                    op = 'opAnd'\n                                                    data = [\n                                                        Container:\n                                                            op = 'opIdent'\n                                                            data = Container:\n                                                                length = 26\n                                                                data = 'com.saucelabs.isignTestApp'\n                                                        Container:\n                                                            op = 'opAnd'\n                                                            data = [\n                                                                Container:\n                                                                    op = 'opAppleGenericAnchor'\n                                                                    data = None\n                                                                Container:\n                                                                    op = 'opAnd'\n                                                                    data = [\n                                                                        Container:\n                                                                            op = 'opCertField'\n                                                                            data = [\n                                                                                'leafCert'\n                                                                                Container:\n                                                                                    length = 10\n                                                                                    data = 'subject.CN'\n                                                                                Container:\n                                                                                    matchOp = 'matchEqual'\n                                                                                    Data = Container:\n                                                                                        length = 49\n                                                                                        data = 'iPhone Developer: Neil Kandalgaonkar (PJ5C3PEW8Z)'\n                                                                            ]\n                                                                        Container:\n                                                                            op = 'opCertGeneric'\n                                                                            data = [\n                                                                                1\n                                                                                Container:\n                                                                                    length = 10\n                                                                                    data = '*\\x86H\\x86\\xf7cd\\x06\\x02\\x01'\n                                                                                Container:\n                                                                                    matchOp = 'matchExists'\n                                                                                    Data = None\n                                                                            ]\n                                                                    ]\n                                                            ]\n                                                    ]\n                                            bytes = LazyContainer: <unread>\n                                ]\n                            bytes = LazyContainer: <unread>\n                    Container:\n                        type = 5\n                        offset = 790\n                        blob = Container:\n                            magic = 'CSMAGIC_ENTITLEMENT'\n                            length = 511\n                            data = Container:\n                                data = {'application-identifier': 'L37S4Z6BE9.com.saucelabs.isignTestApp', 'com.apple.developer.team-identifier': 'L37S4Z6BE9', 'keychain-access-groups': ['L37S4Z6BE9.com.saucelabs.isignTestApp'], 'get-task-allow': True}\n                            bytes = LazyContainer: <unread>\n                    Container:\n                        type = 65536\n                        offset = 1301\n                        blob = Container:\n                            magic = 'CSMAGIC_BLOBWRAPPER'\n                            length = 4370\n                            data = Container:\n                                data = LazyContainer: <unread>\n                            bytes = LazyContainer: <unread>\n                ]\n            bytes = LazyContainer: <unread>\n    bytes = LazyContainer: <unread>\n"
  },
  {
    "path": "tests/Test_unsigned_fat.app/PkgInfo",
    "content": "APPL????"
  },
  {
    "path": "tests/Test_unsigned_fat.app/build.sh",
    "content": "#!/bin/bash\n\n# ./build.sh /path/to/isign\n\n# builds various archival formats of the isign test app\n# and puts them in the test directory of isign. You have to specify\n# isign's source directory on the command line\n\n\nproject=isignTestApp\nisign_dir=$1\nisign_test_dir=$isign_dir/tests\n\nwarn() {\n    echo \"$@\" 1>&2;\n}\n\nbuild_app() {\n    local platform=$1;\n    local build_dir=build/Release-$(echo $platform | tr -d \"0-9.\");\n    xcodebuild -project $project.xcodeproj -sdk $platform;\n}\n\ncopy_app() {\n    local platform=$1;\n    local target=$2;\n    local build_dir=$(build_app $platform)\n    cp -r $build_dir/$project.app $target;\n}\n\ncopy_app_zip() {\n    local platform=$1;\n    local target=$2;\n    local build_dir=$(build_app $platform)\n    pushd $build_dir;\n    rm -f app.zip;\n    zip -r app.zip $project.app;\n    popd;\n    mv $build_dir/app.zip $target;\n}\n\n\nbuild_ipa() {\n    local platform=$1\n    local target=$2\n\n    xcodebuild clean -project $project.xcodeproj -configuration Release -sdk $platform;\n    xcodebuild archive -project $project.xcodeproj -scheme $project -archivePath $project.xcarchive\n    xcodebuild -exportArchive \\\n               -archivePath $projectname.xcarchive \\\n               -exportPath $projectname \\\n               -exportFormat ipa \\\n               -exportProvisioningProfile \"Neil Kandalgaonkar\"\n}\n\n\n\ncopy_app     iphoneos9.2        $isign_test_dir/Test.app;\ncopy_app_zip iphoneos9.2        $isign_test_dir/Test.app.zip;\n# build_ipa     iphoneos9.2        $isign_test_dir/Test.ipa;\n# build_app_zip iphonesimulator9.2 $isign_test_dir/TestSimulator.app.zip;\n\n"
  },
  {
    "path": "tests/Test_unsigned_fat.app/isignTestApp.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t88F49D571C21E0220007422C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D561C21E0220007422C /* AppDelegate.swift */; };\n\t\t88F49D591C21E0220007422C /* FirstViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D581C21E0220007422C /* FirstViewController.swift */; };\n\t\t88F49D5B1C21E0220007422C /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D5A1C21E0220007422C /* SecondViewController.swift */; };\n\t\t88F49D5E1C21E0220007422C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88F49D5C1C21E0220007422C /* Main.storyboard */; };\n\t\t88F49D601C21E0220007422C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 88F49D5F1C21E0220007422C /* Assets.xcassets */; };\n\t\t88F49D631C21E0220007422C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88F49D611C21E0220007422C /* LaunchScreen.storyboard */; };\n\t\t88F49D6E1C21E0220007422C /* isignTestAppTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D6D1C21E0220007422C /* isignTestAppTests.swift */; };\n\t\t88F49D791C21E0220007422C /* isignTestAppUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D781C21E0220007422C /* isignTestAppUITests.swift */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t88F49D6A1C21E0220007422C /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 88F49D4B1C21E0220007422C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 88F49D521C21E0220007422C;\n\t\t\tremoteInfo = isignTestApp;\n\t\t};\n\t\t88F49D751C21E0220007422C /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 88F49D4B1C21E0220007422C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 88F49D521C21E0220007422C;\n\t\t\tremoteInfo = isignTestApp;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t88F49D531C21E0220007422C /* isignTestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = isignTestApp.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t88F49D561C21E0220007422C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\t88F49D581C21E0220007422C /* FirstViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstViewController.swift; sourceTree = \"<group>\"; };\n\t\t88F49D5A1C21E0220007422C /* SecondViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondViewController.swift; sourceTree = \"<group>\"; };\n\t\t88F49D5D1C21E0220007422C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\t88F49D5F1C21E0220007422C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t88F49D621C21E0220007422C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = \"<group>\"; };\n\t\t88F49D641C21E0220007422C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t88F49D691C21E0220007422C /* isignTestAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = isignTestAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t88F49D6D1C21E0220007422C /* isignTestAppTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = isignTestAppTests.swift; sourceTree = \"<group>\"; };\n\t\t88F49D6F1C21E0220007422C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t88F49D741C21E0220007422C /* isignTestAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = isignTestAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t88F49D781C21E0220007422C /* isignTestAppUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = isignTestAppUITests.swift; sourceTree = \"<group>\"; };\n\t\t88F49D7A1C21E0220007422C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t88F49D501C21E0220007422C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D661C21E0220007422C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D711C21E0220007422C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t88F49D4A1C21E0220007422C = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D551C21E0220007422C /* isignTestApp */,\n\t\t\t\t88F49D6C1C21E0220007422C /* isignTestAppTests */,\n\t\t\t\t88F49D771C21E0220007422C /* isignTestAppUITests */,\n\t\t\t\t88F49D541C21E0220007422C /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D541C21E0220007422C /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D531C21E0220007422C /* isignTestApp.app */,\n\t\t\t\t88F49D691C21E0220007422C /* isignTestAppTests.xctest */,\n\t\t\t\t88F49D741C21E0220007422C /* isignTestAppUITests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D551C21E0220007422C /* isignTestApp */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D561C21E0220007422C /* AppDelegate.swift */,\n\t\t\t\t88F49D581C21E0220007422C /* FirstViewController.swift */,\n\t\t\t\t88F49D5A1C21E0220007422C /* SecondViewController.swift */,\n\t\t\t\t88F49D5C1C21E0220007422C /* Main.storyboard */,\n\t\t\t\t88F49D5F1C21E0220007422C /* Assets.xcassets */,\n\t\t\t\t88F49D611C21E0220007422C /* LaunchScreen.storyboard */,\n\t\t\t\t88F49D641C21E0220007422C /* Info.plist */,\n\t\t\t);\n\t\t\tpath = isignTestApp;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D6C1C21E0220007422C /* isignTestAppTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D6D1C21E0220007422C /* isignTestAppTests.swift */,\n\t\t\t\t88F49D6F1C21E0220007422C /* Info.plist */,\n\t\t\t);\n\t\t\tpath = isignTestAppTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D771C21E0220007422C /* isignTestAppUITests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D781C21E0220007422C /* isignTestAppUITests.swift */,\n\t\t\t\t88F49D7A1C21E0220007422C /* Info.plist */,\n\t\t\t);\n\t\t\tpath = isignTestAppUITests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t88F49D521C21E0220007422C /* isignTestApp */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 88F49D7D1C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestApp\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t88F49D4F1C21E0220007422C /* Sources */,\n\t\t\t\t88F49D501C21E0220007422C /* Frameworks */,\n\t\t\t\t88F49D511C21E0220007422C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = isignTestApp;\n\t\t\tproductName = isignTestApp;\n\t\t\tproductReference = 88F49D531C21E0220007422C /* isignTestApp.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\t88F49D681C21E0220007422C /* isignTestAppTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 88F49D801C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t88F49D651C21E0220007422C /* Sources */,\n\t\t\t\t88F49D661C21E0220007422C /* Frameworks */,\n\t\t\t\t88F49D671C21E0220007422C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t88F49D6B1C21E0220007422C /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = isignTestAppTests;\n\t\t\tproductName = isignTestAppTests;\n\t\t\tproductReference = 88F49D691C21E0220007422C /* isignTestAppTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\t88F49D731C21E0220007422C /* isignTestAppUITests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 88F49D831C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppUITests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t88F49D701C21E0220007422C /* Sources */,\n\t\t\t\t88F49D711C21E0220007422C /* Frameworks */,\n\t\t\t\t88F49D721C21E0220007422C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t88F49D761C21E0220007422C /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = isignTestAppUITests;\n\t\t\tproductName = isignTestAppUITests;\n\t\t\tproductReference = 88F49D741C21E0220007422C /* isignTestAppUITests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.ui-testing\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t88F49D4B1C21E0220007422C /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastSwiftUpdateCheck = 0720;\n\t\t\t\tLastUpgradeCheck = 0720;\n\t\t\t\tORGANIZATIONNAME = \"Sauce Labs\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t88F49D521C21E0220007422C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t};\n\t\t\t\t\t88F49D681C21E0220007422C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t\tTestTargetID = 88F49D521C21E0220007422C;\n\t\t\t\t\t};\n\t\t\t\t\t88F49D731C21E0220007422C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t\tTestTargetID = 88F49D521C21E0220007422C;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 88F49D4E1C21E0220007422C /* Build configuration list for PBXProject \"isignTestApp\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 88F49D4A1C21E0220007422C;\n\t\t\tproductRefGroup = 88F49D541C21E0220007422C /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t88F49D521C21E0220007422C /* isignTestApp */,\n\t\t\t\t88F49D681C21E0220007422C /* isignTestAppTests */,\n\t\t\t\t88F49D731C21E0220007422C /* isignTestAppUITests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t88F49D511C21E0220007422C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D631C21E0220007422C /* LaunchScreen.storyboard in Resources */,\n\t\t\t\t88F49D601C21E0220007422C /* Assets.xcassets in Resources */,\n\t\t\t\t88F49D5E1C21E0220007422C /* Main.storyboard in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D671C21E0220007422C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D721C21E0220007422C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t88F49D4F1C21E0220007422C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D5B1C21E0220007422C /* SecondViewController.swift in Sources */,\n\t\t\t\t88F49D571C21E0220007422C /* AppDelegate.swift in Sources */,\n\t\t\t\t88F49D591C21E0220007422C /* FirstViewController.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D651C21E0220007422C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D6E1C21E0220007422C /* isignTestAppTests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D701C21E0220007422C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D791C21E0220007422C /* isignTestAppUITests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t88F49D6B1C21E0220007422C /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 88F49D521C21E0220007422C /* isignTestApp */;\n\t\t\ttargetProxy = 88F49D6A1C21E0220007422C /* PBXContainerItemProxy */;\n\t\t};\n\t\t88F49D761C21E0220007422C /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 88F49D521C21E0220007422C /* isignTestApp */;\n\t\t\ttargetProxy = 88F49D751C21E0220007422C /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\t88F49D5C1C21E0220007422C /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D5D1C21E0220007422C /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D611C21E0220007422C /* LaunchScreen.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D621C21E0220007422C /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t88F49D7B1C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D7C1C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t88F49D7E1C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tINFOPLIST_FILE = isignTestApp/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestApp;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D7F1C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tINFOPLIST_FILE = isignTestApp/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestApp;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t88F49D811C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tINFOPLIST_FILE = isignTestAppTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/isignTestApp.app/isignTestApp\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D821C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tINFOPLIST_FILE = isignTestAppTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/isignTestApp.app/isignTestApp\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t88F49D841C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = isignTestAppUITests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppUITests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_TARGET_NAME = isignTestApp;\n\t\t\t\tUSES_XCTRUNNER = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D851C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = isignTestAppUITests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppUITests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_TARGET_NAME = isignTestApp;\n\t\t\t\tUSES_XCTRUNNER = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t88F49D4E1C21E0220007422C /* Build configuration list for PBXProject \"isignTestApp\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D7B1C21E0220007422C /* Debug */,\n\t\t\t\t88F49D7C1C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t88F49D7D1C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestApp\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D7E1C21E0220007422C /* Debug */,\n\t\t\t\t88F49D7F1C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t};\n\t\t88F49D801C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D811C21E0220007422C /* Debug */,\n\t\t\t\t88F49D821C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t};\n\t\t88F49D831C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppUITests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D841C21E0220007422C /* Debug */,\n\t\t\t\t88F49D851C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 88F49D4B1C21E0220007422C /* Project object */;\n}\n"
  },
  {
    "path": "tests/Test_unsigned_fat.app/isignTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:isignTestApp.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "tests/Test_unsigned_fat.app/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/isignTestApp.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0720\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n               BuildableName = \"isignTestApp.app\"\n               BlueprintName = \"isignTestApp\"\n               ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"88F49D681C21E0220007422C\"\n               BuildableName = \"isignTestAppTests.xctest\"\n               BlueprintName = \"isignTestAppTests\"\n               ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"88F49D731C21E0220007422C\"\n               BuildableName = \"isignTestAppUITests.xctest\"\n               BlueprintName = \"isignTestAppUITests\"\n               ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n            BuildableName = \"isignTestApp.app\"\n            BlueprintName = \"isignTestApp\"\n            ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n            BuildableName = \"isignTestApp.app\"\n            BlueprintName = \"isignTestApp\"\n            ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n            BuildableName = \"isignTestApp.app\"\n            BlueprintName = \"isignTestApp\"\n            ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "tests/Test_unsigned_fat.app/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/xcschememanagement.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>SchemeUserState</key>\n\t<dict>\n\t\t<key>isignTestApp.xcscheme</key>\n\t\t<dict>\n\t\t\t<key>orderHint</key>\n\t\t\t<integer>0</integer>\n\t\t</dict>\n\t</dict>\n\t<key>SuppressBuildableAutocreation</key>\n\t<dict>\n\t\t<key>88F49D521C21E0220007422C</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>88F49D681C21E0220007422C</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>88F49D731C21E0220007422C</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/Test_unsigned_fat.app/isignTestAppTests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/Test_unsigned_fat.app/isignTestAppTests/isignTestAppTests.swift",
    "content": "//\n//  isignTestAppTests.swift\n//  isignTestAppTests\n//\n//  Created by Neil Kandalgaonkar on 12/16/15.\n//  Copyright © 2015 Sauce Labs. All rights reserved.\n//\n\nimport XCTest\n@testable import isignTestApp\n\nclass isignTestAppTests: XCTestCase {\n    \n    override func setUp() {\n        super.setUp()\n        // Put setup code here. This method is called before the invocation of each test method in the class.\n    }\n    \n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n    \n    func testExample() {\n        // This is an example of a functional test case.\n        // Use XCTAssert and related functions to verify your tests produce the correct results.\n    }\n    \n    func testPerformanceExample() {\n        // This is an example of a performance test case.\n        self.measureBlock {\n            // Put the code you want to measure the time of here.\n        }\n    }\n    \n}\n"
  },
  {
    "path": "tests/Test_unsigned_fat.app/isignTestAppUITests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/Test_unsigned_fat.app/isignTestAppUITests/isignTestAppUITests.swift",
    "content": "//\n//  isignTestAppUITests.swift\n//  isignTestAppUITests\n//\n//  Created by Neil Kandalgaonkar on 12/16/15.\n//  Copyright © 2015 Sauce Labs. All rights reserved.\n//\n\nimport XCTest\n\nclass isignTestAppUITests: XCTestCase {\n        \n    override func setUp() {\n        super.setUp()\n        \n        // Put setup code here. This method is called before the invocation of each test method in the class.\n        \n        // In UI tests it is usually best to stop immediately when a failure occurs.\n        continueAfterFailure = false\n        // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.\n        XCUIApplication().launch()\n\n        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.\n    }\n    \n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n    \n    func testExample() {\n        // Use recording to get started writing UI tests.\n        // Use XCTAssert and related functions to verify your tests produce the correct results.\n    }\n    \n}\n"
  },
  {
    "path": "tests/Test_unsigned_thin.app/PkgInfo",
    "content": "APPL????"
  },
  {
    "path": "tests/Test_unsigned_thin.app/build.sh",
    "content": "#!/bin/bash\n\n# ./build.sh /path/to/isign\n\n# builds various archival formats of the isign test app\n# and puts them in the test directory of isign. You have to specify\n# isign's source directory on the command line\n\n\nproject=isignTestApp\nisign_dir=$1\nisign_test_dir=$isign_dir/tests\n\nwarn() {\n    echo \"$@\" 1>&2;\n}\n\nbuild_app() {\n    local platform=$1;\n    local build_dir=build/Release-$(echo $platform | tr -d \"0-9.\");\n    xcodebuild -project $project.xcodeproj -sdk $platform;\n}\n\ncopy_app() {\n    local platform=$1;\n    local target=$2;\n    local build_dir=$(build_app $platform)\n    cp -r $build_dir/$project.app $target;\n}\n\ncopy_app_zip() {\n    local platform=$1;\n    local target=$2;\n    local build_dir=$(build_app $platform)\n    pushd $build_dir;\n    rm -f app.zip;\n    zip -r app.zip $project.app;\n    popd;\n    mv $build_dir/app.zip $target;\n}\n\n\nbuild_ipa() {\n    local platform=$1\n    local target=$2\n\n    xcodebuild clean -project $project.xcodeproj -configuration Release -sdk $platform;\n    xcodebuild archive -project $project.xcodeproj -scheme $project -archivePath $project.xcarchive\n    xcodebuild -exportArchive \\\n               -archivePath $projectname.xcarchive \\\n               -exportPath $projectname \\\n               -exportFormat ipa \\\n               -exportProvisioningProfile \"Neil Kandalgaonkar\"\n}\n\n\n\ncopy_app     iphoneos9.2        $isign_test_dir/Test.app;\ncopy_app_zip iphoneos9.2        $isign_test_dir/Test.app.zip;\n# build_ipa     iphoneos9.2        $isign_test_dir/Test.ipa;\n# build_app_zip iphonesimulator9.2 $isign_test_dir/TestSimulator.app.zip;\n\n"
  },
  {
    "path": "tests/Test_unsigned_thin.app/isignTestApp.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t88F49D571C21E0220007422C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D561C21E0220007422C /* AppDelegate.swift */; };\n\t\t88F49D591C21E0220007422C /* FirstViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D581C21E0220007422C /* FirstViewController.swift */; };\n\t\t88F49D5B1C21E0220007422C /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D5A1C21E0220007422C /* SecondViewController.swift */; };\n\t\t88F49D5E1C21E0220007422C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88F49D5C1C21E0220007422C /* Main.storyboard */; };\n\t\t88F49D601C21E0220007422C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 88F49D5F1C21E0220007422C /* Assets.xcassets */; };\n\t\t88F49D631C21E0220007422C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88F49D611C21E0220007422C /* LaunchScreen.storyboard */; };\n\t\t88F49D6E1C21E0220007422C /* isignTestAppTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D6D1C21E0220007422C /* isignTestAppTests.swift */; };\n\t\t88F49D791C21E0220007422C /* isignTestAppUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D781C21E0220007422C /* isignTestAppUITests.swift */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t88F49D6A1C21E0220007422C /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 88F49D4B1C21E0220007422C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 88F49D521C21E0220007422C;\n\t\t\tremoteInfo = isignTestApp;\n\t\t};\n\t\t88F49D751C21E0220007422C /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 88F49D4B1C21E0220007422C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 88F49D521C21E0220007422C;\n\t\t\tremoteInfo = isignTestApp;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t88F49D531C21E0220007422C /* isignTestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = isignTestApp.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t88F49D561C21E0220007422C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\t88F49D581C21E0220007422C /* FirstViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstViewController.swift; sourceTree = \"<group>\"; };\n\t\t88F49D5A1C21E0220007422C /* SecondViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondViewController.swift; sourceTree = \"<group>\"; };\n\t\t88F49D5D1C21E0220007422C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\t88F49D5F1C21E0220007422C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t88F49D621C21E0220007422C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = \"<group>\"; };\n\t\t88F49D641C21E0220007422C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t88F49D691C21E0220007422C /* isignTestAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = isignTestAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t88F49D6D1C21E0220007422C /* isignTestAppTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = isignTestAppTests.swift; sourceTree = \"<group>\"; };\n\t\t88F49D6F1C21E0220007422C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t88F49D741C21E0220007422C /* isignTestAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = isignTestAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t88F49D781C21E0220007422C /* isignTestAppUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = isignTestAppUITests.swift; sourceTree = \"<group>\"; };\n\t\t88F49D7A1C21E0220007422C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t88F49D501C21E0220007422C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D661C21E0220007422C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D711C21E0220007422C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t88F49D4A1C21E0220007422C = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D551C21E0220007422C /* isignTestApp */,\n\t\t\t\t88F49D6C1C21E0220007422C /* isignTestAppTests */,\n\t\t\t\t88F49D771C21E0220007422C /* isignTestAppUITests */,\n\t\t\t\t88F49D541C21E0220007422C /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D541C21E0220007422C /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D531C21E0220007422C /* isignTestApp.app */,\n\t\t\t\t88F49D691C21E0220007422C /* isignTestAppTests.xctest */,\n\t\t\t\t88F49D741C21E0220007422C /* isignTestAppUITests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D551C21E0220007422C /* isignTestApp */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D561C21E0220007422C /* AppDelegate.swift */,\n\t\t\t\t88F49D581C21E0220007422C /* FirstViewController.swift */,\n\t\t\t\t88F49D5A1C21E0220007422C /* SecondViewController.swift */,\n\t\t\t\t88F49D5C1C21E0220007422C /* Main.storyboard */,\n\t\t\t\t88F49D5F1C21E0220007422C /* Assets.xcassets */,\n\t\t\t\t88F49D611C21E0220007422C /* LaunchScreen.storyboard */,\n\t\t\t\t88F49D641C21E0220007422C /* Info.plist */,\n\t\t\t);\n\t\t\tpath = isignTestApp;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D6C1C21E0220007422C /* isignTestAppTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D6D1C21E0220007422C /* isignTestAppTests.swift */,\n\t\t\t\t88F49D6F1C21E0220007422C /* Info.plist */,\n\t\t\t);\n\t\t\tpath = isignTestAppTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D771C21E0220007422C /* isignTestAppUITests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D781C21E0220007422C /* isignTestAppUITests.swift */,\n\t\t\t\t88F49D7A1C21E0220007422C /* Info.plist */,\n\t\t\t);\n\t\t\tpath = isignTestAppUITests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t88F49D521C21E0220007422C /* isignTestApp */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 88F49D7D1C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestApp\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t88F49D4F1C21E0220007422C /* Sources */,\n\t\t\t\t88F49D501C21E0220007422C /* Frameworks */,\n\t\t\t\t88F49D511C21E0220007422C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = isignTestApp;\n\t\t\tproductName = isignTestApp;\n\t\t\tproductReference = 88F49D531C21E0220007422C /* isignTestApp.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\t88F49D681C21E0220007422C /* isignTestAppTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 88F49D801C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t88F49D651C21E0220007422C /* Sources */,\n\t\t\t\t88F49D661C21E0220007422C /* Frameworks */,\n\t\t\t\t88F49D671C21E0220007422C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t88F49D6B1C21E0220007422C /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = isignTestAppTests;\n\t\t\tproductName = isignTestAppTests;\n\t\t\tproductReference = 88F49D691C21E0220007422C /* isignTestAppTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\t88F49D731C21E0220007422C /* isignTestAppUITests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 88F49D831C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppUITests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t88F49D701C21E0220007422C /* Sources */,\n\t\t\t\t88F49D711C21E0220007422C /* Frameworks */,\n\t\t\t\t88F49D721C21E0220007422C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t88F49D761C21E0220007422C /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = isignTestAppUITests;\n\t\t\tproductName = isignTestAppUITests;\n\t\t\tproductReference = 88F49D741C21E0220007422C /* isignTestAppUITests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.ui-testing\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t88F49D4B1C21E0220007422C /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastSwiftUpdateCheck = 0720;\n\t\t\t\tLastUpgradeCheck = 0720;\n\t\t\t\tORGANIZATIONNAME = \"Sauce Labs\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t88F49D521C21E0220007422C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t};\n\t\t\t\t\t88F49D681C21E0220007422C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t\tTestTargetID = 88F49D521C21E0220007422C;\n\t\t\t\t\t};\n\t\t\t\t\t88F49D731C21E0220007422C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t\tTestTargetID = 88F49D521C21E0220007422C;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 88F49D4E1C21E0220007422C /* Build configuration list for PBXProject \"isignTestApp\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 88F49D4A1C21E0220007422C;\n\t\t\tproductRefGroup = 88F49D541C21E0220007422C /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t88F49D521C21E0220007422C /* isignTestApp */,\n\t\t\t\t88F49D681C21E0220007422C /* isignTestAppTests */,\n\t\t\t\t88F49D731C21E0220007422C /* isignTestAppUITests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t88F49D511C21E0220007422C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D631C21E0220007422C /* LaunchScreen.storyboard in Resources */,\n\t\t\t\t88F49D601C21E0220007422C /* Assets.xcassets in Resources */,\n\t\t\t\t88F49D5E1C21E0220007422C /* Main.storyboard in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D671C21E0220007422C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D721C21E0220007422C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t88F49D4F1C21E0220007422C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D5B1C21E0220007422C /* SecondViewController.swift in Sources */,\n\t\t\t\t88F49D571C21E0220007422C /* AppDelegate.swift in Sources */,\n\t\t\t\t88F49D591C21E0220007422C /* FirstViewController.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D651C21E0220007422C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D6E1C21E0220007422C /* isignTestAppTests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D701C21E0220007422C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D791C21E0220007422C /* isignTestAppUITests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t88F49D6B1C21E0220007422C /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 88F49D521C21E0220007422C /* isignTestApp */;\n\t\t\ttargetProxy = 88F49D6A1C21E0220007422C /* PBXContainerItemProxy */;\n\t\t};\n\t\t88F49D761C21E0220007422C /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 88F49D521C21E0220007422C /* isignTestApp */;\n\t\t\ttargetProxy = 88F49D751C21E0220007422C /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\t88F49D5C1C21E0220007422C /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D5D1C21E0220007422C /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D611C21E0220007422C /* LaunchScreen.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D621C21E0220007422C /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t88F49D7B1C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D7C1C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t88F49D7E1C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tINFOPLIST_FILE = isignTestApp/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestApp;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D7F1C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tINFOPLIST_FILE = isignTestApp/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestApp;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t88F49D811C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tINFOPLIST_FILE = isignTestAppTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/isignTestApp.app/isignTestApp\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D821C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tINFOPLIST_FILE = isignTestAppTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/isignTestApp.app/isignTestApp\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t88F49D841C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = isignTestAppUITests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppUITests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_TARGET_NAME = isignTestApp;\n\t\t\t\tUSES_XCTRUNNER = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D851C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = isignTestAppUITests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppUITests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_TARGET_NAME = isignTestApp;\n\t\t\t\tUSES_XCTRUNNER = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t88F49D4E1C21E0220007422C /* Build configuration list for PBXProject \"isignTestApp\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D7B1C21E0220007422C /* Debug */,\n\t\t\t\t88F49D7C1C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t88F49D7D1C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestApp\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D7E1C21E0220007422C /* Debug */,\n\t\t\t\t88F49D7F1C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t};\n\t\t88F49D801C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D811C21E0220007422C /* Debug */,\n\t\t\t\t88F49D821C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t};\n\t\t88F49D831C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppUITests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D841C21E0220007422C /* Debug */,\n\t\t\t\t88F49D851C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 88F49D4B1C21E0220007422C /* Project object */;\n}\n"
  },
  {
    "path": "tests/Test_unsigned_thin.app/isignTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:isignTestApp.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "tests/Test_unsigned_thin.app/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/isignTestApp.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0720\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n               BuildableName = \"isignTestApp.app\"\n               BlueprintName = \"isignTestApp\"\n               ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"88F49D681C21E0220007422C\"\n               BuildableName = \"isignTestAppTests.xctest\"\n               BlueprintName = \"isignTestAppTests\"\n               ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"88F49D731C21E0220007422C\"\n               BuildableName = \"isignTestAppUITests.xctest\"\n               BlueprintName = \"isignTestAppUITests\"\n               ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n            BuildableName = \"isignTestApp.app\"\n            BlueprintName = \"isignTestApp\"\n            ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n            BuildableName = \"isignTestApp.app\"\n            BlueprintName = \"isignTestApp\"\n            ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n            BuildableName = \"isignTestApp.app\"\n            BlueprintName = \"isignTestApp\"\n            ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "tests/Test_unsigned_thin.app/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/xcschememanagement.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>SchemeUserState</key>\n\t<dict>\n\t\t<key>isignTestApp.xcscheme</key>\n\t\t<dict>\n\t\t\t<key>orderHint</key>\n\t\t\t<integer>0</integer>\n\t\t</dict>\n\t</dict>\n\t<key>SuppressBuildableAutocreation</key>\n\t<dict>\n\t\t<key>88F49D521C21E0220007422C</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>88F49D681C21E0220007422C</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>88F49D731C21E0220007422C</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/Test_unsigned_thin.app/isignTestAppTests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/Test_unsigned_thin.app/isignTestAppTests/isignTestAppTests.swift",
    "content": "//\n//  isignTestAppTests.swift\n//  isignTestAppTests\n//\n//  Created by Neil Kandalgaonkar on 12/16/15.\n//  Copyright © 2015 Sauce Labs. All rights reserved.\n//\n\nimport XCTest\n@testable import isignTestApp\n\nclass isignTestAppTests: XCTestCase {\n    \n    override func setUp() {\n        super.setUp()\n        // Put setup code here. This method is called before the invocation of each test method in the class.\n    }\n    \n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n    \n    func testExample() {\n        // This is an example of a functional test case.\n        // Use XCTAssert and related functions to verify your tests produce the correct results.\n    }\n    \n    func testPerformanceExample() {\n        // This is an example of a performance test case.\n        self.measureBlock {\n            // Put the code you want to measure the time of here.\n        }\n    }\n    \n}\n"
  },
  {
    "path": "tests/Test_unsigned_thin.app/isignTestAppUITests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/Test_unsigned_thin.app/isignTestAppUITests/isignTestAppUITests.swift",
    "content": "//\n//  isignTestAppUITests.swift\n//  isignTestAppUITests\n//\n//  Created by Neil Kandalgaonkar on 12/16/15.\n//  Copyright © 2015 Sauce Labs. All rights reserved.\n//\n\nimport XCTest\n\nclass isignTestAppUITests: XCTestCase {\n        \n    override func setUp() {\n        super.setUp()\n        \n        // Put setup code here. This method is called before the invocation of each test method in the class.\n        \n        // In UI tests it is usually best to stop immediately when a failure occurs.\n        continueAfterFailure = false\n        // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.\n        XCUIApplication().launch()\n\n        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.\n    }\n    \n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n    \n    func testExample() {\n        // Use recording to get started writing UI tests.\n        // Use XCTAssert and related functions to verify your tests produce the correct results.\n    }\n    \n}\n"
  },
  {
    "path": "tests/bad_openssl",
    "content": "#!/bin/bash\n\n# returns nothing; simulates what happens with bad versions of openssl\n"
  },
  {
    "path": "tests/credentials/README.rst",
    "content": "The test credentials in this directory cannot be used to sign apps for use on any iOS device. They\nare sufficiently similar to a real key, certificate and provisioning profile to make\nthe tests pass. \n\nThe key was generated solely for this library, and the certificate is self-signed. A working\nkey would have to be certified by Apple.\n\nThe provisioning profile was created with makeFakePprof.sh and test.mobileprovision.plist. The structure\nis based on a real provisioning profile, but all data has been swapped for meaningless noise.\n"
  },
  {
    "path": "tests/credentials/makeFakePprof.sh",
    "content": "#!/bin/bash\n\nopenssl smime -sign -in test.mobileprovision.plist -outform der -out test.mobileprovision -signer test.cert.pem -inkey test.key.pem -nodetach\n"
  },
  {
    "path": "tests/credentials/test.cert.pem",
    "content": "Bag Attributes\n    friendlyName: isign_tests\n    localKeyID: 25 67 EB F6 B5 12 B7 2F E7 38 49 10 87 2C 92 7D 0A 9D C2 63 \nsubject=/CN=isign_tests/O=isign tests/OU=ISIGNTESTS/ST=CA/C=US/L=San Francisco/emailAddress=dev@saucelabs.com\nissuer=/CN=isign_tests/O=isign tests/OU=ISIGNTESTS/ST=CA/C=US/L=San Francisco/emailAddress=dev@saucelabs.com\n-----BEGIN CERTIFICATE-----\nMIID0TCCArmgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlTEUMBIGA1UEAwwLaXNp\nZ25fdGVzdHMxFDASBgNVBAoMC2lzaWduIHRlc3RzMRMwEQYDVQQLDApJU0lHTlRF\nU1RTMQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMxFjAUBgNVBAcMDVNhbiBGcmFu\nY2lzY28xIDAeBgkqhkiG9w0BCQEWEWRldkBzYXVjZWxhYnMuY29tMB4XDTE1MTAy\nMjE5MTMwN1oXDTI1MTAxOTE5MTMwN1owgZUxFDASBgNVBAMMC2lzaWduX3Rlc3Rz\nMRQwEgYDVQQKDAtpc2lnbiB0ZXN0czETMBEGA1UECwwKSVNJR05URVNUUzELMAkG\nA1UECAwCQ0ExCzAJBgNVBAYTAlVTMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMSAw\nHgYJKoZIhvcNAQkBFhFkZXZAc2F1Y2VsYWJzLmNvbTCCASIwDQYJKoZIhvcNAQEB\nBQADggEPADCCAQoCggEBAPKEyqq6txSChIsoVv0tgAI4o8BDGqAUwqjUT9Ha1byK\npUS/YVtHeaC9ozPNSndlAfFvUiwV+MD0rPznZojQnKtYy6RCIaGySox6FeNqFmL+\nxBUTwQaV2IqZEKUJLSDLY4ExPf98LLdxrieyUWR+ldA0Vatne6aTxqeKjEwUKbBW\nkcSJrYM9I4Z/Z6AGomph+blXWOg0ly5QshxJzXDjn7i8MdW0ry3YpIHLDoSJieW/\nrUNSBiG5b1xy3TNqSrUjyCK4qr0HJqPFaDfuzCKyUJVnYZHkt1+qZ1mmX2CWavtE\n2+s7Uf/Tw10fMszXjXKIP7uxlTOjbfPfgE2Q3RUCSosCAwEAAaMqMCgwDgYDVR0P\nAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUA\nA4IBAQChOZBtgbtJshb/hEm9Ue06TQEqFCdn7N4MoiuwNgq7oO4/xikFBdCE6dcR\nBaqdnsqSFOGvSfNPW1O/ha4nMP65UoKxsoFI40CpjTwRpHUH7g9OGK7a9nsLGDla\nh3BR80V2j2FmgJbjuSQaFSvI4f7rOSAJrOUFu54ofLK3FokjjurpjsaKS+6NDnzB\nPXwBsXBbvjvlyb/0ejLVRiYBYSLfmdjjYpBF+3HaDAzEDXCylZdOzvf11o2aOYHL\nMaEANSFZe09sV2JecwnxoWEWGb7+IgZKNq0hn1ckhumib1gmOkOp6JtyxviEB1yw\nE4pd+A1hdAwzsqKr3xxZmisaV8yH\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "tests/credentials/test.key.pem",
    "content": "Bag Attributes\n    friendlyName: isign_tests\n    localKeyID: 25 67 EB F6 B5 12 B7 2F E7 38 49 10 87 2C 92 7D 0A 9D C2 63 \nKey Attributes: <No Attributes>\n-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEA8oTKqrq3FIKEiyhW/S2AAjijwEMaoBTCqNRP0drVvIqlRL9h\nW0d5oL2jM81Kd2UB8W9SLBX4wPSs/OdmiNCcq1jLpEIhobJKjHoV42oWYv7EFRPB\nBpXYipkQpQktIMtjgTE9/3wst3GuJ7JRZH6V0DRVq2d7ppPGp4qMTBQpsFaRxImt\ngz0jhn9noAaiamH5uVdY6DSXLlCyHEnNcOOfuLwx1bSvLdikgcsOhImJ5b+tQ1IG\nIblvXHLdM2pKtSPIIriqvQcmo8VoN+7MIrJQlWdhkeS3X6pnWaZfYJZq+0Tb6ztR\n/9PDXR8yzNeNcog/u7GVM6Nt89+ATZDdFQJKiwIDAQABAoIBAQDtyhx5qJgIqSzS\n0Vvx5KImC2ksA9/gZFq1dW9KQbreokcIEGqiOIPegvK5wSmpxcVQ+Kjmhyif8YiI\ndU/JCFsFeww5Y4pcZFfKQ46grA2FRW33iKX0Egr/YrO6TjQMesB3FVRH5HZn7DQp\nwiMiWSgFvLrfVJkeLLlU33lOw1pZBbAhNaZK+DQ2nuLDg1mIbJ1B0VRvEo5zVS4r\nCZo8otr3MAkdTbjhqaoGDZuRnjzd72Zl/VCxlg55IJP45WV2hHWt7ofH0RjQ4KSA\nXIuh9KJWf9f6vVv2oZ+nY6P6EA2mzIBKzlfpcPNvUeh+gW4Ln2kbsxnIp2VxU2D+\nUH+oVclpAoGBAP+Risu98rg1et1Sh5oHe2MIZ18n2M01qhqdJx5fY28+7GHVTdvn\nBMaooojpxYJ/aEY2M5oZfG6twCpLN5+YTFsycDsdL5ALoMqGLDdBbtNjmVzQUzuN\ng0oZvu6Xi9qN9GGF84falS+tchAOGQahw+mpWRtqnmNI60geo5V/Ng+lAoGBAPLt\nm/vwM/s09XnFozfX2tdpWUjPUnDRCFWQBSNpnqjeUi4B/evMxXhZIT+z2Vg+cRru\nA4xLRJ2ZQbEYsTPxejCoMJsKD48pFi1KDDAN0HQSKPwKgwHoBJjIGoxb4gV5Uz0T\nFiXMp8667vI2O6VlQZYfvx1K4qsbjRBLQReyE9pvAoGAMVx5BFURtkaODoVML5HW\nYRBUduqJU0lUK4PC9HjUCb6LhXHfceOy5nPXwL32KfhVuYnqeY8Gm5HvlbulaKvP\nw6WAS8qdTyMP0U4M6Dc5IpcQHf8WtF/mxb8nQ4n9tx7H3rYyjUDIo8bKSxON/dvs\nrQrKbSMwqFiDKRDR46QIWwkCgYBL4l1vfcE/H3Pu7gXmU89Qqt/xFpIyG5n24F46\niau+JHSXWpfvKLAmv/Da7VtfbWH3f5IsKPbuJAmZQJVaHHyG5oMIa0Qg/DypORBF\nkosjNukGkmIKHmgRMbDZV3prK1MNKQEqHZvtwAcUMky/hbnPI2uXwuS7foe6J0fW\nFxKMkQKBgBzo3nCUC9nu48abop7wOBUERZAGVTdHEHA97wIgpSkAagMBrkf0f+fN\nhx00UefaJQLvJNPmUQ8t0rmdQX0HkGVAPA2Eek8e2fjpvzjhyUNKb47VllBBm/H/\nqoQZOsKh8YWy373DPydoi9MsFal4E1Pi56co1At6hf4TICWJBedd\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "tests/credentials/test.mobileprovision.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>AppIDName</key>\n\t<string>isign tests</string>\n\t<key>ApplicationIdentifierPrefix</key>\n\t<array>\n\t<string>ISIGNTESTS</string>\n\t</array>\n\t<key>CreationDate</key>\n\t<date>2016-11-28T22:57:49Z</date>\n\t<key>Platform</key>\n\t<array>\n\t\t<string>iOS</string>\n\t</array>\n\t<key>DeveloperCertificates</key>\n\t<array>\n    <data>MIID0TCCArmgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlTEUMBIGA1UEAwwLaXNpZ25fdGVzdHMxFDASBgNVBAoMC2lzaWduIHRlc3RzMRMwEQYDVQQLDApJU0lHTlRFU1RTMQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMxFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xIDAeBgkqhkiG9w0BCQEWEWRldkBzYXVjZWxhYnMuY29tMB4XDTE1MTAyMjE5MTMwN1oXDTI1MTAxOTE5MTMwN1owgZUxFDASBgNVBAMMC2lzaWduX3Rlc3RzMRQwEgYDVQQKDAtpc2lnbiB0ZXN0czETMBEGA1UECwwKSVNJR05URVNUUzELMAkGA1UECAwCQ0ExCzAJBgNVBAYTAlVTMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMSAwHgYJKoZIhvcNAQkBFhFkZXZAc2F1Y2VsYWJzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPKEyqq6txSChIsoVv0tgAI4o8BDGqAUwqjUT9Ha1byKpUS/YVtHeaC9ozPNSndlAfFvUiwV+MD0rPznZojQnKtYy6RCIaGySox6FeNqFmL+xBUTwQaV2IqZEKUJLSDLY4ExPf98LLdxrieyUWR+ldA0Vatne6aTxqeKjEwUKbBWkcSJrYM9I4Z/Z6AGomph+blXWOg0ly5QshxJzXDjn7i8MdW0ry3YpIHLDoSJieW/rUNSBiG5b1xy3TNqSrUjyCK4qr0HJqPFaDfuzCKyUJVnYZHkt1+qZ1mmX2CWavtE2+s7Uf/Tw10fMszXjXKIP7uxlTOjbfPfgE2Q3RUCSosCAwEAAaMqMCgwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBAQChOZBtgbtJshb/hEm9Ue06TQEqFCdn7N4MoiuwNgq7oO4/xikFBdCE6dcRBaqdnsqSFOGvSfNPW1O/ha4nMP65UoKxsoFI40CpjTwRpHUH7g9OGK7a9nsLGDlah3BR80V2j2FmgJbjuSQaFSvI4f7rOSAJrOUFu54ofLK3FokjjurpjsaKS+6NDnzBPXwBsXBbvjvlyb/0ejLVRiYBYSLfmdjjYpBF+3HaDAzEDXCylZdOzvf11o2aOYHLMaEANSFZe09sV2JecwnxoWEWGb7+IgZKNq0hn1ckhumib1gmOkOp6JtyxviEB1ywE4pd+A1hdAwzsqKr3xxZmisaV8yH</data>\n  </array>\n\t<key>Entitlements</key>\n\t<dict>\n\t\t<key>keychain-access-groups</key>\n\t\t<array>\n\t\t\t<string>ISIGNTESTS.*</string>\n\t\t</array>\n\t\t<key>get-task-allow</key>\n\t\t<true/>\n\t\t<key>application-identifier</key>\n\t\t<string>ISIGNTESTS.*</string>\n\t\t<key>com.apple.developer.team-identifier</key>\n\t\t<string>ISIGNTESTS</string>\n\t</dict>\n\t<key>ExpirationDate</key>\n\t<date>2017-11-28T22:57:49Z</date>\n\t<key>Name</key>\n\t<string>RDC-Dev</string>\n\t<key>ProvisionedDevices</key>\n  <array>\n\t\t<string>e2cd3a02c1a3f69a5ff05bce3ea1b1092b30efe0</string>\n\t\t<string>0a0fd3dcb248d3c001a586e8f638800e18c54efc</string>\n\t</array>\n\t<key>TeamIdentifier</key>\n\t<array>\n\t\t<string>ISIGNTESTS</string>\n\t</array>\n\t<key>TeamName</key>\n\t<string>ISIGN OPEN SOURCE</string>\n\t<key>TimeToLive</key>\n\t<integer>365</integer>\n\t<key>UUID</key>\n  <string>f4d8aa37-45a7-4304-960c-1291e1a5a0f3</string>\n\t<key>Version</key>\n\t<integer>1</integer>\n</dict>\n</plist>\n\n\n"
  },
  {
    "path": "tests/credentials_std_names/README.rst",
    "content": "These credentials exist to test the 'credentials directory' feature in isign.\n\nThe credentials are copied from ../credentials and just have the correct names.\n"
  },
  {
    "path": "tests/credentials_std_names/certificate.pem",
    "content": "Bag Attributes\n    friendlyName: isign_tests\n    localKeyID: 25 67 EB F6 B5 12 B7 2F E7 38 49 10 87 2C 92 7D 0A 9D C2 63 \nsubject=/CN=isign_tests/O=isign tests/OU=ISIGNTESTS/ST=CA/C=US/L=San Francisco/emailAddress=dev@saucelabs.com\nissuer=/CN=isign_tests/O=isign tests/OU=ISIGNTESTS/ST=CA/C=US/L=San Francisco/emailAddress=dev@saucelabs.com\n-----BEGIN CERTIFICATE-----\nMIID0TCCArmgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlTEUMBIGA1UEAwwLaXNp\nZ25fdGVzdHMxFDASBgNVBAoMC2lzaWduIHRlc3RzMRMwEQYDVQQLDApJU0lHTlRF\nU1RTMQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMxFjAUBgNVBAcMDVNhbiBGcmFu\nY2lzY28xIDAeBgkqhkiG9w0BCQEWEWRldkBzYXVjZWxhYnMuY29tMB4XDTE1MTAy\nMjE5MTMwN1oXDTI1MTAxOTE5MTMwN1owgZUxFDASBgNVBAMMC2lzaWduX3Rlc3Rz\nMRQwEgYDVQQKDAtpc2lnbiB0ZXN0czETMBEGA1UECwwKSVNJR05URVNUUzELMAkG\nA1UECAwCQ0ExCzAJBgNVBAYTAlVTMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMSAw\nHgYJKoZIhvcNAQkBFhFkZXZAc2F1Y2VsYWJzLmNvbTCCASIwDQYJKoZIhvcNAQEB\nBQADggEPADCCAQoCggEBAPKEyqq6txSChIsoVv0tgAI4o8BDGqAUwqjUT9Ha1byK\npUS/YVtHeaC9ozPNSndlAfFvUiwV+MD0rPznZojQnKtYy6RCIaGySox6FeNqFmL+\nxBUTwQaV2IqZEKUJLSDLY4ExPf98LLdxrieyUWR+ldA0Vatne6aTxqeKjEwUKbBW\nkcSJrYM9I4Z/Z6AGomph+blXWOg0ly5QshxJzXDjn7i8MdW0ry3YpIHLDoSJieW/\nrUNSBiG5b1xy3TNqSrUjyCK4qr0HJqPFaDfuzCKyUJVnYZHkt1+qZ1mmX2CWavtE\n2+s7Uf/Tw10fMszXjXKIP7uxlTOjbfPfgE2Q3RUCSosCAwEAAaMqMCgwDgYDVR0P\nAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUA\nA4IBAQChOZBtgbtJshb/hEm9Ue06TQEqFCdn7N4MoiuwNgq7oO4/xikFBdCE6dcR\nBaqdnsqSFOGvSfNPW1O/ha4nMP65UoKxsoFI40CpjTwRpHUH7g9OGK7a9nsLGDla\nh3BR80V2j2FmgJbjuSQaFSvI4f7rOSAJrOUFu54ofLK3FokjjurpjsaKS+6NDnzB\nPXwBsXBbvjvlyb/0ejLVRiYBYSLfmdjjYpBF+3HaDAzEDXCylZdOzvf11o2aOYHL\nMaEANSFZe09sV2JecwnxoWEWGb7+IgZKNq0hn1ckhumib1gmOkOp6JtyxviEB1yw\nE4pd+A1hdAwzsqKr3xxZmisaV8yH\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "tests/credentials_std_names_2/README.rst",
    "content": "These credentials exist to test the 'multisign' feature in isign\n\nThe credentials are copied from ../credentials_std_names, and exist solely to have\na separate path to point to them.\n"
  },
  {
    "path": "tests/credentials_std_names_2/certificate.pem",
    "content": "Bag Attributes\n    friendlyName: isign_tests\n    localKeyID: 25 67 EB F6 B5 12 B7 2F E7 38 49 10 87 2C 92 7D 0A 9D C2 63 \nsubject=/CN=isign_tests/O=isign tests/OU=ISIGNTESTS/ST=CA/C=US/L=San Francisco/emailAddress=dev@saucelabs.com\nissuer=/CN=isign_tests/O=isign tests/OU=ISIGNTESTS/ST=CA/C=US/L=San Francisco/emailAddress=dev@saucelabs.com\n-----BEGIN CERTIFICATE-----\nMIID0TCCArmgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlTEUMBIGA1UEAwwLaXNp\nZ25fdGVzdHMxFDASBgNVBAoMC2lzaWduIHRlc3RzMRMwEQYDVQQLDApJU0lHTlRF\nU1RTMQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMxFjAUBgNVBAcMDVNhbiBGcmFu\nY2lzY28xIDAeBgkqhkiG9w0BCQEWEWRldkBzYXVjZWxhYnMuY29tMB4XDTE1MTAy\nMjE5MTMwN1oXDTI1MTAxOTE5MTMwN1owgZUxFDASBgNVBAMMC2lzaWduX3Rlc3Rz\nMRQwEgYDVQQKDAtpc2lnbiB0ZXN0czETMBEGA1UECwwKSVNJR05URVNUUzELMAkG\nA1UECAwCQ0ExCzAJBgNVBAYTAlVTMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMSAw\nHgYJKoZIhvcNAQkBFhFkZXZAc2F1Y2VsYWJzLmNvbTCCASIwDQYJKoZIhvcNAQEB\nBQADggEPADCCAQoCggEBAPKEyqq6txSChIsoVv0tgAI4o8BDGqAUwqjUT9Ha1byK\npUS/YVtHeaC9ozPNSndlAfFvUiwV+MD0rPznZojQnKtYy6RCIaGySox6FeNqFmL+\nxBUTwQaV2IqZEKUJLSDLY4ExPf98LLdxrieyUWR+ldA0Vatne6aTxqeKjEwUKbBW\nkcSJrYM9I4Z/Z6AGomph+blXWOg0ly5QshxJzXDjn7i8MdW0ry3YpIHLDoSJieW/\nrUNSBiG5b1xy3TNqSrUjyCK4qr0HJqPFaDfuzCKyUJVnYZHkt1+qZ1mmX2CWavtE\n2+s7Uf/Tw10fMszXjXKIP7uxlTOjbfPfgE2Q3RUCSosCAwEAAaMqMCgwDgYDVR0P\nAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUA\nA4IBAQChOZBtgbtJshb/hEm9Ue06TQEqFCdn7N4MoiuwNgq7oO4/xikFBdCE6dcR\nBaqdnsqSFOGvSfNPW1O/ha4nMP65UoKxsoFI40CpjTwRpHUH7g9OGK7a9nsLGDla\nh3BR80V2j2FmgJbjuSQaFSvI4f7rOSAJrOUFu54ofLK3FokjjurpjsaKS+6NDnzB\nPXwBsXBbvjvlyb/0ejLVRiYBYSLfmdjjYpBF+3HaDAzEDXCylZdOzvf11o2aOYHL\nMaEANSFZe09sV2JecwnxoWEWGb7+IgZKNq0hn1ckhumib1gmOkOp6JtyxviEB1yw\nE4pd+A1hdAwzsqKr3xxZmisaV8yH\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "tests/credentials_std_names_2/key.pem",
    "content": "Bag Attributes\n    friendlyName: isign_tests\n    localKeyID: 25 67 EB F6 B5 12 B7 2F E7 38 49 10 87 2C 92 7D 0A 9D C2 63 \nKey Attributes: <No Attributes>\n-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEA8oTKqrq3FIKEiyhW/S2AAjijwEMaoBTCqNRP0drVvIqlRL9h\nW0d5oL2jM81Kd2UB8W9SLBX4wPSs/OdmiNCcq1jLpEIhobJKjHoV42oWYv7EFRPB\nBpXYipkQpQktIMtjgTE9/3wst3GuJ7JRZH6V0DRVq2d7ppPGp4qMTBQpsFaRxImt\ngz0jhn9noAaiamH5uVdY6DSXLlCyHEnNcOOfuLwx1bSvLdikgcsOhImJ5b+tQ1IG\nIblvXHLdM2pKtSPIIriqvQcmo8VoN+7MIrJQlWdhkeS3X6pnWaZfYJZq+0Tb6ztR\n/9PDXR8yzNeNcog/u7GVM6Nt89+ATZDdFQJKiwIDAQABAoIBAQDtyhx5qJgIqSzS\n0Vvx5KImC2ksA9/gZFq1dW9KQbreokcIEGqiOIPegvK5wSmpxcVQ+Kjmhyif8YiI\ndU/JCFsFeww5Y4pcZFfKQ46grA2FRW33iKX0Egr/YrO6TjQMesB3FVRH5HZn7DQp\nwiMiWSgFvLrfVJkeLLlU33lOw1pZBbAhNaZK+DQ2nuLDg1mIbJ1B0VRvEo5zVS4r\nCZo8otr3MAkdTbjhqaoGDZuRnjzd72Zl/VCxlg55IJP45WV2hHWt7ofH0RjQ4KSA\nXIuh9KJWf9f6vVv2oZ+nY6P6EA2mzIBKzlfpcPNvUeh+gW4Ln2kbsxnIp2VxU2D+\nUH+oVclpAoGBAP+Risu98rg1et1Sh5oHe2MIZ18n2M01qhqdJx5fY28+7GHVTdvn\nBMaooojpxYJ/aEY2M5oZfG6twCpLN5+YTFsycDsdL5ALoMqGLDdBbtNjmVzQUzuN\ng0oZvu6Xi9qN9GGF84falS+tchAOGQahw+mpWRtqnmNI60geo5V/Ng+lAoGBAPLt\nm/vwM/s09XnFozfX2tdpWUjPUnDRCFWQBSNpnqjeUi4B/evMxXhZIT+z2Vg+cRru\nA4xLRJ2ZQbEYsTPxejCoMJsKD48pFi1KDDAN0HQSKPwKgwHoBJjIGoxb4gV5Uz0T\nFiXMp8667vI2O6VlQZYfvx1K4qsbjRBLQReyE9pvAoGAMVx5BFURtkaODoVML5HW\nYRBUduqJU0lUK4PC9HjUCb6LhXHfceOy5nPXwL32KfhVuYnqeY8Gm5HvlbulaKvP\nw6WAS8qdTyMP0U4M6Dc5IpcQHf8WtF/mxb8nQ4n9tx7H3rYyjUDIo8bKSxON/dvs\nrQrKbSMwqFiDKRDR46QIWwkCgYBL4l1vfcE/H3Pu7gXmU89Qqt/xFpIyG5n24F46\niau+JHSXWpfvKLAmv/Da7VtfbWH3f5IsKPbuJAmZQJVaHHyG5oMIa0Qg/DypORBF\nkosjNukGkmIKHmgRMbDZV3prK1MNKQEqHZvtwAcUMky/hbnPI2uXwuS7foe6J0fW\nFxKMkQKBgBzo3nCUC9nu48abop7wOBUERZAGVTdHEHA97wIgpSkAagMBrkf0f+fN\nhx00UefaJQLvJNPmUQ8t0rmdQX0HkGVAPA2Eek8e2fjpvzjhyUNKb47VllBBm/H/\nqoQZOsKh8YWy373DPydoi9MsFal4E1Pi56co1At6hf4TICWJBedd\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "tests/generate_codesig_construct_txt.py",
    "content": "# generate a string representation of a signature parse for an app - do this to generate\n# test files such as Test.app.codesig.construct.txt\n\nfrom isign_base_test import IsignBaseTest\nimport isign.archive\nfrom isign.signable import Executable\n\nimport logging\n\nFORMATTER = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')\n\n\ndef log_to_stderr(level=logging.INFO):\n    root = logging.getLogger()\n    root.setLevel(level)\n    handler = logging.StreamHandler()\n    handler.setFormatter(FORMATTER)\n    root.addHandler(handler)\n\n\nlog_to_stderr(logging.DEBUG)\nlog = logging.getLogger(__name__)\nlog.debug(\"generating a signature parse for an app\")\napp = isign.archive.AppArchive(IsignBaseTest.TEST_APP)\nexecutable = Executable(app.get_executable_path())\narch = executable.arches[0]\ncodesig_str = str(arch['cmds']['LC_CODE_SIGNATURE'])\nprint codesig_str\n"
  },
  {
    "path": "tests/isignTestApp/.gitignore",
    "content": "build\n"
  },
  {
    "path": "tests/isignTestApp/README.md",
    "content": "# isignTestApp\n\nProject to create a very simple test app for isign's test suite.\n\nRun `./build.sh` to create the necessary test app, app.zip, .ipa, and simulator app in the\nisign test directory (which is the containing directory).\n\n## Caveats\n\nCurrently, the TeamID specified is Neil Kandalgaonkar (neilk@neilk.net's) personal\norganization ID. For this to work, you would also need a provisioning profile installed \nin the right places on your system (the obvious thing is to use XCode). So... you pretty\nmuch need to be Neil to build this, unless you modify the `build.sh` script.\n\nFor obvious reasons this is a problem going forward - we'll need to create some sort\nof Apple account which the community can use to sign the test apps. But on the assumption\nthat we will only need to recreate the test apps very rarely, we're open sourcing it as it is,\nfor now.\n"
  },
  {
    "path": "tests/isignTestApp/build.sh",
    "content": "#!/bin/bash\n\n# ./build.sh /path/to/isign\n\n# builds various archival formats of the isign test app\n# and puts them in the test directory of isign. You have to specify\n# isign's source directory on the command line\n#\n# Also you have to have the provisioning profile mentioned configured\n# in the app. \n#\n\nisign_test_dir=..\n\nproject=isignTestApp\n\n# this project just has one scheme configured, same name as project\nscheme=$project\n\n# This file must exist in this directory.\nexport_options_plist=exportOptions.plist\n\n\nwarn() {\n    echo \"$@\" 1>&2;\n}\n\nplatform_to_build_dir() {\n    echo build/Release-$(echo $1 | tr -d \"0-9.\");\n}\n\nbuild_app() {\n    local platform=$1;\n    xcodebuild -project $project.xcodeproj -sdk $platform >&2;\n}\n\ncopy_app() {\n    local platform=$1;\n    local target=$2;\n    build_app $platform\n    local build_dir=$(platform_to_build_dir $platform);\n    rm -r $target\n    cp -r $build_dir/$project.app $target;\n}\n\ncopy_app_zip() {\n    local platform=$1;\n    local target=$2;\n    build_app $platform\n    local build_dir=$(platform_to_build_dir $platform);\n    pushd $build_dir;\n    rm -f app.zip;\n    zip -r app.zip $project.app;\n    popd;\n    mv $build_dir/app.zip $target;\n}\n\ncopy_ipa() {\n    local platform=$1\n    local target=$2\n\n    archive_path=build/$project.xcarchive\n    ipa_dir=build\n    ipa_path=$ipa_dir/$project.ipa\n    rm -f $ipa_path;\n    \n    xcodebuild clean -project $project.xcodeproj -configuration Release -sdk $platform;\n    xcodebuild archive -project $project.xcodeproj -scheme $scheme -archivePath $archive_path;\n    xcodebuild -exportArchive \\\n               -archivePath $archive_path \\\n               -exportPath $ipa_dir \\\n               -exportOptionsPlist $export_options_plist \n\n    cp $ipa_path $target;\n}\n\n\n\nif [[ -n $rvm_path ]]; then\n    warn \"========\";\n    warn \"\"\n    warn \"ACHTUNG!! \"\n    warn \"rvm users! switch to the system version of ruby with: \";\n    warn \"    $ rvm use system\";\n    warn \"otherwise your path to some ruby development tools like ipatool may be wrong\";\n    warn \"\"\n    warn \"========\";\nfi\n\ncopy_app     iphoneos9.2 $isign_test_dir/Test.app;\ncopy_app_zip iphoneos9.2 $isign_test_dir/Test.app.zip;\ncopy_ipa     iphoneos9.2 $isign_test_dir/Test.ipa;\ncopy_app_zip iphonesimulator9.2 $isign_test_dir/TestSimulator.app.zip;\n\n"
  },
  {
    "path": "tests/isignTestApp/exportOptions.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n        <key>teamID</key>\n        <string>L37S4Z6BE9</string>\n        <key>method</key>\n        <string>development</string>\n        <key>uploadSymbols</key>\n        <true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/isignTestApp/isignTestApp/AppDelegate.swift",
    "content": "//\n//  AppDelegate.swift\n//  isignTestApp\n//\n//  Copyright © 2015 Sauce Labs.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\");\n//  you may not use this file except in compliance with the License.\n//  You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n//  Unless required by applicable law or agreed to in writing, software\n//  distributed under the License is distributed on an \"AS IS\" BASIS,\n//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//  See the License for the specific language governing permissions and\n//  limitations under the License.\n//\n\nimport UIKit\n\n@UIApplicationMain\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n\n    var window: UIWindow?\n\n\n    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {\n        // Override point for customization after application launch.\n        return true\n    }\n\n    func applicationWillResignActive(application: UIApplication) {\n        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.\n        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.\n    }\n\n    func applicationDidEnterBackground(application: UIApplication) {\n        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.\n        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.\n    }\n\n    func applicationWillEnterForeground(application: UIApplication) {\n        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.\n    }\n\n    func applicationDidBecomeActive(application: UIApplication) {\n        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.\n    }\n\n    func applicationWillTerminate(application: UIApplication) {\n        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.\n    }\n\n\n}\n\n"
  },
  {
    "path": "tests/isignTestApp/isignTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "tests/isignTestApp/isignTestApp/Assets.xcassets/first.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"first.pdf\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "tests/isignTestApp/isignTestApp/Assets.xcassets/second.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"second.pdf\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "tests/isignTestApp/isignTestApp/Base.lproj/LaunchScreen.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"8150\" systemVersion=\"15A204g\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" useTraitCollections=\"YES\" initialViewController=\"01J-lp-oVM\">\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"8122\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"EHf-IW-A2E\">\n            <objects>\n                <viewController id=\"01J-lp-oVM\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"Llm-lL-Icb\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"xb3-aO-Qok\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Ze5-6b-2t3\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <animations/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"iYj-Kq-Ea1\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"53\" y=\"375\"/>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "tests/isignTestApp/isignTestApp/Base.lproj/Main.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"9531\" systemVersion=\"15C50\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" initialViewController=\"49e-Tb-3d3\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"9529\"/>\n    </dependencies>\n    <scenes>\n        <!--First-->\n        <scene sceneID=\"hNz-n2-bh7\">\n            <objects>\n                <viewController id=\"9pv-A4-QxB\" customClass=\"FirstViewController\" customModule=\"isignTestApp\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"Ia1-K6-d13\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"4ug-Mw-9AY\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"tsR-hK-woN\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"scaleToFill\" text=\"iSign Test App\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" minimumFontSize=\"10\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"KQZ-1w-vlD\">\n                                <rect key=\"frame\" x=\"186\" y=\"279\" width=\"228\" height=\"42\"/>\n                                <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                                <fontDescription key=\"fontDescription\" name=\"Helvetica\" family=\"Helvetica\" pointSize=\"36\"/>\n                                <color key=\"textColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"Loaded by FirstViewController\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"A5M-7J-77L\">\n                                <rect key=\"frame\" x=\"203\" y=\"329\" width=\"195\" height=\"17\"/>\n                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                <color key=\"textColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                        </subviews>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"centerX\" secondItem=\"KQZ-1w-vlD\" secondAttribute=\"centerX\" id=\"6BV-lF-sBN\"/>\n                            <constraint firstItem=\"A5M-7J-77L\" firstAttribute=\"top\" secondItem=\"KQZ-1w-vlD\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"cfb-er-3JN\"/>\n                            <constraint firstItem=\"A5M-7J-77L\" firstAttribute=\"centerX\" secondItem=\"KQZ-1w-vlD\" secondAttribute=\"centerX\" id=\"e1l-AV-tCB\"/>\n                            <constraint firstAttribute=\"centerY\" secondItem=\"KQZ-1w-vlD\" secondAttribute=\"centerY\" id=\"exm-UA-ej4\"/>\n                        </constraints>\n                    </view>\n                    <tabBarItem key=\"tabBarItem\" title=\"First\" image=\"first\" id=\"acW-dT-cKf\"/>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"W5J-7L-Pyd\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"750\" y=\"-320\"/>\n        </scene>\n        <!--Second-->\n        <scene sceneID=\"wg7-f3-ORb\">\n            <objects>\n                <viewController id=\"8rJ-Kc-sve\" customClass=\"SecondViewController\" customModule=\"isignTestApp\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"L7p-HK-0SC\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"Djb-ko-YwX\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"QS5-Rx-YEW\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"scaleToFill\" text=\"also iSign Test App\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" minimumFontSize=\"10\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"zEq-FU-wV5\">\n                                <rect key=\"frame\" x=\"148\" y=\"279\" width=\"304\" height=\"42\"/>\n                                <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                                <fontDescription key=\"fontDescription\" name=\"Helvetica\" family=\"Helvetica\" pointSize=\"36\"/>\n                                <color key=\"textColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" misplaced=\"YES\" text=\"Loaded by SecondViewController\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"NDk-cv-Gan\">\n                                <rect key=\"frame\" x=\"192\" y=\"329\" width=\"216\" height=\"17\"/>\n                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                <color key=\"textColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                        </subviews>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstItem=\"NDk-cv-Gan\" firstAttribute=\"top\" secondItem=\"zEq-FU-wV5\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"Day-4N-Vmt\"/>\n                            <constraint firstItem=\"NDk-cv-Gan\" firstAttribute=\"centerX\" secondItem=\"zEq-FU-wV5\" secondAttribute=\"centerX\" id=\"JgO-Fn-dHn\"/>\n                            <constraint firstAttribute=\"centerX\" secondItem=\"zEq-FU-wV5\" secondAttribute=\"centerX\" id=\"qqM-NS-xev\"/>\n                            <constraint firstAttribute=\"centerY\" secondItem=\"zEq-FU-wV5\" secondAttribute=\"centerY\" id=\"qzY-Ky-pLD\"/>\n                        </constraints>\n                    </view>\n                    <tabBarItem key=\"tabBarItem\" title=\"Second\" image=\"second\" id=\"cPa-gy-q4n\"/>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"4Nw-L8-lE0\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"750\" y=\"360\"/>\n        </scene>\n        <!--Tab Bar Controller-->\n        <scene sceneID=\"yl2-sM-qoP\">\n            <objects>\n                <tabBarController id=\"49e-Tb-3d3\" sceneMemberID=\"viewController\">\n                    <nil key=\"simulatedBottomBarMetrics\"/>\n                    <tabBar key=\"tabBar\" contentMode=\"scaleToFill\" id=\"W28-zg-YXA\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"975\" width=\"768\" height=\"49\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMinY=\"YES\"/>\n                        <color key=\"backgroundColor\" white=\"0.0\" alpha=\"0.0\" colorSpace=\"calibratedWhite\"/>\n                    </tabBar>\n                    <connections>\n                        <segue destination=\"9pv-A4-QxB\" kind=\"relationship\" relationship=\"viewControllers\" id=\"u7Y-xg-7CH\"/>\n                        <segue destination=\"8rJ-Kc-sve\" kind=\"relationship\" relationship=\"viewControllers\" id=\"lzU-1b-eKA\"/>\n                    </connections>\n                </tabBarController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"HuB-VB-40B\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"0.0\" y=\"0.0\"/>\n        </scene>\n    </scenes>\n    <resources>\n        <image name=\"first\" width=\"30\" height=\"30\"/>\n        <image name=\"second\" width=\"30\" height=\"30\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "tests/isignTestApp/isignTestApp/FirstViewController.swift",
    "content": "//\n//  FirstViewController.swift\n//  isignTestApp\n//\n//  Copyright © 2015 Sauce Labs.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\");\n//  you may not use this file except in compliance with the License.\n//  You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n//  Unless required by applicable law or agreed to in writing, software\n//  distributed under the License is distributed on an \"AS IS\" BASIS,\n//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//  See the License for the specific language governing permissions and\n//  limitations under the License.\n//\n\nimport UIKit\n\nclass FirstViewController: UIViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        // Do any additional setup after loading the view, typically from a nib.\n    }\n\n    override func didReceiveMemoryWarning() {\n        super.didReceiveMemoryWarning()\n        // Dispose of any resources that can be recreated.\n    }\n\n\n}\n\n"
  },
  {
    "path": "tests/isignTestApp/isignTestApp/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n\t<key>UIMainStoryboardFile</key>\n\t<string>Main</string>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UIStatusBarTintParameters</key>\n\t<dict>\n\t\t<key>UINavigationBar</key>\n\t\t<dict>\n\t\t\t<key>Style</key>\n\t\t\t<string>UIBarStyleDefault</string>\n\t\t\t<key>Translucent</key>\n\t\t\t<false/>\n\t\t</dict>\n\t</dict>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/isignTestApp/isignTestApp/SecondViewController.swift",
    "content": "//\n//  SecondViewController.swift\n//  isignTestApp\n//\n//  Copyright © 2015 Sauce Labs.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\");\n//  you may not use this file except in compliance with the License.\n//  You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n//  Unless required by applicable law or agreed to in writing, software\n//  distributed under the License is distributed on an \"AS IS\" BASIS,\n//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//  See the License for the specific language governing permissions and\n//  limitations under the License.\n//\n\nimport UIKit\n\nclass SecondViewController: UIViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        // Do any additional setup after loading the view, typically from a nib.\n    }\n\n    override func didReceiveMemoryWarning() {\n        super.didReceiveMemoryWarning()\n        // Dispose of any resources that can be recreated.\n    }\n\n\n}\n\n"
  },
  {
    "path": "tests/isignTestApp/isignTestApp.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t88F49D571C21E0220007422C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D561C21E0220007422C /* AppDelegate.swift */; };\n\t\t88F49D591C21E0220007422C /* FirstViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D581C21E0220007422C /* FirstViewController.swift */; };\n\t\t88F49D5B1C21E0220007422C /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D5A1C21E0220007422C /* SecondViewController.swift */; };\n\t\t88F49D5E1C21E0220007422C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88F49D5C1C21E0220007422C /* Main.storyboard */; };\n\t\t88F49D601C21E0220007422C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 88F49D5F1C21E0220007422C /* Assets.xcassets */; };\n\t\t88F49D631C21E0220007422C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88F49D611C21E0220007422C /* LaunchScreen.storyboard */; };\n\t\t88F49D6E1C21E0220007422C /* isignTestAppTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D6D1C21E0220007422C /* isignTestAppTests.swift */; };\n\t\t88F49D791C21E0220007422C /* isignTestAppUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D781C21E0220007422C /* isignTestAppUITests.swift */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t88F49D6A1C21E0220007422C /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 88F49D4B1C21E0220007422C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 88F49D521C21E0220007422C;\n\t\t\tremoteInfo = isignTestApp;\n\t\t};\n\t\t88F49D751C21E0220007422C /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 88F49D4B1C21E0220007422C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 88F49D521C21E0220007422C;\n\t\t\tremoteInfo = isignTestApp;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t88F49D531C21E0220007422C /* isignTestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = isignTestApp.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t88F49D561C21E0220007422C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\t88F49D581C21E0220007422C /* FirstViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstViewController.swift; sourceTree = \"<group>\"; };\n\t\t88F49D5A1C21E0220007422C /* SecondViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondViewController.swift; sourceTree = \"<group>\"; };\n\t\t88F49D5D1C21E0220007422C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\t88F49D5F1C21E0220007422C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t88F49D621C21E0220007422C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = \"<group>\"; };\n\t\t88F49D641C21E0220007422C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t88F49D691C21E0220007422C /* isignTestAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = isignTestAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t88F49D6D1C21E0220007422C /* isignTestAppTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = isignTestAppTests.swift; sourceTree = \"<group>\"; };\n\t\t88F49D6F1C21E0220007422C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t88F49D741C21E0220007422C /* isignTestAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = isignTestAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t88F49D781C21E0220007422C /* isignTestAppUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = isignTestAppUITests.swift; sourceTree = \"<group>\"; };\n\t\t88F49D7A1C21E0220007422C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t88F49D501C21E0220007422C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D661C21E0220007422C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D711C21E0220007422C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t88F49D4A1C21E0220007422C = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D551C21E0220007422C /* isignTestApp */,\n\t\t\t\t88F49D6C1C21E0220007422C /* isignTestAppTests */,\n\t\t\t\t88F49D771C21E0220007422C /* isignTestAppUITests */,\n\t\t\t\t88F49D541C21E0220007422C /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D541C21E0220007422C /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D531C21E0220007422C /* isignTestApp.app */,\n\t\t\t\t88F49D691C21E0220007422C /* isignTestAppTests.xctest */,\n\t\t\t\t88F49D741C21E0220007422C /* isignTestAppUITests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D551C21E0220007422C /* isignTestApp */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D561C21E0220007422C /* AppDelegate.swift */,\n\t\t\t\t88F49D581C21E0220007422C /* FirstViewController.swift */,\n\t\t\t\t88F49D5A1C21E0220007422C /* SecondViewController.swift */,\n\t\t\t\t88F49D5C1C21E0220007422C /* Main.storyboard */,\n\t\t\t\t88F49D5F1C21E0220007422C /* Assets.xcassets */,\n\t\t\t\t88F49D611C21E0220007422C /* LaunchScreen.storyboard */,\n\t\t\t\t88F49D641C21E0220007422C /* Info.plist */,\n\t\t\t);\n\t\t\tpath = isignTestApp;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D6C1C21E0220007422C /* isignTestAppTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D6D1C21E0220007422C /* isignTestAppTests.swift */,\n\t\t\t\t88F49D6F1C21E0220007422C /* Info.plist */,\n\t\t\t);\n\t\t\tpath = isignTestAppTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D771C21E0220007422C /* isignTestAppUITests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D781C21E0220007422C /* isignTestAppUITests.swift */,\n\t\t\t\t88F49D7A1C21E0220007422C /* Info.plist */,\n\t\t\t);\n\t\t\tpath = isignTestAppUITests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t88F49D521C21E0220007422C /* isignTestApp */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 88F49D7D1C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestApp\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t88F49D4F1C21E0220007422C /* Sources */,\n\t\t\t\t88F49D501C21E0220007422C /* Frameworks */,\n\t\t\t\t88F49D511C21E0220007422C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = isignTestApp;\n\t\t\tproductName = isignTestApp;\n\t\t\tproductReference = 88F49D531C21E0220007422C /* isignTestApp.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\t88F49D681C21E0220007422C /* isignTestAppTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 88F49D801C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t88F49D651C21E0220007422C /* Sources */,\n\t\t\t\t88F49D661C21E0220007422C /* Frameworks */,\n\t\t\t\t88F49D671C21E0220007422C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t88F49D6B1C21E0220007422C /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = isignTestAppTests;\n\t\t\tproductName = isignTestAppTests;\n\t\t\tproductReference = 88F49D691C21E0220007422C /* isignTestAppTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\t88F49D731C21E0220007422C /* isignTestAppUITests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 88F49D831C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppUITests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t88F49D701C21E0220007422C /* Sources */,\n\t\t\t\t88F49D711C21E0220007422C /* Frameworks */,\n\t\t\t\t88F49D721C21E0220007422C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t88F49D761C21E0220007422C /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = isignTestAppUITests;\n\t\t\tproductName = isignTestAppUITests;\n\t\t\tproductReference = 88F49D741C21E0220007422C /* isignTestAppUITests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.ui-testing\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t88F49D4B1C21E0220007422C /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastSwiftUpdateCheck = 0720;\n\t\t\t\tLastUpgradeCheck = 0720;\n\t\t\t\tORGANIZATIONNAME = \"Sauce Labs\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t88F49D521C21E0220007422C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t};\n\t\t\t\t\t88F49D681C21E0220007422C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t\tTestTargetID = 88F49D521C21E0220007422C;\n\t\t\t\t\t};\n\t\t\t\t\t88F49D731C21E0220007422C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t\tTestTargetID = 88F49D521C21E0220007422C;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 88F49D4E1C21E0220007422C /* Build configuration list for PBXProject \"isignTestApp\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 88F49D4A1C21E0220007422C;\n\t\t\tproductRefGroup = 88F49D541C21E0220007422C /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t88F49D521C21E0220007422C /* isignTestApp */,\n\t\t\t\t88F49D681C21E0220007422C /* isignTestAppTests */,\n\t\t\t\t88F49D731C21E0220007422C /* isignTestAppUITests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t88F49D511C21E0220007422C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D631C21E0220007422C /* LaunchScreen.storyboard in Resources */,\n\t\t\t\t88F49D601C21E0220007422C /* Assets.xcassets in Resources */,\n\t\t\t\t88F49D5E1C21E0220007422C /* Main.storyboard in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D671C21E0220007422C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D721C21E0220007422C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t88F49D4F1C21E0220007422C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D5B1C21E0220007422C /* SecondViewController.swift in Sources */,\n\t\t\t\t88F49D571C21E0220007422C /* AppDelegate.swift in Sources */,\n\t\t\t\t88F49D591C21E0220007422C /* FirstViewController.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D651C21E0220007422C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D6E1C21E0220007422C /* isignTestAppTests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D701C21E0220007422C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D791C21E0220007422C /* isignTestAppUITests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t88F49D6B1C21E0220007422C /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 88F49D521C21E0220007422C /* isignTestApp */;\n\t\t\ttargetProxy = 88F49D6A1C21E0220007422C /* PBXContainerItemProxy */;\n\t\t};\n\t\t88F49D761C21E0220007422C /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 88F49D521C21E0220007422C /* isignTestApp */;\n\t\t\ttargetProxy = 88F49D751C21E0220007422C /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\t88F49D5C1C21E0220007422C /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D5D1C21E0220007422C /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D611C21E0220007422C /* LaunchScreen.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D621C21E0220007422C /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t88F49D7B1C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D7C1C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t88F49D7E1C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tINFOPLIST_FILE = isignTestApp/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestApp;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D7F1C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tINFOPLIST_FILE = isignTestApp/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestApp;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t88F49D811C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tINFOPLIST_FILE = isignTestAppTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/isignTestApp.app/isignTestApp\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D821C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tINFOPLIST_FILE = isignTestAppTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/isignTestApp.app/isignTestApp\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t88F49D841C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = isignTestAppUITests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppUITests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_TARGET_NAME = isignTestApp;\n\t\t\t\tUSES_XCTRUNNER = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D851C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = isignTestAppUITests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppUITests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_TARGET_NAME = isignTestApp;\n\t\t\t\tUSES_XCTRUNNER = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t88F49D4E1C21E0220007422C /* Build configuration list for PBXProject \"isignTestApp\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D7B1C21E0220007422C /* Debug */,\n\t\t\t\t88F49D7C1C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t88F49D7D1C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestApp\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D7E1C21E0220007422C /* Debug */,\n\t\t\t\t88F49D7F1C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t};\n\t\t88F49D801C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D811C21E0220007422C /* Debug */,\n\t\t\t\t88F49D821C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t};\n\t\t88F49D831C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppUITests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D841C21E0220007422C /* Debug */,\n\t\t\t\t88F49D851C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 88F49D4B1C21E0220007422C /* Project object */;\n}\n"
  },
  {
    "path": "tests/isignTestApp/isignTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:isignTestApp.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "tests/isignTestApp/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/isignTestApp.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0720\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n               BuildableName = \"isignTestApp.app\"\n               BlueprintName = \"isignTestApp\"\n               ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"88F49D681C21E0220007422C\"\n               BuildableName = \"isignTestAppTests.xctest\"\n               BlueprintName = \"isignTestAppTests\"\n               ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"88F49D731C21E0220007422C\"\n               BuildableName = \"isignTestAppUITests.xctest\"\n               BlueprintName = \"isignTestAppUITests\"\n               ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n            BuildableName = \"isignTestApp.app\"\n            BlueprintName = \"isignTestApp\"\n            ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n            BuildableName = \"isignTestApp.app\"\n            BlueprintName = \"isignTestApp\"\n            ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n            BuildableName = \"isignTestApp.app\"\n            BlueprintName = \"isignTestApp\"\n            ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "tests/isignTestApp/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/xcschememanagement.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>SchemeUserState</key>\n\t<dict>\n\t\t<key>isignTestApp.xcscheme</key>\n\t\t<dict>\n\t\t\t<key>orderHint</key>\n\t\t\t<integer>0</integer>\n\t\t</dict>\n\t</dict>\n\t<key>SuppressBuildableAutocreation</key>\n\t<dict>\n\t\t<key>88F49D521C21E0220007422C</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>88F49D681C21E0220007422C</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>88F49D731C21E0220007422C</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/isignTestApp/isignTestAppTests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/isignTestApp/isignTestAppTests/isignTestAppTests.swift",
    "content": "//\n//  isignTestAppTests.swift\n//  isignTestAppTests\n//\n//  Copyright © 2015 Sauce Labs.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\");\n//  you may not use this file except in compliance with the License.\n//  You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n//  Unless required by applicable law or agreed to in writing, software\n//  distributed under the License is distributed on an \"AS IS\" BASIS,\n//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//  See the License for the specific language governing permissions and\n//  limitations under the License.\n//\n\nimport XCTest\n@testable import isignTestApp\n\nclass isignTestAppTests: XCTestCase {\n    \n    override func setUp() {\n        super.setUp()\n        // Put setup code here. This method is called before the invocation of each test method in the class.\n    }\n    \n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n    \n    func testExample() {\n        // This is an example of a functional test case.\n        // Use XCTAssert and related functions to verify your tests produce the correct results.\n    }\n    \n    func testPerformanceExample() {\n        // This is an example of a performance test case.\n        self.measureBlock {\n            // Put the code you want to measure the time of here.\n        }\n    }\n    \n}\n"
  },
  {
    "path": "tests/isignTestApp/isignTestAppUITests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/isignTestApp/isignTestAppUITests/isignTestAppUITests.swift",
    "content": "//\n//  isignTestAppUITests.swift\n//  isignTestAppUITests\n//\n//  Copyright © 2015 Sauce Labs.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\");\n//  you may not use this file except in compliance with the License.\n//  You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n//  Unless required by applicable law or agreed to in writing, software\n//  distributed under the License is distributed on an \"AS IS\" BASIS,\n//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//  See the License for the specific language governing permissions and\n//  limitations under the License.\n//\n\nimport XCTest\n\nclass isignTestAppUITests: XCTestCase {\n        \n    override func setUp() {\n        super.setUp()\n        \n        // Put setup code here. This method is called before the invocation of each test method in the class.\n        \n        // In UI tests it is usually best to stop immediately when a failure occurs.\n        continueAfterFailure = false\n        // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.\n        XCUIApplication().launch()\n\n        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.\n    }\n    \n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n    \n    func testExample() {\n        // Use recording to get started writing UI tests.\n        // Use XCTAssert and related functions to verify your tests produce the correct results.\n    }\n    \n}\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/.gitignore",
    "content": "build\nPods\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/Podfile",
    "content": "source 'https://github.com/CocoaPods/Specs.git'\nplatform :ios, '8.0'\nuse_frameworks!\n\ntarget 'isignTestApp' do\n  pod 'FontAwesome.swift', '~> 0.7'\nend\n\ntarget 'isignTestAppTests' do\n\nend\n\ntarget 'isignTestAppUITests' do\n\nend\n\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/README.md",
    "content": "# isignTestApp\n\nProject to create a very simple test app for isign's test suite.\n\nThis is exactly like the isignTestApp, except that if it's working, it should \nalso display a lightning bolt on the main screen. \n\nThis app includes Github user @thii's \n[FontAwesome_swift Framework](https://github.com/thii/FontAwesome_swift), \nwhich crucially for our test, includes both a small resource (a font file) and \na small amount of code. \n\n# Prerequisites\n\nThis project uses frameworks from the [CocoaPods](http://cocoapods.org) system.\nTo obtain the frameworks, install Cocoapods, then run `pod install` in this directory.\n\n# Building\n\nRun `./build.sh` to create the necessary test .ipa in the\nisign test directory (which is the containing directory).\n\n## Caveats\n\nCurrently, the TeamID specified is Neil Kandalgaonkar (neilk@neilk.net)'s' personal\norganization ID. For this to work, you would also need a provisioning profile installed \nin the right places on your system (the obvious thing is to use XCode). \n\nSo... you pretty much need to be Neil to build this, unless you modify the `build.sh` \nscript and the `exportOptions.plist` in this directory.\n\nFor obvious reasons this is a problem going forward. Perhaps we'll need to create some sort\nof Apple account which the community can use to sign the test apps. But on the assumption\nthat we will only need to recreate the test apps very rarely, we're open sourcing it as it is,\nfor now.\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/build.sh",
    "content": "#!/bin/bash\n\n# ./build.sh /path/to/isign\n\n# builds various archival formats of the isign test app\n# and puts them in the test directory of isign. You have to specify\n# isign's source directory on the command line\n#\n# Also you have to have the provisioning profile mentioned configured\n# in the app. \n#\n\nisign_test_dir=..\n\nprojectName=isignTestApp\n\n# workspace\nworkspace=$projectName.xcworkspace\n\n# this projectName just has one scheme configured, same name as projectName\nscheme=$projectName\n\n# This file must exist in this directory.\nexport_options_plist=exportOptions.plist\n\nwarn() {\n    echo \"$@\" 1>&2;\n}\n\ncopy_ipa() {\n    local platform=$1\n    local target=$2\n\n    archive_path=build/$projectName.xcarchive\n    ipa_dir=build\n    ipa_path=$ipa_dir/$projectName.ipa\n    rm -f $ipa_path;\n    \n    xcodebuild clean -workspace $workspace \\\n                     -scheme $scheme \\\n                     -configuration Release \\\n                     -sdk $platform;\n    xcodebuild archive -workspace $workspace \\\n                       -scheme $scheme \\\n                       -archivePath $archive_path;\n    xcodebuild -exportArchive \\\n               -archivePath $archive_path \\\n               -exportPath $ipa_dir \\\n               -exportOptionsPlist $export_options_plist;\n\n    cp $ipa_path $target;\n}\n\n\n\nif [[ -n $rvm_path ]]; then\n    warn \"========\";\n    warn \"\"\n    warn \"ACHTUNG!! \"\n    warn \"rvm users! switch to the system version of ruby with: \";\n    warn \"    $ rvm use system\";\n    warn \"otherwise your path to some ruby development tools like ipatool may be wrong\";\n    warn \"\"\n    warn \"========\";\nfi\n\ncopy_ipa     iphoneos9.2 $isign_test_dir/TestWithFrameworks.ipa;\n\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/exportOptions.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n        <key>teamID</key>\n        <string>L37S4Z6BE9</string>\n        <key>method</key>\n        <string>development</string>\n        <key>compileBitcode</key>\n        <false/>\n        <key>uploadSymbols</key>\n        <true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestApp/AppDelegate.swift",
    "content": "//\n//  AppDelegate.swift\n//  isignTestApp\n//\n//  Copyright © 2015 Sauce Labs.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\");\n//  you may not use this file except in compliance with the License.\n//  You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n//  Unless required by applicable law or agreed to in writing, software\n//  distributed under the License is distributed on an \"AS IS\" BASIS,\n//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//  See the License for the specific language governing permissions and\n//  limitations under the License.\n//\n\nimport UIKit\n\n@UIApplicationMain\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n\n    var window: UIWindow?\n\n\n    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {\n        // Override point for customization after application launch.\n        return true\n    }\n\n    func applicationWillResignActive(application: UIApplication) {\n        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.\n        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.\n    }\n\n    func applicationDidEnterBackground(application: UIApplication) {\n        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.\n        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.\n    }\n\n    func applicationWillEnterForeground(application: UIApplication) {\n        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.\n    }\n\n    func applicationDidBecomeActive(application: UIApplication) {\n        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.\n    }\n\n    func applicationWillTerminate(application: UIApplication) {\n        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.\n    }\n\n\n}\n\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestApp/Assets.xcassets/first.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"first.pdf\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestApp/Assets.xcassets/second.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"second.pdf\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestApp/Base.lproj/LaunchScreen.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"8150\" systemVersion=\"15A204g\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" useTraitCollections=\"YES\" initialViewController=\"01J-lp-oVM\">\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"8122\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"EHf-IW-A2E\">\n            <objects>\n                <viewController id=\"01J-lp-oVM\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"Llm-lL-Icb\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"xb3-aO-Qok\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Ze5-6b-2t3\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <animations/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"iYj-Kq-Ea1\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"53\" y=\"375\"/>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestApp/Base.lproj/Main.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"9531\" systemVersion=\"15C50\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" initialViewController=\"49e-Tb-3d3\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"9529\"/>\n        <capability name=\"Aspect ratio constraints\" minToolsVersion=\"5.1\"/>\n    </dependencies>\n    <scenes>\n        <!--First-->\n        <scene sceneID=\"hNz-n2-bh7\">\n            <objects>\n                <viewController id=\"9pv-A4-QxB\" customClass=\"FirstViewController\" customModule=\"isignTestApp\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"Ia1-K6-d13\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"4ug-Mw-9AY\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"tsR-hK-woN\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"scaleToFill\" text=\"iSign Test App\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" minimumFontSize=\"10\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"KQZ-1w-vlD\">\n                                <rect key=\"frame\" x=\"186\" y=\"279\" width=\"228\" height=\"42\"/>\n                                <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                                <fontDescription key=\"fontDescription\" name=\"Helvetica\" family=\"Helvetica\" pointSize=\"36\"/>\n                                <color key=\"textColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"Loaded by FirstViewController\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"A5M-7J-77L\">\n                                <rect key=\"frame\" x=\"203\" y=\"329\" width=\"195\" height=\"17\"/>\n                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                <color key=\"textColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                            <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" ambiguous=\"YES\" misplaced=\"YES\" text=\"Lightning bolt\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"mIi-mA-acD\">\n                                <rect key=\"frame\" x=\"247\" y=\"161\" width=\"106\" height=\"110\"/>\n                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                                <color key=\"textColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                        </subviews>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"centerX\" secondItem=\"KQZ-1w-vlD\" secondAttribute=\"centerX\" id=\"6BV-lF-sBN\"/>\n                            <constraint firstItem=\"mIi-mA-acD\" firstAttribute=\"width\" secondItem=\"tsR-hK-woN\" secondAttribute=\"height\" multiplier=\"53:300\" id=\"JtZ-t6-HqB\"/>\n                            <constraint firstItem=\"A5M-7J-77L\" firstAttribute=\"top\" secondItem=\"KQZ-1w-vlD\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"cfb-er-3JN\"/>\n                            <constraint firstItem=\"A5M-7J-77L\" firstAttribute=\"centerX\" secondItem=\"KQZ-1w-vlD\" secondAttribute=\"centerX\" id=\"e1l-AV-tCB\"/>\n                            <constraint firstAttribute=\"centerY\" secondItem=\"KQZ-1w-vlD\" secondAttribute=\"centerY\" id=\"exm-UA-ej4\"/>\n                            <constraint firstItem=\"mIi-mA-acD\" firstAttribute=\"centerX\" secondItem=\"tsR-hK-woN\" secondAttribute=\"centerX\" id=\"zm0-dg-jmK\"/>\n                        </constraints>\n                    </view>\n                    <tabBarItem key=\"tabBarItem\" title=\"First\" image=\"first\" id=\"acW-dT-cKf\"/>\n                    <connections>\n                        <outlet property=\"boltLabel\" destination=\"mIi-mA-acD\" id=\"W1k-wT-zg4\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"W5J-7L-Pyd\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"750\" y=\"-320\"/>\n        </scene>\n        <!--Second-->\n        <scene sceneID=\"wg7-f3-ORb\">\n            <objects>\n                <viewController id=\"8rJ-Kc-sve\" customClass=\"SecondViewController\" customModule=\"isignTestApp\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"L7p-HK-0SC\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"Djb-ko-YwX\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"QS5-Rx-YEW\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"scaleToFill\" text=\"also iSign Test App\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" minimumFontSize=\"10\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"zEq-FU-wV5\">\n                                <rect key=\"frame\" x=\"148\" y=\"279\" width=\"304\" height=\"42\"/>\n                                <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                                <fontDescription key=\"fontDescription\" name=\"Helvetica\" family=\"Helvetica\" pointSize=\"36\"/>\n                                <color key=\"textColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                            <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" misplaced=\"YES\" text=\"Loaded by SecondViewController\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"NDk-cv-Gan\">\n                                <rect key=\"frame\" x=\"192\" y=\"329\" width=\"216\" height=\"17\"/>\n                                <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                                <color key=\"textColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                                <nil key=\"highlightedColor\"/>\n                            </label>\n                        </subviews>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstItem=\"NDk-cv-Gan\" firstAttribute=\"top\" secondItem=\"zEq-FU-wV5\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"Day-4N-Vmt\"/>\n                            <constraint firstItem=\"NDk-cv-Gan\" firstAttribute=\"centerX\" secondItem=\"zEq-FU-wV5\" secondAttribute=\"centerX\" id=\"JgO-Fn-dHn\"/>\n                            <constraint firstAttribute=\"centerX\" secondItem=\"zEq-FU-wV5\" secondAttribute=\"centerX\" id=\"qqM-NS-xev\"/>\n                            <constraint firstAttribute=\"centerY\" secondItem=\"zEq-FU-wV5\" secondAttribute=\"centerY\" id=\"qzY-Ky-pLD\"/>\n                        </constraints>\n                    </view>\n                    <tabBarItem key=\"tabBarItem\" title=\"Second\" image=\"second\" id=\"cPa-gy-q4n\"/>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"4Nw-L8-lE0\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"750\" y=\"360\"/>\n        </scene>\n        <!--Tab Bar Controller-->\n        <scene sceneID=\"yl2-sM-qoP\">\n            <objects>\n                <tabBarController id=\"49e-Tb-3d3\" sceneMemberID=\"viewController\">\n                    <nil key=\"simulatedBottomBarMetrics\"/>\n                    <tabBar key=\"tabBar\" contentMode=\"scaleToFill\" id=\"W28-zg-YXA\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"975\" width=\"768\" height=\"49\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMinY=\"YES\"/>\n                        <color key=\"backgroundColor\" white=\"0.0\" alpha=\"0.0\" colorSpace=\"calibratedWhite\"/>\n                    </tabBar>\n                    <connections>\n                        <segue destination=\"9pv-A4-QxB\" kind=\"relationship\" relationship=\"viewControllers\" id=\"u7Y-xg-7CH\"/>\n                        <segue destination=\"8rJ-Kc-sve\" kind=\"relationship\" relationship=\"viewControllers\" id=\"lzU-1b-eKA\"/>\n                    </connections>\n                </tabBarController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"HuB-VB-40B\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"0.0\" y=\"0.0\"/>\n        </scene>\n    </scenes>\n    <resources>\n        <image name=\"first\" width=\"30\" height=\"30\"/>\n        <image name=\"second\" width=\"30\" height=\"30\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestApp/FirstViewController.swift",
    "content": "//\n//  FirstViewController.swift\n//  isignTestApp\n//\n//  Copyright © 2015 Sauce Labs.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\");\n//  you may not use this file except in compliance with the License.\n//  You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n//  Unless required by applicable law or agreed to in writing, software\n//  distributed under the License is distributed on an \"AS IS\" BASIS,\n//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//  See the License for the specific language governing permissions and\n//  limitations under the License.\n//\n\nimport UIKit\nimport FontAwesome_swift\n\nclass FirstViewController: UIViewController {\n\n    @IBOutlet weak var boltLabel: UILabel!\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        boltLabel.font = UIFont.fontAwesomeOfSize(100);\n        boltLabel.text = String.fontAwesomeIconWithName(FontAwesome.Bolt);\n        boltLabel.textAlignment = NSTextAlignment.Center;\n    }\n\n    override func didReceiveMemoryWarning() {\n        super.didReceiveMemoryWarning()\n        // Dispose of any resources that can be recreated.\n    }\n\n\n}\n\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestApp/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n\t<key>UIMainStoryboardFile</key>\n\t<string>Main</string>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UIStatusBarTintParameters</key>\n\t<dict>\n\t\t<key>UINavigationBar</key>\n\t\t<dict>\n\t\t\t<key>Style</key>\n\t\t\t<string>UIBarStyleDefault</string>\n\t\t\t<key>Translucent</key>\n\t\t\t<false/>\n\t\t</dict>\n\t</dict>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestApp/SecondViewController.swift",
    "content": "//\n//  SecondViewController.swift\n//  isignTestApp\n//\n//  Copyright © 2015 Sauce Labs.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\");\n//  you may not use this file except in compliance with the License.\n//  You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n//  Unless required by applicable law or agreed to in writing, software\n//  distributed under the License is distributed on an \"AS IS\" BASIS,\n//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//  See the License for the specific language governing permissions and\n//  limitations under the License.\n//\n\nimport UIKit\n\nclass SecondViewController: UIViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        // Do any additional setup after loading the view, typically from a nib.\n    }\n\n    override func didReceiveMemoryWarning() {\n        super.didReceiveMemoryWarning()\n        // Dispose of any resources that can be recreated.\n    }\n\n\n}\n\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestApp.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t83E2137C82FE1346AD0FE999 /* Pods_isignTestApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 482C83E341072C026C4E2D04 /* Pods_isignTestApp.framework */; };\n\t\t88F49D571C21E0220007422C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D561C21E0220007422C /* AppDelegate.swift */; };\n\t\t88F49D591C21E0220007422C /* FirstViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D581C21E0220007422C /* FirstViewController.swift */; };\n\t\t88F49D5B1C21E0220007422C /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D5A1C21E0220007422C /* SecondViewController.swift */; };\n\t\t88F49D5E1C21E0220007422C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88F49D5C1C21E0220007422C /* Main.storyboard */; };\n\t\t88F49D601C21E0220007422C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 88F49D5F1C21E0220007422C /* Assets.xcassets */; };\n\t\t88F49D631C21E0220007422C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 88F49D611C21E0220007422C /* LaunchScreen.storyboard */; };\n\t\t88F49D6E1C21E0220007422C /* isignTestAppTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D6D1C21E0220007422C /* isignTestAppTests.swift */; };\n\t\t88F49D791C21E0220007422C /* isignTestAppUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F49D781C21E0220007422C /* isignTestAppUITests.swift */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t88F49D6A1C21E0220007422C /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 88F49D4B1C21E0220007422C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 88F49D521C21E0220007422C;\n\t\t\tremoteInfo = isignTestApp;\n\t\t};\n\t\t88F49D751C21E0220007422C /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 88F49D4B1C21E0220007422C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 88F49D521C21E0220007422C;\n\t\t\tremoteInfo = isignTestApp;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t1A03A6031C2E68A83409A36A /* Pods-isignTestApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-isignTestApp.release.xcconfig\"; path = \"Pods/Target Support Files/Pods-isignTestApp/Pods-isignTestApp.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t482C83E341072C026C4E2D04 /* Pods_isignTestApp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_isignTestApp.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t568EA0A65D28521957385887 /* Pods-isignTestApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-isignTestApp.debug.xcconfig\"; path = \"Pods/Target Support Files/Pods-isignTestApp/Pods-isignTestApp.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t88F49D531C21E0220007422C /* isignTestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = isignTestApp.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t88F49D561C21E0220007422C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\t88F49D581C21E0220007422C /* FirstViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstViewController.swift; sourceTree = \"<group>\"; };\n\t\t88F49D5A1C21E0220007422C /* SecondViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondViewController.swift; sourceTree = \"<group>\"; };\n\t\t88F49D5D1C21E0220007422C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\t88F49D5F1C21E0220007422C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t88F49D621C21E0220007422C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = \"<group>\"; };\n\t\t88F49D641C21E0220007422C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t88F49D691C21E0220007422C /* isignTestAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = isignTestAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t88F49D6D1C21E0220007422C /* isignTestAppTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = isignTestAppTests.swift; sourceTree = \"<group>\"; };\n\t\t88F49D6F1C21E0220007422C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t88F49D741C21E0220007422C /* isignTestAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = isignTestAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t88F49D781C21E0220007422C /* isignTestAppUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = isignTestAppUITests.swift; sourceTree = \"<group>\"; };\n\t\t88F49D7A1C21E0220007422C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t88F49D501C21E0220007422C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t83E2137C82FE1346AD0FE999 /* Pods_isignTestApp.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D661C21E0220007422C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D711C21E0220007422C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t8767BD99DB0DE852EFDCE52D /* Pods */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t568EA0A65D28521957385887 /* Pods-isignTestApp.debug.xcconfig */,\n\t\t\t\t1A03A6031C2E68A83409A36A /* Pods-isignTestApp.release.xcconfig */,\n\t\t\t);\n\t\t\tname = Pods;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D4A1C21E0220007422C = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D551C21E0220007422C /* isignTestApp */,\n\t\t\t\t88F49D6C1C21E0220007422C /* isignTestAppTests */,\n\t\t\t\t88F49D771C21E0220007422C /* isignTestAppUITests */,\n\t\t\t\t88F49D541C21E0220007422C /* Products */,\n\t\t\t\t8767BD99DB0DE852EFDCE52D /* Pods */,\n\t\t\t\tD851D399435A30E964E93BD3 /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D541C21E0220007422C /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D531C21E0220007422C /* isignTestApp.app */,\n\t\t\t\t88F49D691C21E0220007422C /* isignTestAppTests.xctest */,\n\t\t\t\t88F49D741C21E0220007422C /* isignTestAppUITests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D551C21E0220007422C /* isignTestApp */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D561C21E0220007422C /* AppDelegate.swift */,\n\t\t\t\t88F49D581C21E0220007422C /* FirstViewController.swift */,\n\t\t\t\t88F49D5A1C21E0220007422C /* SecondViewController.swift */,\n\t\t\t\t88F49D5C1C21E0220007422C /* Main.storyboard */,\n\t\t\t\t88F49D5F1C21E0220007422C /* Assets.xcassets */,\n\t\t\t\t88F49D611C21E0220007422C /* LaunchScreen.storyboard */,\n\t\t\t\t88F49D641C21E0220007422C /* Info.plist */,\n\t\t\t);\n\t\t\tpath = isignTestApp;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D6C1C21E0220007422C /* isignTestAppTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D6D1C21E0220007422C /* isignTestAppTests.swift */,\n\t\t\t\t88F49D6F1C21E0220007422C /* Info.plist */,\n\t\t\t);\n\t\t\tpath = isignTestAppTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D771C21E0220007422C /* isignTestAppUITests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D781C21E0220007422C /* isignTestAppUITests.swift */,\n\t\t\t\t88F49D7A1C21E0220007422C /* Info.plist */,\n\t\t\t);\n\t\t\tpath = isignTestAppUITests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tD851D399435A30E964E93BD3 /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t482C83E341072C026C4E2D04 /* Pods_isignTestApp.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t88F49D521C21E0220007422C /* isignTestApp */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 88F49D7D1C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestApp\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t02F23A3A072023BC469E4D28 /* Check Pods Manifest.lock */,\n\t\t\t\t88F49D4F1C21E0220007422C /* Sources */,\n\t\t\t\t88F49D501C21E0220007422C /* Frameworks */,\n\t\t\t\t88F49D511C21E0220007422C /* Resources */,\n\t\t\t\t83318A2D9A5203CEFF1F1C66 /* Embed Pods Frameworks */,\n\t\t\t\t239CFA05A032CAB39434E007 /* Copy Pods Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = isignTestApp;\n\t\t\tproductName = isignTestApp;\n\t\t\tproductReference = 88F49D531C21E0220007422C /* isignTestApp.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\t88F49D681C21E0220007422C /* isignTestAppTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 88F49D801C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t88F49D651C21E0220007422C /* Sources */,\n\t\t\t\t88F49D661C21E0220007422C /* Frameworks */,\n\t\t\t\t88F49D671C21E0220007422C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t88F49D6B1C21E0220007422C /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = isignTestAppTests;\n\t\t\tproductName = isignTestAppTests;\n\t\t\tproductReference = 88F49D691C21E0220007422C /* isignTestAppTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\t88F49D731C21E0220007422C /* isignTestAppUITests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 88F49D831C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppUITests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t88F49D701C21E0220007422C /* Sources */,\n\t\t\t\t88F49D711C21E0220007422C /* Frameworks */,\n\t\t\t\t88F49D721C21E0220007422C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t88F49D761C21E0220007422C /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = isignTestAppUITests;\n\t\t\tproductName = isignTestAppUITests;\n\t\t\tproductReference = 88F49D741C21E0220007422C /* isignTestAppUITests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.ui-testing\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t88F49D4B1C21E0220007422C /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastSwiftUpdateCheck = 0720;\n\t\t\t\tLastUpgradeCheck = 0720;\n\t\t\t\tORGANIZATIONNAME = \"Sauce Labs\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t88F49D521C21E0220007422C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t};\n\t\t\t\t\t88F49D681C21E0220007422C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t\tTestTargetID = 88F49D521C21E0220007422C;\n\t\t\t\t\t};\n\t\t\t\t\t88F49D731C21E0220007422C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t\tTestTargetID = 88F49D521C21E0220007422C;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 88F49D4E1C21E0220007422C /* Build configuration list for PBXProject \"isignTestApp\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 88F49D4A1C21E0220007422C;\n\t\t\tproductRefGroup = 88F49D541C21E0220007422C /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t88F49D521C21E0220007422C /* isignTestApp */,\n\t\t\t\t88F49D681C21E0220007422C /* isignTestAppTests */,\n\t\t\t\t88F49D731C21E0220007422C /* isignTestAppUITests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t88F49D511C21E0220007422C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D631C21E0220007422C /* LaunchScreen.storyboard in Resources */,\n\t\t\t\t88F49D601C21E0220007422C /* Assets.xcassets in Resources */,\n\t\t\t\t88F49D5E1C21E0220007422C /* Main.storyboard in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D671C21E0220007422C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D721C21E0220007422C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t02F23A3A072023BC469E4D28 /* Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Check Pods Manifest.lock\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_ROOT}/../Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [[ $? != 0 ]] ; then\\n    cat << EOM\\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\nEOM\\n    exit 1\\nfi\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t239CFA05A032CAB39434E007 /* Copy Pods Resources */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Copy Pods Resources\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${SRCROOT}/Pods/Target Support Files/Pods-isignTestApp/Pods-isignTestApp-resources.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t83318A2D9A5203CEFF1F1C66 /* Embed Pods Frameworks */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Embed Pods Frameworks\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${SRCROOT}/Pods/Target Support Files/Pods-isignTestApp/Pods-isignTestApp-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t88F49D4F1C21E0220007422C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D5B1C21E0220007422C /* SecondViewController.swift in Sources */,\n\t\t\t\t88F49D571C21E0220007422C /* AppDelegate.swift in Sources */,\n\t\t\t\t88F49D591C21E0220007422C /* FirstViewController.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D651C21E0220007422C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D6E1C21E0220007422C /* isignTestAppTests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t88F49D701C21E0220007422C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t88F49D791C21E0220007422C /* isignTestAppUITests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t88F49D6B1C21E0220007422C /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 88F49D521C21E0220007422C /* isignTestApp */;\n\t\t\ttargetProxy = 88F49D6A1C21E0220007422C /* PBXContainerItemProxy */;\n\t\t};\n\t\t88F49D761C21E0220007422C /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 88F49D521C21E0220007422C /* isignTestApp */;\n\t\t\ttargetProxy = 88F49D751C21E0220007422C /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\t88F49D5C1C21E0220007422C /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D5D1C21E0220007422C /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t88F49D611C21E0220007422C /* LaunchScreen.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t88F49D621C21E0220007422C /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t88F49D7B1C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D7C1C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t88F49D7E1C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 568EA0A65D28521957385887 /* Pods-isignTestApp.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tINFOPLIST_FILE = isignTestApp/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestApp;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D7F1C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 1A03A6031C2E68A83409A36A /* Pods-isignTestApp.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tINFOPLIST_FILE = isignTestApp/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestApp;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t88F49D811C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tINFOPLIST_FILE = isignTestAppTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/isignTestApp.app/isignTestApp\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D821C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tINFOPLIST_FILE = isignTestAppTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/isignTestApp.app/isignTestApp\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t88F49D841C21E0220007422C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = isignTestAppUITests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppUITests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_TARGET_NAME = isignTestApp;\n\t\t\t\tUSES_XCTRUNNER = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t88F49D851C21E0220007422C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = isignTestAppUITests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.saucelabs.isignTestAppUITests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_TARGET_NAME = isignTestApp;\n\t\t\t\tUSES_XCTRUNNER = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t88F49D4E1C21E0220007422C /* Build configuration list for PBXProject \"isignTestApp\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D7B1C21E0220007422C /* Debug */,\n\t\t\t\t88F49D7C1C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t88F49D7D1C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestApp\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D7E1C21E0220007422C /* Debug */,\n\t\t\t\t88F49D7F1C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t88F49D801C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D811C21E0220007422C /* Debug */,\n\t\t\t\t88F49D821C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t88F49D831C21E0220007422C /* Build configuration list for PBXNativeTarget \"isignTestAppUITests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t88F49D841C21E0220007422C /* Debug */,\n\t\t\t\t88F49D851C21E0220007422C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 88F49D4B1C21E0220007422C /* Project object */;\n}\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:isignTestApp.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/isignTestApp.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0720\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n               BuildableName = \"isignTestApp.app\"\n               BlueprintName = \"isignTestApp\"\n               ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"88F49D681C21E0220007422C\"\n               BuildableName = \"isignTestAppTests.xctest\"\n               BlueprintName = \"isignTestAppTests\"\n               ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"88F49D731C21E0220007422C\"\n               BuildableName = \"isignTestAppUITests.xctest\"\n               BlueprintName = \"isignTestAppUITests\"\n               ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n            BuildableName = \"isignTestApp.app\"\n            BlueprintName = \"isignTestApp\"\n            ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n            BuildableName = \"isignTestApp.app\"\n            BlueprintName = \"isignTestApp\"\n            ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"88F49D521C21E0220007422C\"\n            BuildableName = \"isignTestApp.app\"\n            BlueprintName = \"isignTestApp\"\n            ReferencedContainer = \"container:isignTestApp.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestApp.xcodeproj/xcuserdata/neilk.xcuserdatad/xcschemes/xcschememanagement.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>SchemeUserState</key>\n\t<dict>\n\t\t<key>isignTestApp.xcscheme</key>\n\t\t<dict>\n\t\t\t<key>orderHint</key>\n\t\t\t<integer>0</integer>\n\t\t</dict>\n\t</dict>\n\t<key>SuppressBuildableAutocreation</key>\n\t<dict>\n\t\t<key>88F49D521C21E0220007422C</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>88F49D681C21E0220007422C</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t\t<key>88F49D731C21E0220007422C</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestApp.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:isignTestApp.xcodeproj\">\n   </FileRef>\n   <FileRef\n      location = \"group:Pods/Pods.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestAppTests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestAppTests/isignTestAppTests.swift",
    "content": "//\n//  isignTestAppTests.swift\n//  isignTestAppTests\n//\n//  Copyright © 2015 Sauce Labs.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\");\n//  you may not use this file except in compliance with the License.\n//  You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n//  Unless required by applicable law or agreed to in writing, software\n//  distributed under the License is distributed on an \"AS IS\" BASIS,\n//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//  See the License for the specific language governing permissions and\n//  limitations under the License.\n//\n\nimport XCTest\n@testable import isignTestApp\n\nclass isignTestAppTests: XCTestCase {\n    \n    override func setUp() {\n        super.setUp()\n        // Put setup code here. This method is called before the invocation of each test method in the class.\n    }\n    \n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n    \n    func testExample() {\n        // This is an example of a functional test case.\n        // Use XCTAssert and related functions to verify your tests produce the correct results.\n    }\n    \n    func testPerformanceExample() {\n        // This is an example of a performance test case.\n        self.measureBlock {\n            // Put the code you want to measure the time of here.\n        }\n    }\n    \n}\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestAppUITests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/isignTestAppWithFrameworks/isignTestAppUITests/isignTestAppUITests.swift",
    "content": "//\n//  isignTestAppUITests.swift\n//  isignTestAppUITests\n//\n//  Copyright © 2015 Sauce Labs.\n//\n//  Licensed under the Apache License, Version 2.0 (the \"License\");\n//  you may not use this file except in compliance with the License.\n//  You may obtain a copy of the License at\n//\n//  http://www.apache.org/licenses/LICENSE-2.0\n//\n//  Unless required by applicable law or agreed to in writing, software\n//  distributed under the License is distributed on an \"AS IS\" BASIS,\n//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n//  See the License for the specific language governing permissions and\n//  limitations under the License.\n//\n\nimport XCTest\n\nclass isignTestAppUITests: XCTestCase {\n        \n    override func setUp() {\n        super.setUp()\n        \n        // Put setup code here. This method is called before the invocation of each test method in the class.\n        \n        // In UI tests it is usually best to stop immediately when a failure occurs.\n        continueAfterFailure = false\n        // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.\n        XCUIApplication().launch()\n\n        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.\n    }\n    \n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n    \n    func testExample() {\n        // Use recording to get started writing UI tests.\n        // Use XCTAssert and related functions to verify your tests produce the correct results.\n    }\n    \n}\n"
  },
  {
    "path": "tests/isign_base_test.py",
    "content": "from os.path import dirname, exists, join, isdir\nfrom isign import isign\nimport logging\nfrom monitor_temp_file import MonitorTempFile\nimport os\nimport shutil\nimport tempfile\nimport unittest\n\nlog = logging.getLogger(__name__)\n\n\nclass IsignBaseTest(unittest.TestCase):\n    TEST_DIR = dirname(__file__)\n    TEST_APP = join(TEST_DIR, 'Test.app')\n    TEST_APP_CODESIG_STR = join(TEST_DIR,\n                                'Test.app.codesig.construct.txt')\n    TEST_APPZIP = TEST_APP + '.zip'\n    TEST_IPA = join(TEST_DIR, 'Test.ipa')\n    TEST_WITH_FRAMEWORKS_IPA = join(TEST_DIR, 'TestWithFrameworks.ipa')\n    TEST_NONAPP_DIR = join(TEST_DIR, 'NotAnAppDir')\n    TEST_NONAPP_TXT = join(TEST_DIR, 'NotAnApp.txt')\n    TEST_NONAPP_IPA = join(TEST_DIR, 'NotAnApp.ipa')\n    TEST_SIMULATOR_APP = join(TEST_DIR, 'TestSimulator.app.zip')\n    KEY = join(TEST_DIR, 'credentials', 'test.key.pem')\n    CERTIFICATE = join(TEST_DIR, 'credentials', 'test.cert.pem')\n    PROVISIONING_PROFILE = join(TEST_DIR, 'credentials', 'test.mobileprovision')\n    ERROR_KEY = '_errors'\n    CREDENTIALS_DIR = join(TEST_DIR, 'credentials_std_names')\n    CREDENTIALS_DIR_2 = join(TEST_DIR, 'credentials_std_names_2')\n\n    TEST_UNSIGNED_THIN_APP = join(TEST_DIR, 'Test_unsigned_thin.app')\n    TEST_UNSIGNED_FAT_APP = join(TEST_DIR, 'Test_unsigned_fat.app')\n\n\n    # Fake Apple organizational unit\n    OU = 'ISIGNTESTS'\n\n    def setUp(self):\n        \"\"\" this helps us monitor if we're not cleaning up temp files \"\"\"\n        MonitorTempFile.start()\n\n    def tearDown(self):\n        \"\"\" remove monitor on tempfile creation \"\"\"\n        remaining_temp_files = MonitorTempFile.get_temp_files()\n        MonitorTempFile.stop()\n        if len(remaining_temp_files) != 0:\n            log.error(\"remaining temp files: %s\",\n                      ', '.join(remaining_temp_files))\n#        assert len(remaining_temp_files) == 0\n\n    def resign(self, filename, **args):\n        \"\"\" resign with test credentials \"\"\"\n        args.update({\n            \"key\": self.KEY,\n            \"certificate\": self.CERTIFICATE,\n            \"provisioning_profile\": self.PROVISIONING_PROFILE\n        })\n        return isign.resign(filename, **args)\n\n    def unlink(self, path):\n        if exists(path):\n            if isdir(path):\n                shutil.rmtree(path)\n            else:\n                os.unlink(path)\n\n    def get_temp_file(self, prefix='isign-test-'):\n        \"\"\" just getting a file path that probably isn't in use \"\"\"\n        (fd, path) = tempfile.mkstemp(prefix=prefix)\n        os.close(fd)\n        os.unlink(path)\n        return path\n\n    def get_temp_dir(self, prefix='isign-test-'):\n        return tempfile.mkdtemp(prefix=prefix)\n"
  },
  {
    "path": "tests/monitor_temp_file.py",
    "content": "\"\"\"\"\nisign creates big temporary files, using the standard tempfile library.\nIf they are not cleaned up, they can fill up the disk. This has\nalready happened in production. :(\n\nThis library monkey-patches tempfile to use our own temporary\ndirectory, so it's easy to test that we aren't leaving any temp files behind.\n\"\"\"\nimport os\nimport shutil\nimport tempfile\n\n\nclass MonitorTempFile(object):\n    TEMP_DIR = None\n\n    @classmethod\n    def mkdtemp(cls, *args, **kwargs):\n        \"\"\" ensure temp directories are subdirs of TEMP_DIR \"\"\"\n        kwargs['dir'] = MonitorTempFile.TEMP_DIR\n        return tempfile._original_mkdtemp(*args, **kwargs)\n\n    @classmethod\n    def mkstemp(cls, *args, **kwargs):\n        \"\"\" ensure temp files are within TEMP_DIR \"\"\"\n        kwargs['dir'] = MonitorTempFile.TEMP_DIR\n        return tempfile._original_mkstemp(*args, **kwargs)\n\n    @classmethod\n    def NamedTemporaryFile(cls, *args, **kwargs):\n        \"\"\" ensure named temp files are within TEMP_DIR \"\"\"\n        kwargs['dir'] = MonitorTempFile.TEMP_DIR\n        return tempfile._original_NamedTemporaryFile(*args, **kwargs)\n\n    @classmethod\n    def start(cls):\n        \"\"\" swap a few methods in tempfile with our versions that limit them\n            to a particular directory \"\"\"\n\n        if hasattr(tempfile, '_is_patched') and tempfile._is_patched:\n            raise Exception(\"need tempfile to be in unpatched state!\")\n\n        cls.TEMP_DIR = tempfile.mkdtemp(prefix='isign-test-run-')\n\n        tempfile._original_mkdtemp = tempfile.mkdtemp\n        tempfile.mkdtemp = MonitorTempFile.mkdtemp\n\n        tempfile._original_mkstemp = tempfile.mkstemp\n        tempfile.mkstemp = MonitorTempFile.mkstemp\n\n        tempfile._original_NamedTemporaryFile = tempfile.NamedTemporaryFile\n        tempfile.NamedTemporaryFile = MonitorTempFile.NamedTemporaryFile\n\n        tempfile._is_patched = True\n\n    @classmethod\n    def stop(cls):\n        \"\"\" restore a few methods in tempfile. opposite of _tempfile_patch \"\"\"\n        tempfile.mkdtemp = tempfile._original_mkdtemp\n        tempfile.mkstemp = tempfile._original_mkstemp\n        tempfile.NamedTemporaryFile = tempfile._original_NamedTemporaryFile\n\n        tempfile._is_patched = False\n\n        shutil.rmtree(cls.TEMP_DIR)\n\n        cls.TEMP_DIR = None\n\n    @classmethod\n    def get_temp_files(cls):\n        return os.listdir(cls.TEMP_DIR)\n\n    @classmethod\n    def has_no_temp_files(cls):\n        \"\"\" check if this test has created any temp files which\n            aren't cleaned up \"\"\"\n        if cls.TEMP_DIR is None:\n            raise Exception(\"temp dir is None. Maybe call patch() first?\")\n        return len(cls.get_temp_files()) == 0\n"
  },
  {
    "path": "tests/sample-entitlements.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>application-identifier</key>\n\t<string>ISIGNTEST.com.example.isigntest</string>\n\t<key>com.apple.developer.team-identifier</key>\n\t<string>ISIGNTEST</string>\n\t<key>get-task-allow</key>\n\t<true/>\n\t<key>keychain-access-groups</key>\n\t<array>\n\t\t<string>ISIGNTEST.com.example.isigntest</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "tests/test_archive.py",
    "content": "from isign_base_test import IsignBaseTest\nfrom isign.archive import archive_factory, Archive, AppArchive, AppZipArchive, IpaArchive\nimport logging\n\nlog = logging.getLogger(__name__)\n\n\nclass TestArchive(IsignBaseTest):\n\n    def _test_good(self, filename, klass):\n        archive = archive_factory(filename)\n        assert archive is not None\n        assert archive.__class__ is klass\n        assert isinstance(archive, Archive)\n\n    def test_archive_factory_app(self):\n        self._test_good(self.TEST_APP, AppArchive)\n\n    def test_archive_factory_appzip(self):\n        self._test_good(self.TEST_APPZIP, AppZipArchive)\n\n    def test_archive_factory_ipa(self):\n        self._test_good(self.TEST_IPA, IpaArchive)\n\n    def test_archive_factory_nonapp_dir(self):\n        archive = archive_factory(self.TEST_NONAPP_DIR)\n        assert archive is None\n\n    def test_archive_factory_nonapp_ipa(self):\n        archive = archive_factory(self.TEST_NONAPP_IPA)\n        assert archive is None\n\n    def test_archive_factory_nonapp_txt(self):\n        archive = archive_factory(self.TEST_NONAPP_TXT)\n        assert archive is None\n\n    def test_archive_factory_nonapp_simulator_app(self):\n        archive = archive_factory(self.TEST_SIMULATOR_APP)\n        assert archive is None\n\n\nclass TestBundleInfo(IsignBaseTest):\n\n    def _test_bundle_info(self, filename):\n        archive = archive_factory(filename)\n        assert archive is not None\n        assert archive.bundle_info is not None\n        assert archive.bundle_info['CFBundleName'] == 'isignTestApp'\n\n    def test_app_archive_info(self):\n        self._test_bundle_info(self.TEST_APP)\n\n    def test_appzip_archive_info(self):\n        self._test_bundle_info(self.TEST_APPZIP)\n\n    def test_ipa_archive_info(self):\n        self._test_bundle_info(self.TEST_IPA)\n\n\nclass TestArchivePrecheck(IsignBaseTest):\n\n    def test_precheck_app(self):\n        assert AppArchive.precheck(self.TEST_APP)\n\n    def test_precheck_appzip(self):\n        assert AppZipArchive.precheck(self.TEST_APPZIP)\n\n    def test_precheck_ipa(self):\n        assert IpaArchive.precheck(self.TEST_IPA)\n\n    def test_bad_precheck_app(self):\n        assert AppArchive.precheck(self.TEST_NONAPP_DIR) is False\n        assert AppArchive.precheck(self.TEST_APPZIP) is False\n        assert AppArchive.precheck(self.TEST_IPA) is False\n\n    def test_bad_precheck_appzip(self):\n        assert AppZipArchive.precheck(self.TEST_APP) is False\n        assert AppZipArchive.precheck(self.TEST_IPA) is False\n\n    def test_bad_precheck_ipa(self):\n        assert IpaArchive.precheck(self.TEST_APP) is False\n        assert IpaArchive.precheck(self.TEST_APPZIP) is False\n        assert IpaArchive.precheck(self.TEST_NONAPP_IPA) is False\n"
  },
  {
    "path": "tests/test_creds_dir.py",
    "content": "from isign.exceptions import MissingCredentials\nfrom isign_base_test import IsignBaseTest\nfrom isign import isign\nimport os\nfrom os.path import exists, join\nimport logging\n\nlog = logging.getLogger(__name__)\n\n\nclass TestCredentialsDir(IsignBaseTest):\n\n    def test_creds_dir(self):\n        # this directory contains credentials with the standard names\n        # key.pem, certificate.pem, isign.mobileprovision\n        output_path = self.get_temp_file()\n        isign.resign_with_creds_dir(self.TEST_IPA,\n                                    self.CREDENTIALS_DIR,\n                                    output_path=output_path)\n        assert exists(output_path)\n        assert os.path.getsize(output_path) > 0\n        self.unlink(output_path)\n\n    def test_bad_creds_dir(self):\n        # while this contains credentials, they don't have standard names\n        credentials_dir = join(self.TEST_DIR, 'credentials')\n        output_path = self.get_temp_file()\n        with self.assertRaises(MissingCredentials):\n            isign.resign_with_creds_dir(self.TEST_IPA, credentials_dir, output_path=output_path)\n        self.unlink(output_path)\n"
  },
  {
    "path": "tests/test_entitlements.py",
    "content": "from isign_base_test import IsignBaseTest\nfrom isign.bundle import App\nimport logging\n\nlog = logging.getLogger(__name__)\n\n\nclass TestEntitlements(IsignBaseTest):\n    def test_entitlements_extraction(self):\n        entitlements = App.extract_entitlements(self.PROVISIONING_PROFILE)\n        log.debug(entitlements)\n        assert entitlements['application-identifier'] == 'ISIGNTESTS.*'\n        assert entitlements['get-task-allow'] == True\n"
  },
  {
    "path": "tests/test_helpers.py",
    "content": "import isign.archive\nfrom isign.archive import AppZipArchive\nfrom isign.exceptions import MissingHelpers\nfrom isign_base_test import IsignBaseTest\nfrom distutils import spawn\nimport logging\n\n\nlog = logging.getLogger(__name__)\n\n\nclass MissingHelpersArchive(AppZipArchive):\n    \"\"\" An App whose helpers are not present \"\"\"\n    helpers = ['a_file_that_should_never_be_present']\n\n\ndef dummy_find_executable(name):\n    return '/dummy/path/to/name'\n\n\nclass TestHelpers(IsignBaseTest):\n    def test_helpers_is_present(self):\n        \"\"\" test that missing helpers raises exception \"\"\"\n        with self.assertRaises(MissingHelpers):\n            MissingHelpersArchive.precheck(self.TEST_APPZIP)\n\n    def test_helpers_become_present(self):\n        \"\"\" test that we can install helpers without restart \"\"\"\n        with self.assertRaises(MissingHelpers):\n            MissingHelpersArchive.precheck(self.TEST_APPZIP)\n        spawn._original_find_executable = spawn.find_executable\n        spawn.find_executable = dummy_find_executable\n        MissingHelpersArchive.precheck(self.TEST_APPZIP)\n        if hasattr(spawn, '_original_find_executable'):\n            spawn.find_executable = spawn._original_find_executable\n        isign.archive.helper_paths = {}\n"
  },
  {
    "path": "tests/test_multisign.py",
    "content": "from isign_base_test import IsignBaseTest\nimport os\nfrom os.path import exists\nfrom isign.multisign import multisign\nimport logging\n\nlog = logging.getLogger(__name__)\n\n\nclass TestMultisign(IsignBaseTest):\n\n    def test_multisign(self):\n        output_path1 = self.get_temp_file()\n        output_path2 = self.get_temp_file()\n        creds_dir_to_output_paths = {\n            self.CREDENTIALS_DIR: output_path1,\n            self.CREDENTIALS_DIR_2: output_path2\n        }\n        results = multisign(self.TEST_IPA, creds_dir_to_output_paths)\n        log.debug(\"results: %s\", results)\n        for output_path in [output_path1, output_path2]:\n            assert exists(output_path)\n            assert os.path.getsize(output_path) > 0\n            self.unlink(output_path)\n"
  },
  {
    "path": "tests/test_parsing.py",
    "content": "from isign_base_test import IsignBaseTest\nimport isign.bundle\nfrom isign.signable import Executable\nimport logging\n\nlog = logging.getLogger(__name__)\n\n\nclass TestParsing(IsignBaseTest):\n    \"\"\" This tests whether code signatures are parsed, by comparing\n        stringified parses.\"\"\"\n    # Tests the parse-before-resign functionality used in\n    # bin/pprint_codesig, which isn't exposed nicely as such.\n    # Also see generate_codesig_construct_txt.py, to generate\n    # the string this tests for\n    def test_app(self):\n        with open(self.TEST_APP_CODESIG_STR, 'r') as f:\n            expected_codesig_str = f.read().strip()\n        bundle = isign.bundle.App(self.TEST_APP)\n        executable = Executable(bundle, bundle.get_executable_path(), None)\n        arch = executable.arches[0]\n        codesig_str = str(arch['cmds']['LC_CODE_SIGNATURE'])\n        self.assertEquals(expected_codesig_str, codesig_str)\n"
  },
  {
    "path": "tests/test_public_interface.py",
    "content": "from isign_base_test import IsignBaseTest\nimport os\nfrom os.path import exists\nfrom isign import isign\nimport logging\n\nlog = logging.getLogger(__name__)\n\n\nclass TestPublicInterface(IsignBaseTest):\n\n    def _test_signable(self, filename, output_path):\n        self.resign(filename, output_path=output_path)\n        assert exists(output_path)\n        assert os.path.getsize(output_path) > 0\n        self.unlink(output_path)\n\n    def _test_unsignable(self, filename, output_path):\n        with self.assertRaises(isign.NotSignable):\n            self.resign(filename, output_path=output_path)\n        self.unlink(output_path)\n\n    def test_app(self):\n        self._test_signable(self.TEST_APP, self.get_temp_dir())\n\n    def test_app_ipa(self):\n        self._test_signable(self.TEST_IPA, self.get_temp_file())\n\n    def test_app_with_frameworks_ipa(self):\n        self._test_signable(self.TEST_WITH_FRAMEWORKS_IPA, self.get_temp_file())\n\n    def test_appzip(self):\n        self._test_signable(self.TEST_APPZIP, self.get_temp_file())\n\n    def test_non_app_txt(self):\n        self._test_unsignable(self.TEST_NONAPP_TXT, self.get_temp_file())\n\n    def test_non_app_ipa(self):\n        self._test_unsignable(self.TEST_NONAPP_IPA, self.get_temp_file())\n\n    def test_simulator_app(self):\n        self._test_unsignable(self.TEST_SIMULATOR_APP, self.get_temp_file())\n"
  },
  {
    "path": "tests/test_sig.py",
    "content": "import isign\nfrom isign_base_test import IsignBaseTest\nfrom os.path import join\n\n\nclass TestSigner(IsignBaseTest):\n\n    def test_bad_signature(self):\n        \"\"\" make openssl appear to return a bad signature \"\"\"\n        old_openssl = isign.signer.OPENSSL\n        try:\n            signer = isign.signer.Signer(\n                signer_key_file=self.KEY,\n                signer_cert_file=self.CERTIFICATE,\n                apple_cert_file=isign.isign.DEFAULT_APPLE_CERT_PATH)\n            isign.signer.OPENSSL = join(self.TEST_DIR, \"bad_openssl\")\n            with self.assertRaises(Exception):\n                signer.sign(\"some data\")\n        finally:\n            isign.signer.OPENSSL = old_openssl\n"
  },
  {
    "path": "tests/test_versioning.py",
    "content": "#!/usr/bin/env python\nimport os.path\nimport importlib\nimport unittest\n\ntests_dir = os.path.abspath(os.path.dirname(__file__))\npackage_name = tests_dir.split(os.path.sep)[-2].replace('-', '_')\npackage = importlib.import_module(package_name)\n\n\nclass VersioningTestCase(unittest.TestCase):\n\n    def assert_proper_attribute(self, attribute):\n        try:\n            assert getattr(package, attribute), (\n                \"{} improperly set\".format(attribute))\n        except AttributeError:\n            assert False, \"missing {}\".format(attribute)\n\n    def test_version_attribute(self):\n        self.assert_proper_attribute(\"__version__\")\n\n        # test major, minor, and patch are numbers\n        version_split = package.__version__.split(\".\")[:3]\n        assert version_split, \"__version__ is not set\"\n        for n in version_split:\n            try:\n                int(n)\n            except ValueError:\n                assert False, \"'{}' is not an integer\".format(n)\n\n    def test_commit_attribute(self):\n        self.assert_proper_attribute(\"__commit__\")\n\n    def test_build_attribute(self):\n        self.assert_proper_attribute(\"__build__\")\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "tests/test_versus_apple.py",
    "content": "from distutils import spawn\nfrom isign_base_test import IsignBaseTest\nimport logging\nfrom nose.plugins.skip import SkipTest\nimport os\nfrom os.path import join\nimport platform\nimport re\nimport shutil\nimport subprocess\nimport tempfile\nimport zipfile\n\nCODESIGN_BIN = spawn.find_executable('codesign')\n\nlog = logging.getLogger(__name__)\n\n\nclass TestVersusApple(IsignBaseTest):\n    def codesign_display(self, path):\n        \"\"\" inspect a path with codesign \"\"\"\n        cmd = [CODESIGN_BIN, '-d', '-r-', '--verbose=20', path]\n        # n.b. codesign may print things to STDERR, or STDOUT, depending\n        # on exactly what you're extracting. I KNOW RIGHT?\n        proc = subprocess.Popen(cmd,\n                                stdout=subprocess.PIPE,\n                                stderr=subprocess.STDOUT)\n        out, _ = proc.communicate()\n        if proc.returncode != 0:\n            log.debug(out)\n            log.debug(_)\n        assert proc.returncode == 0, \"Return code not 0\"\n        return self.codesign_display_parse(out)\n\n    def codesign_display_parse(self, out):\n        \"\"\"\n        Parse codesign output into a dict.\n\n        The output format is XML-like, in that it's a tree of nodes of\n        varying types (including key-val pairs). We are assuming that\n        it never gets more than 1 level deep (so, \"array line\" is just\n        a special case here)\n        \"\"\"\n\n        # designated => identifier \"com.lyft.ios.enterprise.dev\" and anchor...\n        text_line = re.compile('^(\\w[\\w\\s.]+) => (.*)$')\n\n        # CodeDirectory v=20200 size=79151 flags=0x0(none) hashes=3948+5 ...\n        props_line = re.compile('^(\\w[\\w\\s.]+)\\s+((?:\\w+=\\S+\\s*)+)$')\n\n        # Signed Time=May 14, 2015, 7:12:25 PM\n        # Info.plist=not bound\n        single_prop_line = re.compile('(\\w[\\w\\s.]+)=(.*)$')\n\n        # this assumes we only have one level of sub-arrays\n        #    -3=969d263f74a5755cd3b4bede3f9e90c9fb0b7bca\n        array_line = re.compile('\\s+(-?\\d+)=(.*)$')\n\n        # last node assigned - used for appending sub-arrays, if encountered\n        last = None\n\n        ret = {}\n\n        for line in out.splitlines():\n            key = None\n            val = None\n            text_match = text_line.match(line)\n            props_match = props_line.match(line)\n            sp_match = single_prop_line.match(line)\n            array_match = array_line.match(line)\n            if text_match:\n                key = text_match.group(1)\n                val = text_match.group(2)\n            elif props_match:\n                key = props_match.group(1)\n                val = {}\n                pairs = re.split('\\s+', props_match.group(2))\n                for pair in pairs:\n                    pairmatch = re.match('(\\w+)=(\\S+)', pair)\n                    pairkey = pairmatch.group(1)\n                    pairval = pairmatch.group(2)\n                    val[pairkey] = pairval\n            elif sp_match:\n                key = sp_match.group(1)\n                val = sp_match.group(2)\n            elif array_match:\n                if '_' not in last:\n                    last['_'] = {}\n                akey = array_match.group(1)\n                aval = array_match.group(2)\n                last['_'][akey] = aval\n            else:\n                # probably an error of some kind. These\n                # get appended into the output too. :(\n                if self.ERROR_KEY not in ret:\n                    ret[self.ERROR_KEY] = []\n                ret[self.ERROR_KEY].append(line)\n            if key is not None:\n                if key not in ret:\n                    ret[key] = []\n                ret[key].append(val)\n                last = val\n\n        return ret\n\n    def get_dict_with_key(self, x, key):\n        \"\"\" check a list for a dict that has a key \"\"\"\n        # e.g. if x = [ { 'a': 1 }, { 'b': 2 }]\n        #      and key = 'a'\n        #      return 1\n        for item in x:\n            if key in item:\n                return item[key]\n        return None\n\n    def get_hashes_from_codesign_output_info(self, info):\n        try:\n            return self.get_dict_with_key(info['Hash'], '_') or info['Page'][0]['_']\n        except KeyError:\n            return None\n\n    def assert_common_signed_properties(self, info):\n        # has an executable\n        assert 'Executable' in info\n\n        # has an identifier\n        assert 'Identifier' in info\n\n        # has a codedirectory, embedded\n        assert 'CodeDirectory' in info\n        codedirectory_info = info['CodeDirectory'][0]\n        assert codedirectory_info['location'] == 'embedded'\n\n        # has a set of hashes\n        assert 'Hash' in info\n        hashes = self.get_hashes_from_codesign_output_info(info)\n\n        assert hashes is not None\n\n        # seal hash\n        assert 'CDHash' in info\n\n        # signed\n        assert 'Signature' in info\n\n        assert 'Authority' in info\n        # The following only works with a cert signed by apple\n        #\n        # if isinstance(info['Authority'], list):\n        #    authorities = info['Authority']\n        # else:\n        #    authorities = [info['Authority']]\n        # assert 'Apple Root CA' in authorities\n\n        assert 'Info.plist' in info\n        assert self.get_dict_with_key(info['Info.plist'], 'entries') is not None\n\n        assert 'TeamIdentifier' in info\n        # TODO get this from an arg\n        assert info['TeamIdentifier'][0] == self.OU\n\n        assert 'designated' in info\n        assert 'anchor apple generic' in info['designated'][0]\n\n        # should have no errors\n        assert self.ERROR_KEY not in info\n\n    def assert_common_signed_hashes(self, info, start_index, end_index):\n        assert 'Hash' in info\n        hashes = self.get_hashes_from_codesign_output_info(info)\n        assert hashes is not None\n        for i in range(start_index, end_index + 1):\n            assert str(i) in hashes\n        return hashes\n\n    def assert_hashes_for_signable(self, info, hashes_to_check):\n        \"\"\" check that various hashes look right. \"\"\"\n        # Most of the hashes in the Hash section are hashes of blocks of the\n        # object code in question. These all have positive subscripts.\n        # But the \"special\" slots use negative numbers, and\n        # are hashes of:\n        # -5 Embedded entitlement configuration slot\n        # -4 App-specific slot (in all the examples we know of, all zeroes)\n        # -3 Resource Directory slot\n        # -2 Requirements slot\n        # -1 Info.plist slot\n        # For more info, see codedirectory.h in Apple open source, e.g.\n        # http://opensource.apple.com/source/libsecurity_codesigning/\n        #   libsecurity_codesigning-55032/lib/codedirectory.h\n        assert 'Hash' in info\n        hashes = self.get_hashes_from_codesign_output_info(info)\n        assert hashes is not None\n        for i in hashes_to_check:\n            key = str(i)\n            assert key in hashes\n            assert int(hashes[key], 16) != 0\n\n    def assert_matching_identifier(self, app_path, expected):\n        info = self.codesign_display(app_path)\n        identifier = info['Identifier'][0]\n        assert identifier == expected\n\n    def check_bundle(self, path):\n        \"\"\" look at info for bundles (apps and frameworks) \"\"\"\n        info = self.codesign_display(path)\n        self.assert_common_signed_properties(info)\n        assert 'Sealed Resources' in info\n        self.assert_hashes_for_signable(info, [-5, -3, -2, -1])\n        # TODO subject.CN from cert?\n\n    def check_dylib(self, path):\n        info = self.codesign_display(path)\n        self.assert_common_signed_properties(info)\n        self.assert_hashes_for_signable(info, [-2, -1])\n\n    def test_override_identifier(self):\n        \"\"\" Resign an app with identifiers of varying lengths, test that\n            they were signed correctly with the new identifier  \"\"\"\n        # skip if this isn't a Mac with codesign installed\n        if platform.system() != 'Darwin' or CODESIGN_BIN is None:\n            raise SkipTest\n\n#        old_cwd = os.getcwd()\n\n        info = self.codesign_display(self.TEST_APP)\n        original_id = info['Identifier'][0]\n\n        # Make sure our original ID is long enough to test shorter bundle ids\n        assert len(original_id) >= 6\n\n        alphabet = 'abcdefghijklmnopqrstuvwxyz'\n        while len(alphabet) <= len(original_id):\n            alphabet += alphabet\n\n        # Test with a shorter bundle ID\n        short_id = alphabet[0:len(original_id) / 2 + 1]\n        working_dir = tempfile.mkdtemp()\n        os.chdir(working_dir)\n        resigned_app_path = join(working_dir, 'Short.app')\n        self.resign(self.TEST_APP,\n                    output_path=resigned_app_path,\n                    info_props={\n                        'CFBundleIdentifier': short_id\n                    })\n        self.assert_matching_identifier(resigned_app_path, short_id)\n        shutil.rmtree(working_dir)\n\n        # Test with a longer bundle ID\n        long_id = alphabet[0:len(original_id) + 1]\n        working_dir = tempfile.mkdtemp()\n        os.chdir(working_dir)\n        resigned_app_path = join(working_dir, 'Long.app')\n        self.resign(self.TEST_APP,\n                    output_path=resigned_app_path,\n                    info_props={\n                        'CFBundleIdentifier': long_id\n                    })\n        self.assert_matching_identifier(resigned_app_path, long_id)\n\n #       os.chdir(old_cwd)\n        shutil.rmtree(working_dir)\n\n\n    def test_app(self):\n        \"\"\" Extract a resigned app with frameworks, analyze if some expected\n            things about them are true \"\"\"\n        # skip if this isn't a Mac with codesign installed\n        if platform.system() != 'Darwin' or CODESIGN_BIN is None:\n            raise SkipTest\n\n        old_cwd = os.getcwd()\n\n        # resign the test app that has frameworks, extract it to a temp directory\n        working_dir = tempfile.mkdtemp()\n        resigned_ipa_path = join(working_dir, 'resigned.ipa')\n        self.resign(self.TEST_WITH_FRAMEWORKS_IPA,\n                    output_path=resigned_ipa_path)\n        os.chdir(working_dir)\n        with zipfile.ZipFile(resigned_ipa_path) as zf:\n            zf.extractall()\n\n        # expected path to app\n        # When we ask for codesign to analyze the app directory, it\n        # will default to showing info for the main executable\n        app_path = join(working_dir, 'Payload/isignTestApp.app')\n        self.check_bundle(app_path)\n\n        # Now we do similar tests for a dynamic library, linked to the\n        # main executable.\n        dylib_path = join(app_path, 'Frameworks', 'libswiftCore.dylib')\n        self.check_dylib(dylib_path)\n\n        # Now we do similar tests for a framework\n        framework_path = join(app_path, 'Frameworks', 'FontAwesome_swift.framework')\n        self.check_bundle(framework_path)\n\n        os.chdir(old_cwd)\n        shutil.rmtree(working_dir)\n\n\n    def test_app_from_scratch(self):\n        \"\"\" Test signing app bundles from scratch \"\"\"\n        # skip if this isn't a Mac with codesign installed\n        if platform.system() != 'Darwin' or CODESIGN_BIN is None:\n            raise SkipTest\n\n        working_dir = tempfile.mkdtemp()\n        signed_app_path = join(working_dir, 'signed.app')\n        self.resign(self.TEST_UNSIGNED_THIN_APP,\n                    output_path=signed_app_path)\n        os.chdir(working_dir)\n\n        # expected path to app\n        # When we ask for codesign to analyze the app directory, it\n        # will default to showing info for the main executable\n        app_path = signed_app_path\n        self.check_bundle(app_path)\n\n        # Now we do similar tests for a dynamic library, linked to the\n        # main executable.\n        dylib_path = join(app_path, 'Frameworks', 'libswiftCore.dylib')\n        self.check_dylib(dylib_path)\n\n\n        shutil.rmtree(working_dir)\n\n\n        working_dir = tempfile.mkdtemp()\n        signed_app_path = join(working_dir, 'signed.app')\n        self.resign(self.TEST_UNSIGNED_FAT_APP,\n                    output_path=signed_app_path)\n        os.chdir(working_dir)\n\n        # expected path to app\n        # When we ask for codesign to analyze the app directory, it\n        # will default to showing info for the main executable\n        app_path = signed_app_path\n        self.check_bundle(app_path)\n\n        # Now we do similar tests for a dynamic library, linked to the\n        # main executable.\n        dylib_path = join(app_path, 'Frameworks', 'libswiftCore.dylib')\n        self.check_dylib(dylib_path)\n\n\n        shutil.rmtree(working_dir)\n"
  },
  {
    "path": "version.sh",
    "content": "#!/bin/bash\n\n# Figures out what the current version is, echoes that back,\n# and also writes a `version.json` file into the package.\n\nset -e\nMAJMIN_VERSION=\"1.6\"\n\npushd $(dirname $0) >/dev/null\nworking_dir=$PWD\nname=$(basename $PWD)\npopd >/dev/null\npackage=$(echo $name | sed 's/-/_/g')\nversion_json=\"${working_dir}/${package}/version.json\"\n\nversion_suffix=\"\"\n# official version\nif [[ \"$JOB_NAME\" = \"${name}\" ]] && [[ -n \"$BUILD_TAG\" ]]; then\n    patch_version=0\n    if [[ -n \"$(git tag --list v$MAJMIN_VERSION.0)\" ]]; then\n        # number of commits since vMAJOR.MINOR.0\n        patch_version=$(git rev-list --count $(git describe --tags --match \"v${MAJMIN_VERSION}.0\" | cut -f 1 -d -)...HEAD)\n    fi\n    # add post version if built before (i.e., already tagged)\n    post_version=$(git tag --contain | wc -l | awk '{print $1}')\n    test \"$post_version\" -gt 0 && version_suffix=\".post${post_version}\"\n# development version\nelse\n    if [[ -n \"$(git tag --list 'v[0-9]*')\" ]]; then\n        recent_tag=$(git describe --tags --match 'v[0-9]*' | cut -f 1 -d -)\n        majmin_version=$(echo $recent_tag | tr \"v.-\" \" \" | awk '{print $1\".\"$2}')\n        patch_version=$(echo $recent_tag | tr \"v.-\" \" \" | awk '{print $3}')\n        dev_version=$(git rev-list --count ${recent_tag}...HEAD)\n    else  # start of dev, nothing tagged\n        majmin_version=\"0.0\"\n        patch_version=\"0\"\n        dev_version=$(git rev-list --count HEAD)\n    fi\n    version_suffix=\".$(date '+%s').dev${dev_version}+${USER}\"\nfi\n\nversion=\"${majmin_version:-$MAJMIN_VERSION}.${patch_version}${version_suffix}\"\njson='\"version\": \"'$version'\", \"commit\": \"'$(git rev-parse HEAD)'\", \"build\": \"'${BUILD_TAG:-\"dev\"}'\"'\n# write-out version.json\necho \"{${json}}\" > $version_json\n\nstyle=\"$1\"\nif [[ \"$style\" = \"json\" ]]; then\n    cat $version_json\nelse\n    echo $version\nfi\n"
  }
]