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