Minor description of the dependencies that Monitor has for connecting to:
Stephen Soltesz [Fri, 2 Nov 2007 21:51:59 +0000 (21:51 +0000)]
  * RT
  * MySQL
  * and local database output formats.

README.txt [new file with mode: 0644]
util/PHPSerialize.py [new file with mode: 0644]
util/PHPUnserialize.py [new file with mode: 0644]

diff --git a/README.txt b/README.txt
new file mode 100644 (file)
index 0000000..9c8cf4d
--- /dev/null
@@ -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 (file)
index 0000000..d25b71b
--- /dev/null
@@ -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 (file)
index 0000000..d939ce0
--- /dev/null
@@ -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))
+
+