summaryrefslogtreecommitdiff
path: root/install-xpi
diff options
context:
space:
mode:
Diffstat (limited to 'install-xpi')
-rwxr-xr-xinstall-xpi258
1 files changed, 258 insertions, 0 deletions
diff --git a/install-xpi b/install-xpi
new file mode 100755
index 0000000..ddd7b1a
--- /dev/null
+++ b/install-xpi
@@ -0,0 +1,258 @@
+#!/usr/bin/python
+
+# Copyright (c) 2009-2011, Benjamin Drung <bdrung@debian.org>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import csv
+import optparse
+import os
+import stat
+import subprocess
+import sys
+import zipfile
+
+import RDF
+
+LICENSE_PATTERN_LIST = (
+ "copying",
+ "gpl.txt",
+ "licence",
+ "license",
+ "licence.txt",
+ "license.txt"
+)
+
+# error codes
+COMMAND_LINE_SYNTAX_ERROR = 1
+XPI_FILE_DOES_NOT_EXISTS = 2
+
+def get_query_field_id_as_list(rdf_path, query_string):
+ ret = []
+ model = RDF.Model()
+ parser = RDF.Parser(name="rdfxml")
+ parser.parse_into_model(model, "file:" + rdf_path)
+ query = RDF.Query("PREFIX em: <http://www.mozilla.org/2004/em-rdf#> " + \
+ query_string, query_language="sparql")
+ results = query.execute(model)
+ for result in results:
+ ret.append(result["id"].literal_value["string"])
+ return ret
+
+def get_target_applications(install_rdf):
+ target_applications = get_query_field_id_as_list(install_rdf,
+ "SELECT ?id WHERE { ?x1 em:targetApplication ?x2 . ?x2 em:id ?id }")
+ return target_applications
+
+def get_extension_id(install_rdf):
+ extension_ids = set(get_query_field_id_as_list(install_rdf,
+ "SELECT ?id WHERE {?x1 em:targetApplication ?x2 . ?x1 em:id ?id }"))
+ return extension_ids.pop()
+
+def get_arch(package):
+ lines = open("debian/control").readlines()
+ package_lines = filter(lambda x: x.find("Package:") >= 0, lines)
+ packages = map(lambda x: x[x.find(":")+1:].strip(), package_lines)
+ architecture_lines = filter(lambda x: x.find("Architecture:") >= 0, lines)
+ architectures = map(lambda x: x[x.find(":")+1:].strip(), architecture_lines)
+ (_, arch) = filter(lambda (x, y): x == package,
+ zip(packages, architectures))[0]
+ return arch
+
+def get_mode(filename):
+ statinfo = os.stat(filename)
+ mode = statinfo[stat.ST_MODE]
+ return mode & 0777
+
+def get_xul_apps():
+ csvfile = open("/usr/share/mozilla-devscripts/xul-app-data.csv")
+ csv_reader = csv.DictReader(csvfile)
+ rows = []
+ for row in csv_reader:
+ rows.append(row)
+ return rows
+
+def install_xpi(script_name, package, xpi_file, exclude, install_dir, links,
+ correct_permissions, remove_licenses, system_prefs, verbose=False):
+ # get xpi file content list
+ if not os.path.isfile(xpi_file):
+ print >> sys.stderr, "%s: Error: xpi file %s does not exist." % \
+ (script_name, xpi_file)
+ sys.exit(XPI_FILE_DOES_NOT_EXISTS)
+ zfobj = zipfile.ZipFile(xpi_file)
+ xpi_content = zfobj.namelist()
+
+ # determine installation directory
+ if get_arch(package) == "all":
+ lib_share_dir = "share"
+ else:
+ lib_share_dir = "lib"
+ if install_dir is None:
+ install_dir = os.path.join("usr", lib_share_dir, "xul-ext",
+ package.replace("xul-ext-", ""))
+ copy_dir = os.path.join("debian", package, install_dir.strip("/"))
+ if verbose:
+ print "%s: install directory: %s" % (script_name, install_dir)
+
+ # remove documented license files
+ if remove_licenses:
+ for name in filter(lambda x: not x.endswith('/'), xpi_content):
+ basename = os.path.basename(name).lower()
+ if basename in LICENSE_PATTERN_LIST:
+ exclude.append(name)
+ print "%s: exclude license file %s" % (script_name, name)
+
+ # create directory and extract xpi file
+ if not os.path.isdir(copy_dir):
+ os.makedirs(copy_dir)
+ command = ["unzip", "-o", "-d", copy_dir, xpi_file]
+ if len(exclude) > 0:
+ command.append("-x")
+ command.extend(exclude)
+ print " ".join(command)
+ subprocess.call(command)
+
+ # correct permissons of files to 644 and directories to 755
+ if correct_permissions:
+ for name in xpi_content:
+ filename = os.path.join(copy_dir, name)
+ if os.path.exists(filename):
+ mode = get_mode(filename)
+ if os.path.isdir(filename) and mode != 0755:
+ print "%s: correct permission from %s to %s of %s" % \
+ (script_name, oct(mode), oct(0755), name)
+ os.chmod(filename, 0755)
+ elif os.path.isfile(filename):
+ header = open(filename, "r").read(2)
+ if header != "#!" and mode != 0644:
+ # file without shebang
+ print "%s: correct permission from %s to %s of %s" % \
+ (script_name, oct(mode), oct(0644), name)
+ os.chmod(filename, 0644)
+ elif header == "#!" and mode != 0755:
+ # file with shebang
+ print "%s: correct permission from %s to %s of %s" % \
+ (script_name, oct(mode), oct(0755), name)
+ os.chmod(filename, 0755)
+
+ # create a system preference file in /etc
+ if system_prefs:
+ # search for preference files
+ pref_dir = os.path.join("defaults", "preferences")
+ preferences = filter(lambda f: os.path.dirname(f) == pref_dir and \
+ f.endswith(".js"), xpi_content)
+ if len(preferences) > 0:
+ prefdir = os.path.join("etc", "xul-ext")
+ full_prefdir = os.path.join("debian", package, prefdir)
+ if not os.path.exists(full_prefdir):
+ os.makedirs(full_prefdir)
+ prefname = package.replace("xul-ext-", "") + ".js"
+ # create system preference file
+ f = open(os.path.join(full_prefdir, prefname), "w")
+ if os.path.isfile(os.path.join("debian", package + ".js")):
+ # use debian/package.js as configuration file if it exists
+ content = open(os.path.join("debian", package + ".js")).read()
+ # replace @INSTALLDIR@ by the actual installation directory
+ content = content.replace("@INSTALLDIR@",
+ os.path.join("/", install_dir))
+ f.write(content)
+ else:
+ f.write("// Place your preferences for " + package +
+ " in this file.\n")
+ f.write("// You can override here the preferences specified "
+ "in\n")
+ map(lambda x: f.write("// " +
+ os.path.join("/", install_dir, x) +
+ "\n"), preferences)
+ f.close()
+ link_source = os.path.join(prefdir, prefname)
+ link_target = os.path.join(install_dir, "defaults", "preferences",
+ "000system.js")
+ command = ["dh_link", "-p" + package, link_source, link_target]
+ if verbose:
+ print " ".join(command)
+ subprocess.call(command)
+
+ # get symlinks list
+ extension_id = get_extension_id(os.path.join(copy_dir, "install.rdf"))
+ filename = os.path.join(copy_dir, "install.rdf")
+ target_applications = get_target_applications(filename)
+ for target_application in target_applications:
+ destination = os.path.join("/usr", lib_share_dir, "mozilla/extensions",
+ target_application, extension_id)
+ links.add(destination)
+
+ # create symlinks
+ for link in links:
+ command = ["dh_link", "-p" + package, install_dir, link]
+ print " ".join(command)
+ subprocess.call(command)
+
+def get_first_package():
+ lines = open("debian/control").readlines()
+ package_lines = filter(lambda x: x.find("Package:") >= 0, lines)
+ packages = map(lambda x: x[x.find(":")+1:].strip(), package_lines)
+ return packages[0]
+
+def main():
+ usage = "%s [options] <xpi-file>" % (os.path.basename(sys.argv[0]))
+ epilog = "See %s(1) for more info." % (os.path.basename(sys.argv[0]))
+ parser = optparse.OptionParser(usage=usage, epilog=epilog)
+
+ parser.add_option("--disable-system-prefs",
+ help="do not create a system preference file in /etc",
+ dest="system_prefs", action="store_false", default=True)
+ parser.add_option("-x", "--exclude", metavar="FILE",
+ help="do not install specified FILE",
+ dest="exclude", action="append", default=list())
+ parser.add_option("-i", "--install-dir", metavar="DIRECTORY",
+ help="install extension into the specified DIRECTORY",
+ dest="install_dir")
+ parser.add_option("-l", "--link", metavar="DIRECTORY",
+ help="link from DIRECTORY to extension directory",
+ dest="links", action="append", default=list())
+ parser.add_option("-p", "--package", metavar="PACKAGE",
+ help="install the extension into specified PACKAGE",
+ dest="package", default=get_first_package())
+ parser.add_option("--preserve-permissions",
+ help="do not adjust the file permissions",
+ dest="correct_permissions", action="store_false", default=True)
+ parser.add_option("-r", "--remove-license-files",
+ help="do not install license files",
+ dest="remove_licenses", action="store_true", default=False)
+ parser.add_option("-v", "--verbose", help="print more information",
+ dest="verbose", action="store_true", default=False)
+
+ (options, args) = parser.parse_args()
+
+ script_name = os.path.basename(sys.argv[0])
+
+ if len(args) == 0:
+ print >> sys.stderr, "%s: Error: No xpi file specified." % (script_name)
+ sys.exit(COMMAND_LINE_SYNTAX_ERROR)
+ elif len(args) > 1:
+ print >> sys.stderr, "%s: Error: Multiple xpi files specified: %s" % \
+ (script_name, ", ".join(args))
+ sys.exit(COMMAND_LINE_SYNTAX_ERROR)
+
+ if options.verbose:
+ print script_name + ": Install %s into package %s." % \
+ (args[0], options.package)
+
+ install_xpi(script_name, options.package, args[0], options.exclude,
+ options.install_dir, set(options.links),
+ options.correct_permissions, options.remove_licenses,
+ options.system_prefs, options.verbose)
+
+if __name__ == "__main__":
+ main()