Package pyamf :: Module sol
[hide private]
[frames] | no frames]

Source Code for Module pyamf.sol

  1  # -*- coding: utf-8 -*- 
  2  # 
  3  # Copyright (c) 2007-2009 The PyAMF Project. 
  4  # See LICENSE.txt for details. 
  5   
  6  """ 
  7  Local Shared Object implementation. 
  8   
  9  Local Shared Object (LSO), sometimes known as Adobe Flash cookies, is a 
 10  cookie-like data entity used by the Adobe Flash Player and Gnash. The players 
 11  allow web content to read and write LSO data to the computer's local drive on 
 12  a per-domain basis. 
 13   
 14  @see: U{Local Shared Object on WikiPedia (external) 
 15  <http://en.wikipedia.org/wiki/Local_Shared_Object>} 
 16  @see: U{Local Shared Object envelope (external) 
 17  <http://osflash.org/documentation/amf/envelopes/sharedobject>} 
 18   
 19  @since: 0.1.0 
 20  """ 
 21   
 22  import pyamf 
 23  from pyamf import util 
 24   
 25  #: Magic Number - 2 bytes 
 26  HEADER_VERSION = '\x00\xbf' 
 27  #: Marker - 10 bytes 
 28  HEADER_SIGNATURE = 'TCSO\x00\x04\x00\x00\x00\x00' 
 29  #: Padding - 4 bytes 
 30  PADDING_BYTE = '\x00' 
 31   
 32   
33 -def decode(stream, strict=True):
34 """ 35 Decodes a SOL stream. C{strict} mode ensures that the sol stream is as spec 36 compatible as possible. 37 38 @param strict: Ensure that the SOL stream is as spec compatible as possible. 39 @type strict: C{bool} 40 @return: A C{tuple} containing the C{root_name} and a C{dict} of name, 41 value pairs. 42 @rtype: C{tuple} 43 44 @raise DecodeError: Unknown SOL version in header. 45 @raise DecodeError: Inconsistent stream header length. 46 @raise DecodeError: Invalid signature. 47 @raise DecodeError: Invalid padding read. 48 @raise DecodeError: Missing padding byte. 49 """ 50 if not isinstance(stream, util.BufferedByteStream): 51 stream = util.BufferedByteStream(stream) 52 53 # read the version 54 version = stream.read(2) 55 56 if version != HEADER_VERSION: 57 raise pyamf.DecodeError('Unknown SOL version in header') 58 59 # read the length 60 length = stream.read_ulong() 61 62 if strict and stream.remaining() != length: 63 raise pyamf.DecodeError('Inconsistent stream header length') 64 65 # read the signature 66 signature = stream.read(10) 67 68 if signature != HEADER_SIGNATURE: 69 raise pyamf.DecodeError('Invalid signature') 70 71 length = stream.read_ushort() 72 root_name = stream.read_utf8_string(length) 73 74 # read padding 75 if stream.read(3) != PADDING_BYTE * 3: 76 raise pyamf.DecodeError('Invalid padding read') 77 78 decoder = pyamf.get_decoder(stream.read_uchar()) 79 decoder.stream = stream 80 81 values = {} 82 83 while 1: 84 if stream.at_eof(): 85 break 86 87 name = decoder.readString() 88 value = decoder.readElement() 89 90 # read the padding 91 if stream.read(1) != PADDING_BYTE: 92 raise pyamf.DecodeError('Missing padding byte') 93 94 values[name] = value 95 96 return (root_name, values)
97 98
99 -def encode(name, values, strict=True, encoding=pyamf.AMF0):
100 """ 101 Produces a SharedObject encoded stream based on the name and values. 102 103 @param name: The root name of the SharedObject. 104 @type name: C{basestring} 105 @param values: A C{dict} of name value pairs to be encoded in the stream. 106 @type values: C{dict} 107 @param strict: Ensure that the SOL stream is as spec compatible as possible. 108 @type strict: C{bool} 109 @return: A SharedObject encoded stream. 110 @rtype: L{BufferedByteStream<pyamf.util.BufferedByteStream>} 111 """ 112 encoder = pyamf.get_encoder(encoding) 113 encoder.stream = stream = util.BufferedByteStream() 114 115 # write the header 116 stream.write(HEADER_VERSION) 117 118 if strict is True: 119 length_pos = stream.tell() 120 121 stream.write_ulong(0) 122 123 # write the signature 124 stream.write(HEADER_SIGNATURE) 125 126 # write the root name 127 if not isinstance(name, unicode): 128 name = unicode(name) 129 130 stream.write_ushort(len(name)) 131 stream.write_utf8_string(name) 132 133 # write the padding 134 stream.write(PADDING_BYTE * 3) 135 stream.write_uchar(encoding) 136 137 for n, v in values.iteritems(): 138 encoder.writeString(n, writeType=False) 139 encoder.writeElement(v) 140 141 # write the padding 142 stream.write(PADDING_BYTE) 143 144 if strict: 145 stream.seek(length_pos) 146 stream.write_ulong(stream.remaining() - 4) 147 148 stream.seek(0) 149 150 return stream
151 152
153 -def load(name_or_file):
154 """ 155 Loads a sol file and returns a L{SOL} object. 156 157 @param name_or_file: Name of file, or file-object. 158 @type name_or_file: C{str} or C{StringIO} 159 160 @raise ValueError: Readable stream expected. 161 """ 162 f = name_or_file 163 opened = False 164 165 if isinstance(name_or_file, basestring): 166 f = open(name_or_file, 'rb') 167 opened = True 168 elif not hasattr(f, 'read'): 169 raise ValueError('Readable stream expected') 170 171 name, values = decode(f.read()) 172 s = SOL(name) 173 174 for n, v in values.iteritems(): 175 s[n] = v 176 177 if opened is True: 178 f.close() 179 180 return s
181 182
183 -def save(sol, name_or_file, encoding=pyamf.AMF0):
184 """ 185 Writes a L{SOL} object to C{name_or_file}. 186 187 @param sol: 188 @type sol: 189 @param name_or_file: Name of file, or file-object. 190 @type name_or_file: C{str} or C{StringIO} 191 @param encoding: AMF encoding type. 192 @type encoding: C{int} 193 194 @raise ValueError: Writable stream expected. 195 """ 196 f = name_or_file 197 opened = False 198 199 if isinstance(name_or_file, basestring): 200 f = open(name_or_file, 'wb+') 201 opened = True 202 elif not hasattr(f, 'write'): 203 raise ValueError('Writable stream expected') 204 205 f.write(encode(sol.name, sol, encoding=encoding).getvalue()) 206 207 if opened: 208 f.close()
209 210
211 -class SOL(dict):
212 """ 213 Local Shared Object class, allows easy manipulation of the internals of a 214 C{sol} file. 215 """
216 - def __init__(self, name):
217 self.name = name
218
219 - def save(self, name_or_file, encoding=pyamf.AMF0):
220 save(self, name_or_file, encoding)
221
222 - def __repr__(self):
223 return '<%s %s %s at 0x%x>' % (self.__class__.__name__, 224 self.name, dict.__repr__(self), id(self))
225 226 LSO = SOL 227