1 # -*- coding: iso-8859-1 -*- 2 """ 3 MoinMoin - MoinMessage library 4 5 @copyright: 2012 by Paul Boddie <paul@boddie.org.uk> 6 @license: GNU GPL (v2 or later), see COPYING.txt for details. 7 """ 8 9 from MoinMoin.log import getLogger 10 from email import message_from_string 11 from email.encoders import encode_noop 12 from email.mime.multipart import MIMEMultipart 13 from email.mime.application import MIMEApplication 14 from email.mime.base import MIMEBase 15 from email.mime.text import MIMEText 16 from subprocess import Popen, PIPE 17 import httplib 18 19 class Message: 20 21 "An update message." 22 23 def __init__(self): 24 self.updates = [] 25 26 def add_update(self, alternatives): 27 if len(alternatives) > 1: 28 part = MIMEMultipart() 29 for alternative in alternatives: 30 part.attach(alternative) 31 self.updates.append(part) 32 else: 33 self.updates.append(alternatives[0]) 34 35 def get_payload(self): 36 if len(self.updates) == 1: 37 message = self.updates[0] 38 else: 39 message = MIMEMultipart() 40 message.add_header("Update-Type", "collection") 41 for update in self.updates: 42 message.attach(update) 43 44 return message 45 46 class MoinMessageError(Exception): 47 pass 48 49 def gpg(args, text): 50 51 "Invoke gpg with the given 'args', supplying the given 'text'." 52 53 cmd = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) 54 55 cmd.stdin.write(text) 56 cmd.stdin.close() 57 58 errors = cmd.stderr.read() 59 if errors: 60 getLogger(__name__).warning(errors) 61 62 try: 63 text = cmd.stdout.read() 64 65 # Test for a zero result. 66 67 if not cmd.wait(): 68 return text 69 else: 70 raise MoinMessageError, errors 71 72 finally: 73 cmd.stdout.close() 74 cmd.stderr.close() 75 76 def signMessage(message, keyid): 77 78 """ 79 Return a signed 'message' using the given 'keyid'. 80 """ 81 82 text = message.as_string() 83 signature = gpg(["gpg", "--armor", "-u", keyid, "--detach-sig"], text) 84 85 # Make the container for the message. 86 87 signed_message = MIMEMultipart("signed", protocol="application/pgp-signature") 88 signed_message.attach(message) 89 90 signature_part = MIMEBase("application", "pgp-signature") 91 signature_part.set_payload(signature) 92 signed_message.attach(signature_part) 93 94 return signed_message 95 96 def encryptMessage(message, keyid): 97 98 """ 99 Return an encrypted 'message' using the given 'keyid'. 100 """ 101 102 text = message.as_string() 103 encrypted = gpg(["gpg", "--armor", "-r", keyid, "--encrypt", "--trust-model", "always"], text) 104 105 # Make the container for the message. 106 107 encrypted_message = MIMEMultipart("encrypted", protocol="application/pgp-encrypted") 108 109 # For encrypted content, add the declaration and content. 110 111 declaration = MIMEBase("application", "pgp-encrypted") 112 declaration.set_payload("Version: 1") 113 encrypted_message.attach(declaration) 114 115 content = MIMEApplication(encrypted, "octet-stream", encode_noop) 116 encrypted_message.attach(content) 117 118 return encrypted_message 119 120 def sendMessage(message, host, path): 121 122 "Send 'message' to the given 'host' using the specified URL 'path'." 123 124 text = message.as_string() 125 126 req = httplib.HTTPConnection(host) 127 req.request("PUT", path, text) # {"Content-Length" : len(text)} 128 resp = req.getresponse() 129 return resp.read() 130 131 # vim: tabstop=4 expandtab shiftwidth=4