xulrunner/app/install_app.py

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 #!/usr/bin/env python
     3 # This Source Code Form is subject to the terms of the Mozilla Public
     4 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
     5 # You can obtain one at http://mozilla.org/MPL/2.0/.
     7 # Min version of python is 2.7
     8 import sys
     9 if ((sys.version_info.major != 2) or (sys.version_info.minor < 7)):
    10     raise Exception("You need to use Python version 2.7 or higher")
    12 import os, shutil, re, zipfile
    13 from ConfigParser import SafeConfigParser
    15 # Platform-specific support
    16 # see https://developer.mozilla.org/en/XULRunner/Deploying_XULRunner_1.8
    17 if sys.platform.startswith('linux') or sys.platform == "win32":
    18     def installApp(appLocation, installDir, appName, greDir):
    19         zipApp, iniParser, appName = validateArguments(appLocation, installDir, appName, greDir)
    20         if (zipApp):
    21             zipApp.extractAll(installDir)
    22         else:
    23             shutil.copytree(appLocation, installDir)
    24         shutil.copy2(os.path.join(greDir, xulrunnerStubName),
    25                      os.path.join(installDir, appName))
    26         copyGRE(greDir, os.path.join(installDir, "xulrunner"))
    28 if sys.platform.startswith('linux'):
    29     xulrunnerStubName = "xulrunner-stub"
    31     def makeAppName(leafName):
    32         return leafName.lower()
    34 elif sys.platform == "win32":
    35     xulrunnerStubName = "xulrunner-stub.exe"
    37     def makeAppName(leafName):
    38         return leafName + ".exe"
    40 elif sys.platform == "darwin":
    41     xulrunnerStubName = "xulrunner"
    43     def installApp(appLocation, installDir, appName, greDir):
    44         zipApp, iniparser, appName = validateArguments(appLocation, installDir, appName, greDir)
    45         installDir += "/" + appName + ".app"
    46         resourcesDir = os.path.join(installDir, "Contents/Resources")
    47         if (zipApp):
    48             zipApp.extractAll(resourcesDir)
    49         else:
    50             shutil.copytree(appLocation, resourcesDir)
    51         MacOSDir = os.path.join(installDir, "Contents/MacOS")
    52         os.makedirs(MacOSDir)
    53         shutil.copy2(os.path.join(greDir, xulrunnerStubName), MacOSDir)
    54         copyGRE(greDir,
    55                 os.path.join(installDir, "Contents/Frameworks/XUL.framework"))
    57         # Contents/Info.plist
    58         contents = """<?xml version="1.0" encoding="UTF-8"?>
    59 <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    60 <plist version="1.0">
    61 <dict>
    62 <key>CFBundleInfoDictionaryVersion</key>
    63 <string>6.0</string>
    64 <key>CFBundlePackageType</key>
    65 <string>APPL</string>
    66 <key>CFBundleSignature</key>
    67 <string>????</string>
    68 <key>CFBundleExecutable</key>
    69 <string>xulrunner</string>
    70 <key>NSAppleScriptEnabled</key>
    71 <true/>
    72 <key>CFBundleGetInfoString</key>
    73 <string>$infoString</string>
    74 <key>CFBundleName</key>
    75 <string>$appName</string>
    76 <key>CFBundleShortVersionString</key>
    77 <string>$version</string>
    78 <key>CFBundleVersion</key>
    79 <string>$version.$buildID</string>
    80 <key>CFBundleIdentifier</key>
    81 <string>$reverseVendor</string>
    82 </dict>
    83 </plist>
    84 """
    85         version = iniparser.get("App", "Version")
    86         buildID = iniparser.get("App", "BuildID")
    87         infoString = appName + " " + version
    88         reverseVendor = "com.vendor.unknown"
    89         appID = iniparser.get("App", "ID")
    90         colonIndex = appID.find("@") + 1
    91         if (colonIndex != 0):
    92             vendor = appID[colonIndex:]
    93             reverseVendor = ".".join(vendor.split(".")[::-1])
    94         contents = contents.replace("$infoString", infoString)
    95         contents = contents.replace("$appName", appName)
    96         contents = contents.replace("$version", version)
    97         contents = contents.replace("$buildID", buildID)
    98         contents = contents.replace("$reverseVendor", reverseVendor)
    99         infoPList = open(os.path.join(installDir, "Contents/Info.plist"), "w+b")
   100         infoPList.write(contents)
   101         infoPList.close()
   103     def makeAppName(leafName):
   104         return leafName
   106 else:
   107     # Implement xulrunnerStubName, installApp and makeAppName as above.
   108     raise Exception("This operating system isn't supported for install_app.py yet!")
   109 # End platform-specific support
   111 def resolvePath(path):
   112     return os.path.realpath(path)
   114 def requireINIOption(iniparser, section, option):
   115     if not (iniparser.has_option(section, option)):
   116         raise Exception("application.ini must have a " + option + " option under the " +  section + " section")
   118 def checkAppINI(appLocation):
   119     if (os.path.isdir(appLocation)):
   120         zipApp = None
   121         appINIPath = os.path.join(appLocation, "application.ini")
   122         if not (os.path.isfile(appINIPath)):
   123             raise Exception(appINIPath + " does not exist")
   124         appINI = open(appINIPath)
   125     elif (zipfile.is_zipfile(appLocation)):
   126         zipApp = zipfile.ZipFile(appLocation)
   127         if not ("application.ini" in zipApp.namelist()):
   128             raise Exception("jar:" + appLocation + "!/application.ini does not exist")
   129         appINI = zipApp.open("application.ini")
   130     else:
   131         raise Exception("appLocation must be a directory containing application.ini or a zip file with application.ini at its root")
   133     # application.ini verification
   134     iniparser = SafeConfigParser()
   135     iniparser.readfp(appINI)
   136     if not (iniparser.has_section("App")):
   137         raise Exception("application.ini must have an App section")
   138     if not (iniparser.has_section("Gecko")):
   139         raise Exception("application.ini must have a Gecko section")
   140     requireINIOption(iniparser, "App", "Name")
   141     requireINIOption(iniparser, "App", "Version")
   142     requireINIOption(iniparser, "App", "BuildID")
   143     requireINIOption(iniparser, "App", "ID")
   144     requireINIOption(iniparser, "Gecko", "MinVersion")
   146     return zipApp, iniparser
   147     pass
   149 def copyGRE(greDir, targetDir):
   150     shutil.copytree(greDir, targetDir, symlinks=True)
   152 def validateArguments(appLocation, installDir, appName, greDir):
   153     # application directory / zip verification
   154     appLocation = resolvePath(appLocation)
   156     # target directory
   157     installDir = resolvePath(installDir)
   159     if (os.path.exists(installDir)):
   160         raise Exception("installDir must not exist: " + cmds.installDir)
   162     greDir = resolvePath(greDir)
   163     xulrunnerStubPath = os.path.isfile(os.path.join(greDir, xulrunnerStubName))
   164     if not xulrunnerStubPath:
   165         raise Exception("XULRunner stub executable not found: " + os.path.join(greDir, xulrunnerStubName))
   167     # appName
   168     zipApp, iniparser = checkAppINI(appLocation)
   169     if not appName:
   170         appName = iniparser.get("App", "Name")
   171     appName = makeAppName(appName)
   172     pattern = re.compile("[\\\/\:*?\"<>|\x00]")
   173     if pattern.search(appName):
   174         raise Exception("App name has illegal characters for at least one operating system")
   175     return zipApp, iniparser, appName
   177 def handleCommandLine():
   178     import argparse
   180     # Argument parsing.
   181     parser = argparse.ArgumentParser(
   182         description="XULRunner application installer",
   183         usage="""install_app.py appLocation installDir greDir [--appName APPNAME]
   184            install_app.py -h
   185            install_app.py --version
   186     """
   187     )
   188     parser.add_argument(
   189         "appLocation",
   190         action="store",
   191         help="The directory or ZIP file containing application.ini as a top-level child file"
   192     )
   193     parser.add_argument(
   194         "installDir",
   195         action="store",
   196         help="The directory to install the application to"
   197     )
   198     parser.add_argument(
   199         "--greDir",
   200         action="store",
   201         help="The directory containing the Gecko SDK (usually where this Python script lives)",
   202         default=os.path.dirname(sys.argv[0])
   203     )
   204     parser.add_argument(
   205         "--appName",
   206         action="store",
   207         help="The name of the application to install"
   208     )
   209     parser.add_argument("--version", action="version", version="%(prog)s 1.0")
   211     # The command code.
   212     cmds = parser.parse_args()
   213     try:
   214         installApp(cmds.appLocation, cmds.installDir, cmds.appName, cmds.greDir)
   215     except exn:
   216         shutil.rmtree(cmds.installDir)
   217         raise exn
   218     print cmds.appName + " application installed to " + cmds.installDir
   220 if __name__ == '__main__':
   221     handleCommandLine()

mercurial