Back to index

moin  1.9.0~rc2
_PHPsessionParser.py
Go to the documentation of this file.
00001 """
00002     MoinMoin - Parsing of PHP session files
00003 
00004     @copyright: 2005 MoinMoin:AlexanderSchremmer (Thanks to Spreadshirt)
00005     @license: GNU GPL, see COPYING for details.
00006 """
00007 
00008 #Known minor bugs/questions/ideas:
00009 #How does object demarshalling work?
00010 #The order of the python dictionaries is not stable compared to the PHP arrays
00011 #The loader does not check the owner of the files, so be aware of faked session
00012 #files.
00013 
00014 import os
00015 from MoinMoin import wikiutil
00016 
00017 s_prefix = "sess_"
00018 s_path = "/tmp"
00019 
00020 class UnknownObject(object):
00021     """ Used in the return value if the input data could not be parsed. """
00022     def __init__(self, pos):
00023         self.pos = pos
00024 
00025     def __repr__(self):
00026         return "<Unknown object at pos %i>" % self.pos
00027 
00028 def transformList(items):
00029     """ Transforms a list [1, 2, 3, 4, ...] into a
00030         [(1, 2), (3, 4), ...] generator. """
00031     for i in xrange(0, len(items), 2):
00032         yield (items[i], items[i+1])
00033     raise StopIteration
00034 
00035 def parseValue(string, start=0):
00036     """ Parses the inner structure. """
00037     # TODO: replace "string" by something else
00038     #print "Parsing %r" % (string[start:], )
00039 
00040     val_type = string[start]
00041     try:
00042         header_end = string.index(':', 3+start)
00043         first_data = string[start+2:header_end]
00044     except ValueError:
00045         first_data = None
00046 
00047     #print "Saw type %r, first_data is %r." % (val_type, first_data)
00048     if val_type == 'a': # array (in Python rather a mixture of a list and a dict)
00049         i = 0
00050         items = []
00051 
00052         current_pos = header_end+2
00053         data = string
00054         while i != (int(first_data) * 2):
00055             item, current_pos = parseValue(data, current_pos)
00056             items.append(item)
00057             i += 1
00058             current_pos += 1
00059 
00060         t_list = list(transformList(items))
00061         try:
00062             result = dict(t_list) # note that dict does not retain the order
00063         except TypeError:
00064             result = list(t_list)
00065             #print "Warning, could not convert to dict: %r" %  (result, )
00066         return result, current_pos
00067 
00068     if val_type == 's': # string
00069         current_pos = header_end+2
00070         end = current_pos + int(first_data)
00071         data = string[current_pos:end]
00072         current_pos = end+1
00073         if data.startswith("a:"): #Sometimes, arrays are marshalled as strings.
00074             try:
00075                 data = parseValue(data, 0)[0]
00076             except ValueError: #Hmm, wrongly guessed. Just an ordinary string
00077                 pass
00078         return data, current_pos
00079 
00080     if val_type in ('i', 'b'): # integer or boolean
00081         current_pos = start+2
00082         str_buffer = ""
00083         while current_pos != len(string):
00084             cur_char = string[current_pos]
00085             if cur_char.isdigit() or cur_char == "-":
00086                 str_buffer += cur_char
00087             else:
00088                 cast = (val_type == 'i') and int or (lambda x: bool(int(x)))
00089                 return cast(str_buffer), current_pos
00090             current_pos += 1
00091 
00092     if val_type == "N": # Null, called None in Python
00093         return None, start+1
00094 
00095     return UnknownObject(start), start+1
00096 
00097 def parseSession(boxed):
00098     """ Parses the outer structure that is similar to a dict. """
00099     current_pos = 0
00100     session_dict = {}
00101     while current_pos < len(boxed):
00102         name_end = boxed.find("|", current_pos) # TODO: replace by .index()?
00103         name = boxed[current_pos:name_end]
00104         current_pos = name_end+1
00105         data, current_pos = parseValue(boxed, current_pos)
00106         current_pos += 1
00107         session_dict[name] = data
00108 
00109     return session_dict
00110 
00111 def loadSession(key, path=s_path, prefix=s_prefix):
00112     """ Loads a particular session from the directory. The key needs to be the
00113         session id. """
00114     key = key.lower()
00115     filename = os.path.join(path, prefix + wikiutil.taintfilename(key))
00116 
00117     try:
00118         f = open(filename, "rb")
00119     except IOError, e:
00120         if e.errno == 2:
00121             return None # session does not exist
00122         else:
00123             raise
00124 
00125     blob = f.read()
00126     f.close()
00127     return parseSession(blob)
00128 
00129 def listSessions(path=s_path, prefix=s_prefix):
00130     """ Lists all sessions in a particular directory. """
00131     return [os.path.basename(x).replace(s_prefix, '') for x in os.listdir(s_path)
00132             if x.startswith(s_prefix)]
00133 
00134 if __name__ == '__main__':
00135     # testing code
00136     import time
00137     a = time.clock()
00138 
00139     #print s
00140     p_s = loadSession("...")
00141     import pprint
00142     pprint.pprint(p_s)
00143     print time.clock() - a
00144     print listSessions()
00145