summaryrefslogtreecommitdiff
path: root/paramiko/message.py
diff options
context:
space:
mode:
authorJeff Forcier <jeff@bitprophet.org>2014-03-05 17:03:37 -0800
committerJeff Forcier <jeff@bitprophet.org>2014-03-05 17:03:37 -0800
commitb2be63ec623b5944f9b84cac8b8f41aeb2b42fb7 (patch)
tree389e17b0c08cd34872a2e3afbc34860ab44fb3ed /paramiko/message.py
parentbd61c7c0a9a4a2020d0acfb6a01e9ec85bb43b8e (diff)
parentae078f51d622931954e47e78029a889c4e721a05 (diff)
downloadparamiko-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.py103
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):
"""