diff options
author | Jeff Forcier <jeff@bitprophet.org> | 2014-03-05 17:03:37 -0800 |
---|---|---|
committer | Jeff Forcier <jeff@bitprophet.org> | 2014-03-05 17:03:37 -0800 |
commit | b2be63ec623b5944f9b84cac8b8f41aeb2b42fb7 (patch) | |
tree | 389e17b0c08cd34872a2e3afbc34860ab44fb3ed /paramiko/message.py | |
parent | bd61c7c0a9a4a2020d0acfb6a01e9ec85bb43b8e (diff) | |
parent | ae078f51d622931954e47e78029a889c4e721a05 (diff) | |
download | paramiko-b2be63ec623b5944f9b84cac8b8f41aeb2b42fb7.tar.gz |
Merge remote-tracking branch 'scottkmaxwell/py3-support-without-py25' into python3
Conflicts:
dev-requirements.txt
paramiko/__init__.py
paramiko/file.py
paramiko/hostkeys.py
paramiko/message.py
paramiko/proxy.py
paramiko/server.py
paramiko/transport.py
paramiko/util.py
paramiko/win_pageant.py
setup.py
Diffstat (limited to 'paramiko/message.py')
-rw-r--r-- | paramiko/message.py | 103 |
1 files changed, 79 insertions, 24 deletions
diff --git a/paramiko/message.py b/paramiko/message.py index 213b2e79..a487f2e8 100644 --- a/paramiko/message.py +++ b/paramiko/message.py @@ -21,9 +21,9 @@ Implementation of an SSH2 "message". """ import struct -import cStringIO from paramiko import util +from paramiko.common import * class Message (object): @@ -37,6 +37,8 @@ class Message (object): paramiko doesn't support yet. """ + big_int = long(0xff000000) + def __init__(self, content=None): """ Create a new SSH2 message. @@ -46,15 +48,15 @@ class Message (object): decomposing a message). """ if content != None: - self.packet = cStringIO.StringIO(content) + self.packet = BytesIO(content) else: - self.packet = cStringIO.StringIO() + self.packet = BytesIO() def __str__(self): """ - Return the byte stream content of this message, as a string. + Return the byte stream content of this message, as a string/bytes obj. """ - return self.packet.getvalue() + return self.asbytes() def __repr__(self): """ @@ -62,6 +64,15 @@ class Message (object): """ return 'paramiko.Message(' + repr(self.packet.getvalue()) + ')' + def asbytes(self): + """ + Return the byte stream content of this Message, as bytes. + + @return: the contents of this Message. + @rtype: bytes + """ + return self.packet.getvalue() + def rewind(self): """ Rewind the message to the beginning as if no items had been parsed @@ -99,7 +110,7 @@ class Message (object): b = self.packet.read(n) max_pad_size = 1<<20 # Limit padding to 1 MB if len(b) < n and n < max_pad_size: - return b + '\x00' * (n - len(b)) + return b + zero_byte * (n - len(b)) return b def get_byte(self): @@ -118,7 +129,7 @@ class Message (object): Fetch a boolean from the stream. """ b = self.get_bytes(1) - return b != '\x00' + return b != zero_byte def get_int(self): """ @@ -126,6 +137,19 @@ class Message (object): :return: a 32-bit unsigned `int`. """ + byte = self.get_bytes(1) + if byte == max_byte: + return util.inflate_long(self.get_binary()) + byte += self.get_bytes(3) + return struct.unpack('>I', byte)[0] + + def get_size(self): + """ + Fetch an int from the stream. + + @return: a 32-bit unsigned integer. + @rtype: int + """ return struct.unpack('>I', self.get_bytes(4))[0] def get_int64(self): @@ -142,7 +166,7 @@ class Message (object): :return: an arbitrary-length integer (`long`). """ - return util.inflate_long(self.get_string()) + return util.inflate_long(self.get_binary()) def get_string(self): """ @@ -150,7 +174,30 @@ class Message (object): contain unprintable characters. (It's not unheard of for a string to contain another byte-stream message.) """ - return self.get_bytes(self.get_int()) + return self.get_bytes(self.get_size()) + + def get_text(self): + """ + Fetch a string from the stream. This could be a byte string and may + contain unprintable characters. (It's not unheard of for a string to + contain another byte-stream Message.) + + @return: a string. + @rtype: string + """ + return u(self.get_bytes(self.get_size())) + #return self.get_bytes(self.get_size()) + + def get_binary(self): + """ + Fetch a string from the stream. This could be a byte string and may + contain unprintable characters. (It's not unheard of for a string to + contain another byte-stream Message.) + + @return: a string. + @rtype: string + """ + return self.get_bytes(self.get_size()) def get_list(self): """ @@ -158,7 +205,7 @@ class Message (object): These are trivially encoded as comma-separated values in a string. """ - return self.get_string().split(',') + return self.get_text().split(',') def add_bytes(self, b): """ @@ -185,9 +232,19 @@ class Message (object): :param bool b: boolean value to add """ if b: - self.add_byte('\x01') + self.packet.write(one_byte) else: - self.add_byte('\x00') + self.packet.write(zero_byte) + return self + + def add_size(self, n): + """ + Add an integer to the stream. + + @param n: integer to add + @type n: int + """ + self.packet.write(struct.pack('>I', n)) return self def add_int(self, n): @@ -196,6 +253,10 @@ class Message (object): :param int n: integer to add """ + if n >= Message.big_int: + self.packet.write(max_byte) + self.add_string(util.deflate_long(n)) + else: self.packet.write(struct.pack('>I', n)) return self @@ -224,7 +285,8 @@ class Message (object): :param str s: string to add """ - self.add_int(len(s)) + s = asbytes(s) + self.add_size(len(s)) self.packet.write(s) return self @@ -240,21 +302,14 @@ class Message (object): return self def _add(self, i): - if type(i) is str: - return self.add_string(i) - elif type(i) is int: - return self.add_int(i) - elif type(i) is long: - if i > 0xffffffffL: - return self.add_mpint(i) - else: - return self.add_int(i) - elif type(i) is bool: + if type(i) is bool: return self.add_boolean(i) + elif isinstance(i, integer_types): + return self.add_int(i) elif type(i) is list: return self.add_list(i) else: - raise Exception('Unknown type') + return self.add_string(i) def add(self, *seq): """ |