helper_msgcoding.py.bak
1 """ 2 Message encoding end decoding functions 3 """ 4 5 import string 6 import zlib 7 8 import messagetypes 9 from bmconfigparser import config 10 from debug import logger 11 from tr import _translate 12 13 try: 14 import msgpack 15 except ImportError: 16 try: 17 import umsgpack as msgpack 18 except ImportError: 19 import fallback.umsgpack.umsgpack as msgpack 20 21 BITMESSAGE_ENCODING_IGNORE = 0 22 BITMESSAGE_ENCODING_TRIVIAL = 1 23 BITMESSAGE_ENCODING_SIMPLE = 2 24 BITMESSAGE_ENCODING_EXTENDED = 3 25 26 27 class MsgEncodeException(Exception): 28 """Exception during message encoding""" 29 pass 30 31 32 class MsgDecodeException(Exception): 33 """Exception during message decoding""" 34 pass 35 36 37 class DecompressionSizeException(MsgDecodeException): 38 # pylint: disable=super-init-not-called 39 """Decompression resulted in too much data (attack protection)""" 40 def __init__(self, size): 41 self.size = size 42 43 44 class MsgEncode(object): 45 """Message encoder class""" 46 def __init__(self, message, encoding=BITMESSAGE_ENCODING_SIMPLE): 47 self.data = None 48 self.encoding = encoding 49 self.length = 0 50 if self.encoding == BITMESSAGE_ENCODING_EXTENDED: 51 self.encodeExtended(message) 52 elif self.encoding == BITMESSAGE_ENCODING_SIMPLE: 53 self.encodeSimple(message) 54 elif self.encoding == BITMESSAGE_ENCODING_TRIVIAL: 55 self.encodeTrivial(message) 56 else: 57 raise MsgEncodeException("Unknown encoding %i" % (encoding)) 58 59 def encodeExtended(self, message): 60 """Handle extended encoding""" 61 try: 62 msgObj = messagetypes.message.Message() 63 self.data = zlib.compress(msgpack.dumps(msgObj.encode(message)), 9) 64 except zlib.error: 65 logger.error("Error compressing message") 66 raise MsgEncodeException("Error compressing message") 67 except msgpack.exceptions.PackException: 68 logger.error("Error msgpacking message") 69 raise MsgEncodeException("Error msgpacking message") 70 self.length = len(self.data) 71 72 def encodeSimple(self, message): 73 """Handle simple encoding""" 74 self.data = 'Subject:%(subject)s\nBody:%(body)s' % message 75 self.length = len(self.data) 76 77 def encodeTrivial(self, message): 78 """Handle trivial encoding""" 79 self.data = message['body'] 80 self.length = len(self.data) 81 82 83 class MsgDecode(object): 84 """Message decoder class""" 85 def __init__(self, encoding, data): 86 self.encoding = encoding 87 if self.encoding == BITMESSAGE_ENCODING_EXTENDED: 88 self.decodeExtended(data) 89 elif self.encoding in ( 90 BITMESSAGE_ENCODING_SIMPLE, BITMESSAGE_ENCODING_TRIVIAL): 91 self.decodeSimple(data) 92 else: 93 self.body = _translate( 94 "MsgDecode", 95 "The message has an unknown encoding.\n" 96 "Perhaps you should upgrade Bitmessage.") 97 self.subject = _translate("MsgDecode", "Unknown encoding") 98 99 def decodeExtended(self, data): 100 """Handle extended encoding""" 101 dc = zlib.decompressobj() 102 tmp = "" 103 while len(tmp) <= config.safeGetInt("zlib", "maxsize"): 104 try: 105 got = dc.decompress( 106 data, config.safeGetInt("zlib", "maxsize") 107 + 1 - len(tmp)) 108 # EOF 109 if got == "": 110 break 111 tmp += got 112 data = dc.unconsumed_tail 113 except zlib.error: 114 logger.error("Error decompressing message") 115 raise MsgDecodeException("Error decompressing message") 116 else: 117 raise DecompressionSizeException(len(tmp)) 118 119 try: 120 tmp = msgpack.loads(tmp) 121 except (msgpack.exceptions.UnpackException, 122 msgpack.exceptions.ExtraData): 123 logger.error("Error msgunpacking message") 124 raise MsgDecodeException("Error msgunpacking message") 125 126 try: 127 msgType = tmp[""] 128 except KeyError: 129 logger.error("Message type missing") 130 raise MsgDecodeException("Message type missing") 131 132 msgObj = messagetypes.constructObject(tmp) 133 if msgObj is None: 134 raise MsgDecodeException("Malformed message") 135 try: 136 msgObj.process() 137 except: # noqa:E722 138 raise MsgDecodeException("Malformed message") 139 if msgType == "message": 140 self.subject = msgObj.subject 141 self.body = msgObj.body 142 143 def decodeSimple(self, data): 144 """Handle simple encoding""" 145 bodyPositionIndex = string.find(data, '\nBody:') 146 if bodyPositionIndex > 1: 147 subject = data[8:bodyPositionIndex] 148 # Only save and show the first 500 characters of the subject. 149 # Any more is probably an attack. 150 subject = subject[:500] 151 body = data[bodyPositionIndex + 6:] 152 else: 153 subject = '' 154 body = data 155 # Throw away any extra lines (headers) after the subject. 156 if subject: 157 subject = subject.splitlines()[0] 158 self.subject = subject 159 self.body = body