1 # -*- coding: iso-8859-1 -*- 2 """ 3 getfiles - Obtain files using MoinMessage 4 5 @copyright: 2013, 2014 by Paul Boddie <paul@boddie.org.uk> 6 @license: GNU GPL (v2 or later), see COPYING.txt for details. 7 """ 8 9 from MoinMessage import * 10 from email.mime.application import MIMEApplication 11 from email.mime.text import MIMEText 12 from email.parser import Parser 13 from os.path import join, exists 14 from os import makedirs 15 import sys 16 17 def writefile(filename, s): 18 f = open(filename, "wb") 19 try: 20 f.write(s) 21 finally: 22 f.close() 23 24 if __name__ == "__main__": 25 try: 26 service = sys.argv[1] 27 signer = sys.argv[2] 28 url = sys.argv[3] 29 sender = sys.argv[4] 30 datetime = sys.argv[5] 31 target_dir = sys.argv[6] 32 except IndexError: 33 print >>sys.stderr, """\ 34 Need a service key identifier, signing key identifier, the repository URL, 35 sender identifier, the datetime of the last resources retrieved, and the target 36 directory as arguments to this program. 37 """ 38 sys.exit(1) 39 40 # Bundle files into a message. 41 42 message = Message() 43 44 part = MIMEText("\n".join([sender, datetime]), "moinmessage-request") 45 message.add_update(part) 46 47 # Get the e-mail message itself. 48 49 message = message.get_payload() 50 51 # Encrypt, sign and send the message. 52 53 gpg = GPG() 54 message = gpg.encryptMessage(message, service) 55 message = gpg.signMessage(message, signer) 56 resp = sendMessageForReading(message, url) 57 58 # Verify, decrypt and unpack the message. 59 60 try: 61 if not is_signed(message): 62 print >>sys.stderr, "Incoming message was not signed." 63 sys.exit(1) 64 65 message = Parser().parse(resp) 66 fingerprint, identity, content = gpg.verifyMessage(message) 67 68 if is_encrypted(content): 69 text = gpg.decryptMessage(content) 70 content = Parser().parsestr(text) 71 72 except MoinMessageDecodingError: 73 print >>sys.stderr, "Incoming message was improperly encoded." 74 sys.exit(1) 75 76 except MoinMessageError, exc: 77 print >>sys.stderr, "Incoming message was not verifiable: %s" % exc 78 sys.exit(1) 79 80 message = Message() 81 message.handle_message(content) 82 83 for part in message.updates: 84 85 # Use the "outer" filename to determine a directory for the retrieved 86 # file, even though the eventual filename in the directory may be 87 # different. 88 89 filename = part["Content-Disposition"] 90 directory, leafname = filename.split("/") 91 92 # The data may be encrypted. 93 94 try: 95 data = gpg.decryptMessage(part) 96 except MoinMessageError: 97 print >>sys.stderr, "Message part was not decrypted." 98 data = part.get_payload(decode=True) 99 100 # Parse the decoded data. 101 102 content = Parser().parsestr(data) 103 104 if content.is_multipart(): 105 files = content.get_payload() 106 else: 107 files = [content] 108 109 # Treat each part of the verified, possibly encrypted message as a file. 110 111 for file in files: 112 data = file.get_payload(decode=True) 113 114 realname = file.get("Content-Disposition") 115 filename = join(directory, realname or leafname) 116 117 dirpath = join(target_dir, directory) 118 if not exists(dirpath): 119 makedirs(dirpath) 120 writefile(join(target_dir, filename), data) 121 122 # vim: tabstop=4 expandtab shiftwidth=4