Minor description of the dependencies that Monitor has for connecting to:
[monitor.git] / util / PHPSerialize.py
1 import types, string
2
3 """
4 Serialize class for the PHP serialization format.
5
6 @version v0.4 BETA
7 @author Scott Hurring; scott at hurring dot com
8 @copyright Copyright (c) 2005 Scott Hurring
9 @license http://opensource.org/licenses/gpl-license.php GNU Public License
10 $Id: PHPSerialize.py,v 1.1 2006/01/08 21:53:19 shurring Exp $
11
12 Most recent version can be found at:
13 http://hurring.com/code/python/phpserialize/
14
15 Usage:
16 # Create an instance of the serialize engine
17 s = PHPSerialize()
18 # serialize some python data into a string
19 serialized_string = s.serialize(string)
20 # encode a session list (php's session_encode) 
21 serialized_string = s.session_encode(list)
22
23 See README.txt for more information.
24 """
25
26 class PHPSerialize(object):
27         """
28         Class to serialize data using the PHP Serialize format.
29
30         Usage:
31         serialized_string = PHPSerialize().serialize(data)
32         serialized_string = PHPSerialize().session_encode(list)
33         """
34         
35         def __init__(self):
36                 pass
37
38         def session_encode(self, session):
39                 """Thanks to Ken Restivo for suggesting the addition
40                 of session_encode
41                 """
42                 out = ""
43                 for (k,v) in session.items():
44                         out = out + "%s|%s" % (k, self.serialize(v))
45                 return out
46                 
47         def serialize(self, data):
48                 return self.serialize_value(data)
49
50         def is_int(self, data):
51                 """
52                 Determine if a string var looks like an integer
53                 TODO: Make this do what PHP does, instead of a hack
54                 """
55                 try: 
56                         int(data)
57                         return True
58                 except:
59                         return False
60                 
61         def serialize_key(self, data):
62                 """
63                 Serialize a key, which follows different rules than when 
64                 serializing values.  Many thanks to Todd DeLuca for pointing 
65                 out that keys are serialized differently than values!
66                 
67                 From http://us2.php.net/manual/en/language.types.array.php
68                 A key may be either an integer or a string. 
69                 If a key is the standard representation of an integer, it will be
70                 interpreted as such (i.e. "8" will be interpreted as int 8,
71                 while "08" will be interpreted as "08"). 
72                 Floats in key are truncated to integer. 
73                 """
74                 # Integer, Long, Float, Boolean => integer
75                 if type(data) is types.IntType or type(data) is types.LongType \
76                 or type(data) is types.FloatType or type(data) is types.BooleanType:
77                         return "i:%s;" % int(data)
78                         
79                 # String => string or String => int (if string looks like int)
80                 elif type(data) is types.StringType:
81                         if self.is_int(data):
82                                 return "i:%s;" % int(data)
83                         else:
84                                 return "s:%i:\"%s\";" % (len(data),  data);
85                 
86                 # None / NULL => empty string
87                 elif type(data) is types.NoneType:
88                         return "s:0:\"\";"
89                 
90                 # I dont know how to serialize this
91                 else:
92                         raise Exception("Unknown / Unhandled key  type (%s)!" % type(data))
93
94
95         def serialize_value(self, data):
96                 """
97                 Serialize a value.
98                 """
99
100                 # Integer => integer
101                 if type(data) is types.IntType:
102                         return "i:%s;" % data
103
104                 # Float, Long => double
105                 elif type(data) is types.FloatType or type(data) is types.LongType:
106                         return "d:%s;" % data
107
108                 # String => string or String => int (if string looks like int)
109                 # Thanks to Todd DeLuca for noticing that PHP strings that
110                 # look like integers are serialized as ints by PHP 
111                 elif type(data) is types.StringType:
112                         if self.is_int(data):
113                                 return "i:%s;" % int(data)
114                         else:
115                                 return "s:%i:\"%s\";" % (len(data), data);
116
117                 # None / NULL
118                 elif type(data) is types.NoneType:
119                         return "N;";
120
121                 # Tuple and List => array
122                 # The 'a' array type is the only kind of list supported by PHP.
123                 # array keys are automagically numbered up from 0
124                 elif type(data) is types.ListType or type(data) is types.TupleType:
125                         i = 0
126                         out = []
127                         # All arrays must have keys
128                         for k in data:
129                                 out.append(self.serialize_key(i))
130                                 out.append(self.serialize_value(k))
131                                 i += 1
132                         return "a:%i:{%s}" % (len(data), "".join(out))
133
134                 # Dict => array
135                 # Dict is the Python analogy of a PHP array
136                 elif type(data) is types.DictType:
137                         out = []
138                         for k in data:
139                                 out.append(self.serialize_key(k))
140                                 out.append(self.serialize_value(data[k]))
141                         return "a:%i:{%s}" % (len(data), "".join(out))
142
143                 # Boolean => bool
144                 elif type(data) is types.BooleanType:
145                         return "b:%i;" % (data == 1)
146
147                 # I dont know how to serialize this
148                 else:
149                         raise Exception("Unknown / Unhandled data type (%s)!" % type(data))