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