--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/releasing/blocks/framework/src/Blocks/gpg.py Thu Sep 02 15:02:14 2010 +0800
@@ -0,0 +1,132 @@
+#
+# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+# Wrapper for gpg
+#
+
+''' gpg command wrapper '''
+
+import sys
+from subprocess import Popen, PIPE
+from collections import namedtuple
+import logging
+
+_GNUPGPREFIX = "[GNUPG:] "
+_GNUPGGOODSIG = "GOODSIG"
+_GNUPGBADSIG = "BADSIG"
+_GNUPGNOPUBKEY = "NO_PUBKEY"
+_GNUPGKEYEXPIRED = "KEYEXPIRED"
+_GNUPGREVKEYSIG = "REVKEYSIG"
+
+class GpgStatusCode(object):
+ VERIFIED, BADSIG, NO_PUBKEY, KEYEXPIRED, REVKEYSIG = range(5)
+
+VerifyInfo = namedtuple("VerifyInfo", "name")
+VerifyStatus = namedtuple("VerifyStatus", "code, info")
+
+#define GNUPGVALIDSIG "[GNUPG:] VALIDSIG"
+#define GNUPGNODATA "[GNUPG:] NODATA"
+
+class GpgError(Exception):
+ """ Gpg exited with error """
+ def __init__(self, errorcode, output):
+ Exception.__init__(self, "Gpg failed with error code %s" % errorcode)
+ self.errorcode = errorcode
+ self.output = output.strip()
+
+def sign(sourcePath, outputPath, homedir=None, batch=False, passfile=None):
+ '''
+ Create a gpg signature of a file.
+
+ sign() has two modes: file and pipe. File: Specify sourcePath and outputPath
+ as strings to create signature of file sourcePath in file outputPath. Pipe:
+ Specify sourcePath as readable object and outputPath as None. The signature
+ is the return value.
+
+ Use a combination of batch, homedir and passfile to eliminate the need for
+ interaction.
+
+ File mode::
+ gpg.sign("/my/file", "/my/file.gpg")
+
+ Pipe mode without interaction::
+ f = open("/my/file", "rb")
+ key = gpg.sign(f, None, "/my/passwordless/keydir", True)
+ f.close()
+
+ @param sourcePath: Path of the file to sign, or pipe to read the file from
+ @type sourcePath: String or file-like object
+ @param outputPath: Path to write signature to, or None in pipe mode
+ @type outputPath: String or None
+ @param homedir: Directory to read keyfile from
+ @type homedir: String
+ @param batch: Whether to use I{--batch} with gpg command
+ @type batch: Boolean
+ @param passfile: Optional passphrase file to use with the key
+ @type passfile: String
+ '''
+ cmdstr = "gpg -abs"
+ if homedir:
+ cmdstr += ' --homedir "%s"' % homedir
+ if batch:
+ cmdstr += ' --batch'
+ pStdin = None
+ else:
+ pStdin = sys.stdin
+ if passfile:
+ cmdstr += ' --passphrase-file "%s"' % passfile
+
+ if isinstance(outputPath, basestring) and isinstance(sourcePath, basestring):
+ cmdstr += ' -o "%s" "%s"' % (outputPath, sourcePath)
+ p = Popen(cmdstr, shell=True, stdin=pStdin, stdout=PIPE, stderr=PIPE)
+ else:
+ assert (sourcePath and hasattr(sourcePath, "read")), "sourcePath not file-like object!"
+ p = Popen(cmdstr, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
+ blockSize = 32*1024
+ buf = sourcePath.read(blockSize)
+ while buf:
+ try:
+ p.stdin.write(buf)
+ except IOError:
+ break
+ buf = sourcePath.read(blockSize)
+ (stdoutput, stderror) = p.communicate()
+ if stderror is None:
+ stderror = ""
+ if p.returncode != 0:
+ raise GpgError(p.returncode, stderror)
+ return stdoutput
+
+def verify(signFilePath, signedFilePath, homedir=None):
+ cmdstr = ('gpgv --keyring pubring.gpg --ignore-time-conflict --status-fd 2 %s "%s" "%s"' %
+ ('--homedir "%s"' % homedir if homedir else "", signFilePath, signedFilePath))
+ logging.debug("GPG running: %s", cmdstr)
+ p = Popen(cmdstr, shell=True, stdin=sys.stdin, stdout=PIPE, stderr=PIPE)
+ (stdoutput, stderror) = p.communicate()
+ logging.debug("GPG stdout: %s", stdoutput)
+ logging.debug("GPG stderror (status): %s", stderror)
+ for line in stderror.splitlines():
+ if line.startswith(_GNUPGPREFIX):
+ line = line.replace(_GNUPGPREFIX, "", 1)
+ (statusString, _, info) = line.partition(" ")
+ status = {_GNUPGGOODSIG: GpgStatusCode.VERIFIED,
+ _GNUPGBADSIG: GpgStatusCode.BADSIG,
+ _GNUPGNOPUBKEY: GpgStatusCode.NO_PUBKEY,
+ _GNUPGKEYEXPIRED: GpgStatusCode.KEYEXPIRED,
+ _GNUPGREVKEYSIG: GpgStatusCode.REVKEYSIG}.get(statusString)
+ if status is not None:
+ name = info.partition(" ")[2]
+ return VerifyStatus(status, VerifyInfo(name))
+ if p.returncode != 0:
+ raise GpgError(p.returncode, stdoutput)
\ No newline at end of file