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 distributed 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   
 25  from paramiko import util 
 26  from paramiko.common import zero_byte, max_byte, one_byte, asbytes 
 27  from paramiko.py3compat import long, BytesIO, u, integer_types 
 28   
 29   
30 -class Message (object):
31 """ 32 An SSH2 message is a stream of bytes that encodes some combination of 33 strings, integers, bools, and infinite-precision integers (known in Python 34 as longs). This class builds or breaks down such a byte stream. 35 36 Normally you don't need to deal with anything this low-level, but it's 37 exposed for people implementing custom extensions, or features that 38 paramiko doesn't support yet. 39 """ 40 41 big_int = long(0xff000000) 42
43 - def __init__(self, content=None):
44 """ 45 Create a new SSH2 message. 46 47 :param str content: 48 the byte stream to use as the message content (passed in only when 49 decomposing a message). 50 """ 51 if content is not None: 52 self.packet = BytesIO(content) 53 else: 54 self.packet = BytesIO()
55
56 - def __str__(self):
57 """ 58 Return the byte stream content of this message, as a string/bytes obj. 59 """ 60 return self.asbytes()
61
62 - def __repr__(self):
63 """ 64 Returns a string representation of this object, for debugging. 65 """ 66 return 'paramiko.Message(' + repr(self.packet.getvalue()) + ')'
67
68 - def asbytes(self):
69 """ 70 Return the byte stream content of this Message, as bytes. 71 """ 72 return self.packet.getvalue()
73
74 - def rewind(self):
75 """ 76 Rewind the message to the beginning as if no items had been parsed 77 out of it yet. 78 """ 79 self.packet.seek(0)
80
81 - def get_remainder(self):
82 """ 83 Return the bytes (as a `str`) of this message that haven't already been 84 parsed and returned. 85 """ 86 position = self.packet.tell() 87 remainder = self.packet.read() 88 self.packet.seek(position) 89 return remainder
90
91 - def get_so_far(self):
92 """ 93 Returns the `str` bytes of this message that have been parsed and 94 returned. The string passed into a message's constructor can be 95 regenerated by concatenating ``get_so_far`` and `get_remainder`. 96 """ 97 position = self.packet.tell() 98 self.rewind() 99 return self.packet.read(position)
100
101 - def get_bytes(self, n):
102 """ 103 Return the next ``n`` bytes of the message (as a `str`), without 104 decomposing into an int, decoded string, etc. Just the raw bytes are 105 returned. Returns a string of ``n`` zero bytes if there weren't ``n`` 106 bytes remaining in the message. 107 """ 108 b = self.packet.read(n) 109 max_pad_size = 1 << 20 # Limit padding to 1 MB 110 if len(b) < n < max_pad_size: 111 return b + zero_byte * (n - len(b)) 112 return b
113
114 - def get_byte(self):
115 """ 116 Return the next byte of the message, without decomposing it. This 117 is equivalent to `get_bytes(1) <get_bytes>`. 118 119 :return: 120 the next (`str`) byte of the message, or ``'\000'`` if there aren't 121 any bytes remaining. 122 """ 123 return self.get_bytes(1)
124
125 - def get_boolean(self):
126 """ 127 Fetch a boolean from the stream. 128 """ 129 b = self.get_bytes(1) 130 return b != zero_byte
131
132 - def get_int(self):
133 """ 134 Fetch an int from the stream. 135 136 :return: a 32-bit unsigned `int`. 137 """ 138 byte = self.get_bytes(1) 139 if byte == max_byte: 140 return util.inflate_long(self.get_binary()) 141 byte += self.get_bytes(3) 142 return struct.unpack('>I', byte)[0]
143
144 - def get_size(self):
145 """ 146 Fetch an int from the stream. 147 148 @return: a 32-bit unsigned integer. 149 @rtype: int 150 """ 151 return struct.unpack('>I', self.get_bytes(4))[0]
152
153 - def get_int64(self):
154 """ 155 Fetch a 64-bit int from the stream. 156 157 :return: a 64-bit unsigned integer (`long`). 158 """ 159 return struct.unpack('>Q', self.get_bytes(8))[0]
160
161 - def get_mpint(self):
162 """ 163 Fetch a long int (mpint) from the stream. 164 165 :return: an arbitrary-length integer (`long`). 166 """ 167 return util.inflate_long(self.get_binary())
168
169 - def get_string(self):
170 """ 171 Fetch a `str` from the stream. This could be a byte string and may 172 contain unprintable characters. (It's not unheard of for a string to 173 contain another byte-stream message.) 174 """ 175 return self.get_bytes(self.get_size())
176
177 - def get_text(self):
178 """ 179 Fetch a string from the stream. This could be a byte string and may 180 contain unprintable characters. (It's not unheard of for a string to 181 contain another byte-stream Message.) 182 183 @return: a string. 184 @rtype: string 185 """ 186 return u(self.get_bytes(self.get_size()))
187 #return self.get_bytes(self.get_size()) 188
189 - def get_binary(self):
190 """ 191 Fetch a string from the stream. This could be a byte string and may 192 contain unprintable characters. (It's not unheard of for a string to 193 contain another byte-stream Message.) 194 195 @return: a string. 196 @rtype: string 197 """ 198 return self.get_bytes(self.get_size())
199
200 - def get_list(self):
201 """ 202 Fetch a `list` of `strings <str>` from the stream. 203 204 These are trivially encoded as comma-separated values in a string. 205 """ 206 return self.get_text().split(',')
207
208 - def add_bytes(self, b):
209 """ 210 Write bytes to the stream, without any formatting. 211 212 :param str b: bytes to add 213 """ 214 self.packet.write(b) 215 return self
216
217 - def add_byte(self, b):
218 """ 219 Write a single byte to the stream, without any formatting. 220 221 :param str b: byte to add 222 """ 223 self.packet.write(b) 224 return self
225
226 - def add_boolean(self, b):
227 """ 228 Add a boolean value to the stream. 229 230 :param bool b: boolean value to add 231 """ 232 if b: 233 self.packet.write(one_byte) 234 else: 235 self.packet.write(zero_byte) 236 return self
237
238 - def add_size(self, n):
239 """ 240 Add an integer to the stream. 241 242 :param int n: integer to add 243 """ 244 self.packet.write(struct.pack('>I', n)) 245 return self
246
247 - def add_int(self, n):
248 """ 249 Add an integer to the stream. 250 251 :param int n: integer to add 252 """ 253 if n >= Message.big_int: 254 self.packet.write(max_byte) 255 self.add_string(util.deflate_long(n)) 256 else: 257 self.packet.write(struct.pack('>I', n)) 258 return self
259
260 - def add_int64(self, n):
261 """ 262 Add a 64-bit int to the stream. 263 264 :param long n: long int to add 265 """ 266 self.packet.write(struct.pack('>Q', n)) 267 return self
268
269 - def add_mpint(self, z):
270 """ 271 Add a long int to the stream, encoded as an infinite-precision 272 integer. This method only works on positive numbers. 273 274 :param long z: long int to add 275 """ 276 self.add_string(util.deflate_long(z)) 277 return self
278
279 - def add_string(self, s):
280 """ 281 Add a string to the stream. 282 283 :param str s: string to add 284 """ 285 s = asbytes(s) 286 self.add_size(len(s)) 287 self.packet.write(s) 288 return self
289
290 - def add_list(self, l):
291 """ 292 Add a list of strings to the stream. They are encoded identically to 293 a single string of values separated by commas. (Yes, really, that's 294 how SSH2 does it.) 295 296 :param list l: list of strings to add 297 """ 298 self.add_string(','.join(l)) 299 return self
300
301 - def _add(self, i):
302 if type(i) is bool: 303 return self.add_boolean(i) 304 elif isinstance(i, integer_types): 305 return self.add_int(i) 306 elif type(i) is list: 307 return self.add_list(i) 308 else: 309 return self.add_string(i)
310
311 - def add(self, *seq):
312 """ 313 Add a sequence of items to the stream. The values are encoded based 314 on their type: str, int, bool, list, or long. 315 316 .. warning:: 317 Longs are encoded non-deterministically. Don't use this method. 318 319 :param seq: the sequence of items 320 """ 321 for item in seq: 322 self._add(item)
323