From fd8e295c2e03bf2ed461fe522fd755cdb3fb99d0 Mon Sep 17 00:00:00 2001 From: Stephen Soltesz Date: Fri, 2 Nov 2007 21:51:59 +0000 Subject: [PATCH] Minor description of the dependencies that Monitor has for connecting to: * RT * MySQL * and local database output formats. --- README.txt | 17 +++ util/PHPSerialize.py | 149 +++++++++++++++++++++++++++ util/PHPUnserialize.py | 228 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 394 insertions(+) create mode 100644 README.txt create mode 100644 util/PHPSerialize.py create mode 100644 util/PHPUnserialize.py diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..9c8cf4d --- /dev/null +++ b/README.txt @@ -0,0 +1,17 @@ +Dependencies + + * RT - 3.4.1 - + The version at rt.planet-lab.org is 3.4.1 and is incompatible with later + versions of the command line tool. + + The RPM pulls in *ALOT* of stuff; probably easier to work with from the + source package, especially, since all that's needed is the command line + tool. It has far fewer dependencies than the full RT package. + + * MySQL-python + python module necessary for connecting to the mysql RT database and + extracting a list of open and new tickets. + + * util/PHPSerializer/PHPUnserializer + these are helper scripts for converting pickle objects into php serialize + objects and back. diff --git a/util/PHPSerialize.py b/util/PHPSerialize.py new file mode 100644 index 0000000..d25b71b --- /dev/null +++ b/util/PHPSerialize.py @@ -0,0 +1,149 @@ +import types, string + +""" +Serialize class for the PHP serialization format. + +@version v0.4 BETA +@author Scott Hurring; scott at hurring dot com +@copyright Copyright (c) 2005 Scott Hurring +@license http://opensource.org/licenses/gpl-license.php GNU Public License +$Id: PHPSerialize.py,v 1.1 2006/01/08 21:53:19 shurring Exp $ + +Most recent version can be found at: +http://hurring.com/code/python/phpserialize/ + +Usage: +# Create an instance of the serialize engine +s = PHPSerialize() +# serialize some python data into a string +serialized_string = s.serialize(string) +# encode a session list (php's session_encode) +serialized_string = s.session_encode(list) + +See README.txt for more information. +""" + +class PHPSerialize(object): + """ + Class to serialize data using the PHP Serialize format. + + Usage: + serialized_string = PHPSerialize().serialize(data) + serialized_string = PHPSerialize().session_encode(list) + """ + + def __init__(self): + pass + + def session_encode(self, session): + """Thanks to Ken Restivo for suggesting the addition + of session_encode + """ + out = "" + for (k,v) in session.items(): + out = out + "%s|%s" % (k, self.serialize(v)) + return out + + def serialize(self, data): + return self.serialize_value(data) + + def is_int(self, data): + """ + Determine if a string var looks like an integer + TODO: Make this do what PHP does, instead of a hack + """ + try: + int(data) + return True + except: + return False + + def serialize_key(self, data): + """ + Serialize a key, which follows different rules than when + serializing values. Many thanks to Todd DeLuca for pointing + out that keys are serialized differently than values! + + From http://us2.php.net/manual/en/language.types.array.php + A key may be either an integer or a string. + If a key is the standard representation of an integer, it will be + interpreted as such (i.e. "8" will be interpreted as int 8, + while "08" will be interpreted as "08"). + Floats in key are truncated to integer. + """ + # Integer, Long, Float, Boolean => integer + if type(data) is types.IntType or type(data) is types.LongType \ + or type(data) is types.FloatType or type(data) is types.BooleanType: + return "i:%s;" % int(data) + + # String => string or String => int (if string looks like int) + elif type(data) is types.StringType: + if self.is_int(data): + return "i:%s;" % int(data) + else: + return "s:%i:\"%s\";" % (len(data), data); + + # None / NULL => empty string + elif type(data) is types.NoneType: + return "s:0:\"\";" + + # I dont know how to serialize this + else: + raise Exception("Unknown / Unhandled key type (%s)!" % type(data)) + + + def serialize_value(self, data): + """ + Serialize a value. + """ + + # Integer => integer + if type(data) is types.IntType: + return "i:%s;" % data + + # Float, Long => double + elif type(data) is types.FloatType or type(data) is types.LongType: + return "d:%s;" % data + + # String => string or String => int (if string looks like int) + # Thanks to Todd DeLuca for noticing that PHP strings that + # look like integers are serialized as ints by PHP + elif type(data) is types.StringType: + if self.is_int(data): + return "i:%s;" % int(data) + else: + return "s:%i:\"%s\";" % (len(data), data); + + # None / NULL + elif type(data) is types.NoneType: + return "N;"; + + # Tuple and List => array + # The 'a' array type is the only kind of list supported by PHP. + # array keys are automagically numbered up from 0 + elif type(data) is types.ListType or type(data) is types.TupleType: + i = 0 + out = [] + # All arrays must have keys + for k in data: + out.append(self.serialize_key(i)) + out.append(self.serialize_value(k)) + i += 1 + return "a:%i:{%s}" % (len(data), "".join(out)) + + # Dict => array + # Dict is the Python analogy of a PHP array + elif type(data) is types.DictType: + out = [] + for k in data: + out.append(self.serialize_key(k)) + out.append(self.serialize_value(data[k])) + return "a:%i:{%s}" % (len(data), "".join(out)) + + # Boolean => bool + elif type(data) is types.BooleanType: + return "b:%i;" % (data == 1) + + # I dont know how to serialize this + else: + raise Exception("Unknown / Unhandled data type (%s)!" % type(data)) diff --git a/util/PHPUnserialize.py b/util/PHPUnserialize.py new file mode 100644 index 0000000..d939ce0 --- /dev/null +++ b/util/PHPUnserialize.py @@ -0,0 +1,228 @@ +import types, string, re + +""" +Unserialize class for the PHP serialization format. + +@version v0.4 BETA +@author Scott Hurring; scott at hurring dot com +@copyright Copyright (c) 2005 Scott Hurring +@license http://opensource.org/licenses/gpl-license.php GNU Public License +$Id: PHPUnserialize.py,v 1.1 2006/01/08 21:53:19 shurring Exp $ + +Most recent version can be found at: +http://hurring.com/code/python/phpserialize/ + +Usage: +# Create an instance of the unserialize engine +u = PHPUnserialize() +# unserialize some string into python data +data = u.unserialize(serialized_string) + +Please see README.txt for more information. +""" + +class PHPUnserialize(object): + """ + Class to unserialize something from the PHP Serialize format. + + Usage: + u = PHPUnserialize() + data = u.unserialize(serialized_string) + """ + + def __init__(self): + pass + + def session_decode(self, data): + """Thanks to Ken Restivo for suggesting the addition + of session_encode + """ + session = {} + while len(data) > 0: + m = re.match('^(\w+)\|', data) + if m: + key = m.group(1) + offset = len(key)+1 + (dtype, dataoffset, value) = self._unserialize(data, offset) + offset = offset + dataoffset + data = data[offset:] + session[key] = value + else: + # No more stuff to decode + return session + + return session + + def unserialize(self, data): + return self._unserialize(data, 0)[2] + + def _unserialize(self, data, offset=0): + """ + Find the next token and unserialize it. + Recurse on array. + + offset = raw offset from start of data + + return (type, offset, value) + """ + + buf = [] + dtype = string.lower(data[offset:offset+1]) + + #print "# dtype =", dtype + + # 't:' = 2 chars + dataoffset = offset + 2 + typeconvert = lambda x : x + chars = datalength = 0 + + # int => Integer + if dtype == 'i': + typeconvert = lambda x : int(x) + (chars, readdata) = self.read_until(data, dataoffset, ';') + # +1 for end semicolon + dataoffset += chars + 1 + + # bool => Boolean + elif dtype == 'b': + typeconvert = lambda x : (int(x) == 1) + (chars, readdata) = self.read_until(data, dataoffset, ';') + # +1 for end semicolon + dataoffset += chars + 1 + + # double => Floating Point + elif dtype == 'd': + typeconvert = lambda x : float(x) + (chars, readdata) = self.read_until(data, dataoffset, ';') + # +1 for end semicolon + dataoffset += chars + 1 + + # n => None + elif dtype == 'n': + readdata = None + + # s => String + elif dtype == 's': + (chars, stringlength) = self.read_until(data, dataoffset, ':') + # +2 for colons around length field + dataoffset += chars + 2 + + # +1 for start quote + (chars, readdata) = self.read_chars(data, dataoffset+1, int(stringlength)) + # +2 for endquote semicolon + dataoffset += chars + 2 + + if chars != int(stringlength) != int(readdata): + raise Exception("String length mismatch") + + # array => Dict + # If you originally serialized a Tuple or List, it will + # be unserialized as a Dict. PHP doesn't have tuples or lists, + # only arrays - so everything has to get converted into an array + # when serializing and the original type of the array is lost + elif dtype == 'a': + readdata = {} + + # If all dict keys are increasing ints from zero, + # then make it a list. + # Else, + # just return the original dict + def is_list(keys): + # list with no elements + if len(keys) == 0: + return True + # list with one element: 0 + if len(keys) == 1: + if type(keys[0]) == int and keys[0] == 0: + return True + else: + return False + + # all other cases + for i in range(1,len(keys)): + x = keys[i-1] + y = keys[i] + if type(x) == int and type(y) == int and y-x == 1: + continue + else: + return False + return True + + # Empty {} and empty [] are ambiguous. + # A default could either be configured or assumed to be a list? + def dict_to_list(dict): + + keys = dict.keys() + keys.sort() + + if is_list(keys): + return [dict[k] for k in keys] + else: + return dict + + typeconvert = lambda x : dict_to_list(x) + + # How many keys does this list have? + (chars, keys) = self.read_until(data, dataoffset, ':') + # +2 for colons around length field + dataoffset += chars + 2 + + # Loop through and fetch this number of key/value pairs + for i in range(0, int(keys)): + # Read the key + (ktype, kchars, key) = self._unserialize(data, dataoffset) + dataoffset += kchars + #print "Key(%i) = (%s, %i, %s) %i" % (i, ktype, kchars, key, dataoffset) + + # Read value of the key + (vtype, vchars, value) = self._unserialize(data, dataoffset) + dataoffset += vchars + #print "Value(%i) = (%s, %i, %s) %i" % (i, vtype, vchars, value, dataoffset) + + # Set the list element + readdata[key] = value + + # +1 for end semicolon + dataoffset += 1 + #chars = int(dataoffset) - start + + # I don't know how to unserialize this + else: + raise Exception("Unknown / Unhandled data type (%s)!" % dtype) + + + return (dtype, dataoffset-offset, typeconvert(readdata)) + + def read_until(self, data, offset, stopchar): + """ + Read from data[offset] until you encounter some char 'stopchar'. + """ + buf = [] + char = data[offset:offset+1] + i = 2 + while char != stopchar: + # Consumed all the characters and havent found ';' + if i+offset > len(data): + raise Exception("Invalid") + buf.append(char) + char = data[offset+(i-1):offset+i] + i += 1 + + # (chars_read, data) + return (len(buf), "".join(buf)) + + def read_chars(self, data, offset, length): + """ + Read 'length' number of chars from data[offset]. + """ + buf = [] + # Account for the starting quote char + #offset += 1 + for i in range(0, length): + char = data[offset+(i-1):offset+i] + buf.append(char) + + # (chars_read, data) + return (len(buf), "".join(buf)) + + -- 2.43.0