Package paramiko :: Module message
[frames] | no frames]

Source Code for Module paramiko.message

  1  # Copyright (C) 2003-2007  Robey Pointer <robeypointer@gmail.com> 
  2  # 
  3  # This file is part of paramiko. 
  4  # 
  5  # Paramiko is free software; you can redistribute it and/or modify it under the 
  6  # terms of the GNU Lesser General Public License as published by the Free 
  7  # Software Foundation; either version 2.1 of the License, or (at your option) 
  8  # any later version. 
  9  # 
 10  # Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY 
 11  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 
 12  # A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more 
 13  # details. 
 14  # 
 15  # You should have received a copy of the GNU Lesser General Public License 
 16  # along with Paramiko; if not, write to the Free Software Foundation, Inc., 
 17  # 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. 
 18   
 19  """ 
 20  Implementation of an SSH2 "message". 
 21  """ 
 22   
 23  import struct 
 24  import cStringIO 
 25   
 26  from paramiko import util 
 27   
 28   
29 -class Message (object):
30 """ 31 An SSH2 I{Message} is a stream of bytes that encodes some combination of 32 strings, integers, bools, and infinite-precision integers (known in python 33 as I{long}s). This class builds or breaks down such a byte stream. 34 35 Normally you don't need to deal with anything this low-level, but it's 36 exposed for people implementing custom extensions, or features that 37 paramiko doesn't support yet. 38 """ 39
40 - def __init__(self, content=None):
41 """ 42 Create a new SSH2 Message. 43 44 @param content: the byte stream to use as the Message content (passed 45 in only when decomposing a Message). 46 @type content: string 47 """ 48 if content != None: 49 self.packet = cStringIO.StringIO(content) 50 else: 51 self.packet = cStringIO.StringIO()
52
53 - def __str__(self):
54 """ 55 Return the byte stream content of this Message, as a string. 56 57 @return: the contents of this Message. 58 @rtype: string 59 """ 60 return self.packet.getvalue()
61
62 - def __repr__(self):
63 """ 64 Returns a string representation of this object, for debugging. 65 66 @rtype: string 67 """ 68 return 'paramiko.Message(' + repr(self.packet.getvalue()) + ')'
69
70 - def rewind(self):
71 """ 72 Rewind the message to the beginning as if no items had been parsed 73 out of it yet. 74 """ 75 self.packet.seek(0)
76
77 - def get_remainder(self):
78 """ 79 Return the bytes of this Message that haven't already been parsed and 80 returned. 81 82 @return: a string of the bytes not parsed yet. 83 @rtype: string 84 """ 85 position = self.packet.tell() 86 remainder = self.packet.read() 87 self.packet.seek(position) 88 return remainder
89
90 - def get_so_far(self):
91 """ 92 Returns the bytes of this Message that have been parsed and returned. 93 The string passed into a Message's constructor can be regenerated by 94 concatenating C{get_so_far} and L{get_remainder}. 95 96 @return: a string of the bytes parsed so far. 97 @rtype: string 98 """ 99 position = self.packet.tell() 100 self.rewind() 101 return self.packet.read(position)
102
103 - def get_bytes(self, n):
104 """ 105 Return the next C{n} bytes of the Message, without decomposing into 106 an int, string, etc. Just the raw bytes are returned. 107 108 @return: a string of the next C{n} bytes of the Message, or a string 109 of C{n} zero bytes, if there aren't C{n} bytes remaining. 110 @rtype: string 111 """ 112 b = self.packet.read(n) 113 if len(b) < n: 114 return b + '\x00' * (n - len(b)) 115 return b
116
117 - def get_byte(self):
118 """ 119 Return the next byte of the Message, without decomposing it. This 120 is equivalent to L{get_bytes(1)<get_bytes>}. 121 122 @return: the next byte of the Message, or C{'\000'} if there aren't 123 any bytes remaining. 124 @rtype: string 125 """ 126 return self.get_bytes(1)
127
128 - def get_boolean(self):
129 """ 130 Fetch a boolean from the stream. 131 132 @return: C{True} or C{False} (from the Message). 133 @rtype: bool 134 """ 135 b = self.get_bytes(1) 136 return b != '\x00'
137
138 - def get_int(self):
139 """ 140 Fetch an int from the stream. 141 142 @return: a 32-bit unsigned integer. 143 @rtype: int 144 """ 145 return struct.unpack('>I', self.get_bytes(4))[0]
146
147 - def get_int64(self):
148 """ 149 Fetch a 64-bit int from the stream. 150 151 @return: a 64-bit unsigned integer. 152 @rtype: long 153 """ 154 return struct.unpack('>Q', self.get_bytes(8))[0]
155
156 - def get_mpint(self):
157 """ 158 Fetch a long int (mpint) from the stream. 159 160 @return: an arbitrary-length integer. 161 @rtype: long 162 """ 163 return util.inflate_long(self.get_string())
164
165 - def get_string(self):
166 """ 167 Fetch a string from the stream. This could be a byte string and may 168 contain unprintable characters. (It's not unheard of for a string to 169 contain another byte-stream Message.) 170 171 @return: a string. 172 @rtype: string 173 """ 174 return self.get_bytes(self.get_int())
175
176 - def get_list(self):
177 """ 178 Fetch a list of strings from the stream. These are trivially encoded 179 as comma-separated values in a string. 180 181 @return: a list of strings. 182 @rtype: list of strings 183 """ 184 return self.get_string().split(',')
185
186 - def add_bytes(self, b):
187 """ 188 Write bytes to the stream, without any formatting. 189 190 @param b: bytes to add 191 @type b: str 192 """ 193 self.packet.write(b) 194 return self
195
196 - def add_byte(self, b):
197 """ 198 Write a single byte to the stream, without any formatting. 199 200 @param b: byte to add 201 @type b: str 202 """ 203 self.packet.write(b) 204 return self
205
206 - def add_boolean(self, b):
207 """ 208 Add a boolean value to the stream. 209 210 @param b: boolean value to add 211 @type b: bool 212 """ 213 if b: 214 self.add_byte('\x01') 215 else: 216 self.add_byte('\x00') 217 return self
218
219 - def add_int(self, n):
220 """ 221 Add an integer to the stream. 222 223 @param n: integer to add 224 @type n: int 225 """ 226 self.packet.write(struct.pack('>I', n)) 227 return self
228
229 - def add_int64(self, n):
230 """ 231 Add a 64-bit int to the stream. 232 233 @param n: long int to add 234 @type n: long 235 """ 236 self.packet.write(struct.pack('>Q', n)) 237 return self
238
239 - def add_mpint(self, z):
240 """ 241 Add a long int to the stream, encoded as an infinite-precision 242 integer. This method only works on positive numbers. 243 244 @param z: long int to add 245 @type z: long 246 """ 247 self.add_string(util.deflate_long(z)) 248 return self
249
250 - def add_string(self, s):
251 """ 252 Add a string to the stream. 253 254 @param s: string to add 255 @type s: str 256 """ 257 self.add_int(len(s)) 258 self.packet.write(s) 259 return self
260
261 - def add_list(self, l):
262 """ 263 Add a list of strings to the stream. They are encoded identically to 264 a single string of values separated by commas. (Yes, really, that's 265 how SSH2 does it.) 266 267 @param l: list of strings to add 268 @type l: list(str) 269 """ 270 self.add_string(','.join(l)) 271 return self
272
273 - def _add(self, i):
274 if type(i) is str: 275 return self.add_string(i) 276 elif type(i) is int: 277 return self.add_int(i) 278 elif type(i) is long: 279 if i > 0xffffffffL: 280 return self.add_mpint(i) 281 else: 282 return self.add_int(i) 283 elif type(i) is bool: 284 return self.add_boolean(i) 285 elif type(i) is list: 286 return self.add_list(i) 287 else: 288 raise Exception('Unknown type')
289
290 - def add(self, *seq):
291 """ 292 Add a sequence of items to the stream. The values are encoded based 293 on their type: str, int, bool, list, or long. 294 295 @param seq: the sequence of items 296 @type seq: sequence 297 298 @bug: longs are encoded non-deterministically. Don't use this method. 299 """ 300 for item in seq: 301 self._add(item)
302