[project @ Arch-1:robey@lag.net--2003-public%secsh--dev--1.0--patch-24]
document more of Message; add get_int64 all of the get_* methods are now documented, but there's a bit more to do. get_int64 added for eventual sftp support.
This commit is contained in:
parent
35ed103572
commit
ea8c1378e8
|
@ -26,29 +26,71 @@ import string, types, struct
|
|||
from util import inflate_long, deflate_long
|
||||
|
||||
|
||||
class Message(object):
|
||||
"represents the encoding of an SSH2 message"
|
||||
class Message (object):
|
||||
"""
|
||||
An SSH2 I{Message} is a stream of bytes that encodes some combination of
|
||||
strings, integers, bools, and infinite-precision integers (known in python
|
||||
as I{long}s). This class builds or breaks down such a byte stream.
|
||||
"""
|
||||
|
||||
def __init__(self, content=''):
|
||||
"""
|
||||
Create a new SSH2 Message.
|
||||
|
||||
@param content: the byte stream to use as the Message content (usually
|
||||
passed in only when decomposing a Message).
|
||||
@type content: string
|
||||
"""
|
||||
self.packet = content
|
||||
self.idx = 0
|
||||
self.seqno = -1
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
Return the byte stream content of this Message, as a string.
|
||||
|
||||
@return: the contents of this Message.
|
||||
@rtype: string
|
||||
"""
|
||||
return self.packet
|
||||
|
||||
def __repr__(self):
|
||||
"""
|
||||
Returns a string representation of this object, for debugging.
|
||||
|
||||
@rtype: string
|
||||
"""
|
||||
return 'Message(' + repr(self.packet) + ')'
|
||||
|
||||
def get_remainder(self):
|
||||
"remaining bytes still unparsed"
|
||||
"""
|
||||
Return the bytes of this Message that haven't already been parsed and
|
||||
returned.
|
||||
|
||||
@return: a string of the bytes not parsed yet.
|
||||
@rtype: string
|
||||
"""
|
||||
return self.packet[self.idx:]
|
||||
|
||||
def get_so_far(self):
|
||||
"bytes that have been parsed"
|
||||
"""
|
||||
Returns the bytes of this Message that have been parsed and returned.
|
||||
The string passed into a Message's constructor can be regenerated by
|
||||
concatenating C{get_so_far} and L{get_remainder}.
|
||||
|
||||
@return: a string of the bytes parsed so far.
|
||||
@rtype: string
|
||||
"""
|
||||
return self.packet[:self.idx]
|
||||
|
||||
def get_bytes(self, n):
|
||||
"""
|
||||
Return the next C{n} bytes of the Message, without decomposing into
|
||||
an int, string, etc. Just the raw bytes are returned.
|
||||
|
||||
@return: a string of the next C{n} bytes of the Message, or a string
|
||||
of C{n} zero bytes, if there aren't C{n} bytes remaining.
|
||||
@rtype: string
|
||||
"""
|
||||
if self.idx + n > len(self.packet):
|
||||
return '\x00'*n
|
||||
b = self.packet[self.idx:self.idx+n]
|
||||
|
@ -56,16 +98,36 @@ class Message(object):
|
|||
return b
|
||||
|
||||
def get_byte(self):
|
||||
"""
|
||||
Return the next byte of the Message, without decomposing it. This
|
||||
is equivalent to L{get_bytes(1)<get_bytes>}.
|
||||
|
||||
@return: the next byte of the Message, or C{'\000'} if there aren't
|
||||
any bytes remaining.
|
||||
@rtype: string
|
||||
"""
|
||||
return self.get_bytes(1)
|
||||
|
||||
def get_boolean(self):
|
||||
"""
|
||||
Fetch a boolean from the stream.
|
||||
|
||||
@return: C{True} or C{False} (from the Message).
|
||||
@rtype: bool
|
||||
"""
|
||||
b = self.get_bytes(1)
|
||||
if b == '\x00':
|
||||
return 0
|
||||
return False
|
||||
else:
|
||||
return 1
|
||||
return True
|
||||
|
||||
def get_int(self):
|
||||
"""
|
||||
Fetch an int from the stream.
|
||||
|
||||
@return: a 32-bit unsigned integer.
|
||||
@rtype: int
|
||||
"""
|
||||
x = self.packet
|
||||
i = self.idx
|
||||
if i + 4 > len(x):
|
||||
|
@ -74,10 +136,39 @@ class Message(object):
|
|||
self.idx = i+4
|
||||
return n
|
||||
|
||||
def get_int64(self):
|
||||
"""
|
||||
Fetch a 64-bit int from the stream.
|
||||
|
||||
@return: a 64-bit unsigned integer.
|
||||
@rtype: long
|
||||
"""
|
||||
x = self.packet
|
||||
i = self.idx
|
||||
if i + 8 > len(x):
|
||||
return 0L
|
||||
n = struct.unpack('>Q', x[i:i+8])[0]
|
||||
self.idx += 8
|
||||
return n
|
||||
|
||||
def get_mpint(self):
|
||||
"""
|
||||
Fetch a long int (mpint) from the stream.
|
||||
|
||||
@return: an arbitrary-length integer.
|
||||
@rtype: long
|
||||
"""
|
||||
return inflate_long(self.get_string())
|
||||
|
||||
def get_string(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
|
||||
"""
|
||||
l = self.get_int()
|
||||
if self.idx + l > len(self.packet):
|
||||
return ''
|
||||
|
@ -86,6 +177,13 @@ class Message(object):
|
|||
return str
|
||||
|
||||
def get_list(self):
|
||||
"""
|
||||
Fetch a list of strings from the stream. These are trivially encoded
|
||||
as comma-separated values in a string.
|
||||
|
||||
@return: a list of strings.
|
||||
@type: list of strings
|
||||
"""
|
||||
str = self.get_string()
|
||||
l = string.split(str, ',')
|
||||
return l
|
||||
|
|
Loading…
Reference in New Issue