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.text import MIMEText 11 from email.parser import Parser 12 from os.path import join, exists 13 from os import makedirs 14 from time import strftime 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 def decrypt(gpg, content): 25 if is_encrypted(content): 26 text = gpg.decryptMessage(content) 27 return Parser().parsestr(text) 28 else: 29 return content 30 31 if __name__ == "__main__": 32 try: 33 service = sys.argv[1] 34 signer = sys.argv[2] 35 url = sys.argv[3] 36 sender = sys.argv[4] 37 datetime = sys.argv[5] 38 target_dir = sys.argv[6] 39 except IndexError: 40 print >>sys.stderr, """\ 41 Need a service key identifier, signing key identifier, the repository URL, 42 sender identifier, the datetime of the last resources retrieved, and the target 43 directory as arguments to this program. 44 """ 45 sys.exit(1) 46 47 # Bundle files into a message. 48 49 message = Message() 50 51 commands = ["MBOX %s" % sender, "LAST %s" % datetime, "RETR"] 52 part = MIMEText("\n".join(commands), "x-moinmessage-fetch") 53 message.add_update(part) 54 55 # Get the e-mail message itself. 56 57 email_message = message.get_payload() 58 59 # Sign, encrypt and send the request. 60 61 gpg = GPG() 62 signed_message = gpg.signMessage(email_message, signer) 63 encrypted_message = gpg.encryptMessage(signed_message, service) 64 resp = sendMessageOpener(encrypted_message, url) 65 66 # Verify the response after possible transport encryption. 67 68 try: 69 message = Parser().parse(resp) 70 message = decrypt(gpg, message) 71 fingerprint, identity, content = gpg.verifyMessage(message) 72 73 except MoinMessageDecodingError: 74 print >>sys.stderr, "Incoming message was improperly encoded." 75 sys.exit(1) 76 77 except MoinMessageError, exc: 78 print >>sys.stderr, "Incoming message was not verifiable: %s" % exc 79 sys.exit(1) 80 81 message = Message() 82 message.handle_message(content) 83 84 for part in message.updates: 85 if part.get_content_type() == "text/x-moinmessage-fetch-result": 86 if part["Request-Status"] != "OK": 87 print part 88 else: 89 print part["Request-Type"] 90 continue 91 92 # Use the "outer" filename to determine a directory for the retrieved 93 # file, even though the eventual filename in the directory may be 94 # different. 95 96 timestamp = strftime("%Y-%m-%d_%H:%M:%S") 97 directory = part.get("Content-Disposition", timestamp) 98 99 # The retrieved content may be encrypted. 100 101 part = decrypt(gpg, part) 102 103 # The original sender may now be verified. 104 105 if is_signed(part): 106 fingerprint, identity, content = gpg.verifyMessage(part) 107 print >>sys.stderr, "Content signed by %s." % identity 108 109 if content.is_multipart(): 110 files = content.get_payload() 111 else: 112 files = [content] 113 114 # Treat each part of the verified, possibly encrypted message as a file. 115 116 for file in files: 117 data = file.get_payload(decode=True) 118 119 realname = file["Content-Disposition"] 120 filename = join(directory, realname) 121 122 dirpath = join(target_dir, directory) 123 if not exists(dirpath): 124 makedirs(dirpath) 125 writefile(join(target_dir, filename), data) 126 127 # vim: tabstop=4 expandtab shiftwidth=4