home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 January / maximum-cd-2011-01.iso / DiscContents / xbmc-9.11.exe / system / python / spyce / modules / session.py < prev    next >
Encoding:
Python Source  |  2009-12-23  |  11.7 KB  |  369 lines

  1. ##################################################
  2. # SPYCE - Python-based HTML Scripting
  3. # Copyright (c) 2002 Rimon Barr.
  4. #
  5. # Refer to spyce.py
  6. # CVS: $Id: session.py 20864 2009-06-02 06:16:47Z ceros7 $
  7. ##################################################
  8.  
  9. from spyceModule import spyceModule
  10. import re, time, string, random
  11. import spyceLock
  12. try:
  13.   import cPickle
  14.   pickle = cPickle
  15. except:
  16.   import pickle
  17.  
  18. __doc__ = '''Session module provides support for session management - the
  19. storage of variables on the server between requests under some short
  20. identifier. 
  21.  
  22. A user must call setHandler() to determine how the sessions are stored, before
  23. using the other session methods. The get(), set() and delete() methods provide
  24. access to the session information. 
  25.  
  26. The autoSession() method will turn on the automatic session management
  27. (loading and saving the session). When automatic session management is turned
  28. on the session information, identifier, parameter name and browser method are
  29. stored in the variables called auto, autoID, autoName and autoMethod,
  30. respectively.'''
  31.  
  32. class session(spyceModule):
  33.   def start(self):
  34.     "Initialise the session module variables."
  35.     self._serverobject = self._api.getServerObject()
  36.     if 'session' not in dir(self._serverobject):
  37.       self._serverobject.session = sessionHandlerRegistry()
  38.     self._handler = None
  39.     self._clearAutoSession()
  40.   def finish(self, theError=None):
  41.     "Save the session, if automatic session management is turned on."
  42.     if self.autoID:
  43.       self.set(self.auto, self.autoExpire, self.autoID)
  44.       if self.autoMethod=='cookie':
  45.         self._api.getModule('cookie').set(self.autoName, self.autoID)
  46.     sessionCleanup(self._serverobject.session)
  47.   def init(self, handler=None, *args, **kwargs):
  48.     if handler: 
  49.       session = apply(self.setHandler, (handler,)+args)
  50.       if kwargs.has_key('auto') and kwargs['auto']:
  51.         auto = kwargs['auto']
  52.         if type(auto) != type(()): 
  53.           auto = (auto,)
  54.         apply(session.autoSession, auto)
  55.   def setHandler(self, file_name, *params):
  56.     "Select a session handler."
  57.     file_name = string.split(file_name, ':')
  58.     if len(file_name)==1: file, name = None, file_name[0]
  59.     else: file, name = file_name[:2]
  60.     if file: handler = self._api.loadModule(name, file, self._api.getFilename())
  61.     else: handler = eval(name)
  62.     self._handler = apply(handler, (self,)+params)
  63.     self._serverobject.session.add(self._handler)
  64.     return self
  65.   def get(self, id):  # method deletes session, if stale
  66.     "Retrieve session information."
  67.     if not self._handler: raise 'call setHandler to initialise'
  68.     return self._handler.get(id)
  69.   def delete(self, id=None):
  70.     "Delete session information."
  71.     if not self._handler: raise 'call setHandler to initialise'
  72.     if not id:
  73.       id = self.autoID
  74.       self._clearAutoSession()
  75.     return self._handler.delete(id)
  76.   def set(self, state, expire, id=None):
  77.     "Set session information."
  78.     if not self._handler: raise 'call setHandler to initialise'
  79.     return self._handler.set(state, expire, id)
  80.   def clear(self):
  81.     "Clear all session information in current handler."
  82.     if not self._handler: raise 'call setHandler to initialise'
  83.     return self._handler.clear()
  84.   def autoSession(self, expire, method='cookie', name='spyceSession'):
  85.     "Turn on automatic session management."
  86.     if not self._handler: raise 'call setHandler to initialise'
  87.     method = string.lower(method)
  88.     if method=='cookie': self.autoID = self._api.getModule('cookie').get(name)
  89.     elif method=='post': self.autoID = self._api.getModule('request').post1(name)
  90.     elif method=='get': self.autoID = self._api.getModule('request').get1(name)
  91.     else: raise 'runtime error: invalid autosession method'
  92.     self.autoMethod = method
  93.     self.autoName = name
  94.     self.autoExpire = expire
  95.     self.auto = None
  96.     if self.autoID:
  97.       self.auto = self.get(self.autoID)
  98.       if not self.auto: self.autoID = None
  99.     if not self.autoID:  # generate a sessionid
  100.       self.autoID = self.set(None, self.autoExpire)
  101.   def _clearAutoSession(self):
  102.     self.auto = None
  103.     self.autoID = None
  104.     self.autoMethod = None
  105.     self.autoName = None
  106.     self.autoExpire = None
  107.     
  108. ##################################################
  109. # Cleanup
  110. #
  111.  
  112. # expire sessions every n requests in expectation
  113. SESSION_EXPIRE_CHECK = 50
  114.  
  115. class sessionHandlerRegistry:
  116.   "Registry of all used session handlers."
  117.   def __init__(self):
  118.     self.handlers = {}
  119.   def add(self, handler):
  120.     self.handlers[handler.getHandlerID()] = handler
  121.   def list(self):
  122.     return self.handlers.values()
  123.   def remove(self, handler):
  124.     del self.handlers[handler.getHandlerID()]
  125.  
  126. def sessionCleanup(registry):
  127.   """Iterates through all session handlers and sessions to perform session
  128.   cleanup"""
  129.   if random.randrange(SESSION_EXPIRE_CHECK): return
  130.   for handler in registry.list():
  131.     try:
  132.       sessions = handler.keys()
  133.       for s in sessions:
  134.         handler.get(s)   # will delete stale sessions
  135.     except:
  136.       registry.remove(handler)
  137.  
  138.  
  139. ##################################################
  140. # Session handlers
  141. #
  142.  
  143. class sessionHandler:
  144.   '''All session handlers should subclass this, and implement the methods
  145.   marked: 'not implemented'.'''
  146.   def __init__(self, sessionModule):
  147.     self.childnum = sessionModule._api.getServerID()
  148.   def getHandlerID(self):
  149.     raise 'not implemented'
  150.   def get(self, id):  # method should delete, if session is stale
  151.     raise 'not implemented'
  152.   def delete(self, id):
  153.     raise 'not implemented'
  154.   def clear(self):
  155.     raise 'not implemented'
  156.   def set(self, state, expire, id=None):
  157.     raise 'not implemented'
  158.   def keys(self):
  159.     raise 'not implemented'
  160.   def __getitem__(self, key):
  161.     return self.get(key)
  162.   def __delitem__(self, key):
  163.     return self.delete(key)
  164.  
  165. ##################################################
  166. # File-based session handler
  167. #
  168.  
  169. class session_dir(sessionHandler):
  170.   def __init__(self, sessionModule, dir):
  171.     sessionHandler.__init__(self, sessionModule)
  172.     if not os.path.exists(dir):
  173.       raise "session directory '%s' does not exist" % dir
  174.     self.dir = dir
  175.     self.prefix = 'spy'
  176.     self.BINARY_MODE = 1
  177.   def getHandlerID(self):
  178.     return 'session_dir', self.childnum, self.dir
  179.   def get(self, id):
  180.     if not id: return None
  181.     filename = os.path.join(self.dir, self.prefix+id)
  182.     f=None
  183.     sessionInfo = None
  184.     try:
  185.       f=open(filename, 'r')
  186.       sessionInfo = pickle.load(f)
  187.       f.close()
  188.     except:
  189.       try:
  190.         if f: f.close()
  191.         os.unlink(filename)
  192.       except: pass
  193.     if sessionInfo:
  194.       if time.time() > sessionInfo['expire']:
  195.         self.delete(id)
  196.         return None
  197.       else: return sessionInfo['state']
  198.     else: return None
  199.   def delete(self, id):
  200.     try:
  201.       filename = os.path.join(self.dir, self.prefix+id)
  202.       os.remove(filename)
  203.     except: pass
  204.   def clear(self):
  205.     for id in self.keys():
  206.       self.delete(id)
  207.   def set(self, state, expire, id=None):
  208.     f=None
  209.     try:
  210.       if id:
  211.         filename = os.path.join(self.dir, self.prefix+id)
  212.         f=open(filename, 'w')
  213.       else:
  214.         filename, f, id = openUniqueFile(self.dir, self.prefix, ('%d_' % self.childnum))
  215.       sessionInfo = {}
  216.       sessionInfo['expire'] = int(time.time())+expire
  217.       sessionInfo['state'] = state
  218.       pickle.dump(sessionInfo, f, self.BINARY_MODE)
  219.       f.close()
  220.     except:
  221.       try:
  222.         if f: f.close()
  223.       except: pass
  224.       raise
  225.     return id
  226.   def keys(self):
  227.     sessions = os.listdir(self.dir)
  228.     sessions = filter(lambda s, p=self.prefix: s[:len(p)]==p, sessions)
  229.     sessions = map(lambda s, self=self: s[len(self.prefix):], sessions)
  230.     return sessions
  231.  
  232. # requires unique (dir, prefix)
  233. def openUniqueFile(dir, prefix, unique, mode='w', max=1000000):
  234.   filelock = spyceLock.fileLock(os.path.join(dir, prefix))
  235.   filelock.lock(1)
  236.   try:
  237.     id = "%06d"%random.randrange(max)
  238.     filename = os.path.join(dir, prefix+unique+id)
  239.     while os.path.exists(filename):
  240.       id = str(random.randrange(max))
  241.       filename = os.path.join(dir, prefix+unique+id)
  242.     f = None
  243.     f = open(filename, mode)
  244.     return filename, f, unique+id
  245.   finally:
  246.     filelock.unlock()
  247.  
  248. ##################################################
  249. # Hash file session handlers
  250. #
  251.  
  252. class sessionHandlerDBM(sessionHandler):
  253.   def __init__(self, sessionModule, filename):
  254.     sessionHandler.__init__(self, sessionModule)
  255.     self.filename = filename
  256.     self.dbm = None
  257.     self.BINARY_MODE = 1
  258.     self.dbm_type = None  # redefine in subclass
  259.   def getHandlerID(self):
  260.     return 'session_'+self.dbm_type, self.childnum, self.filename
  261.   def _open(self):
  262.     raise 'need to implement'
  263.   def _close(self):
  264.     if self.dbm:
  265.       self.dbm.close()
  266.       self.dbm = None
  267.   def get(self, id):
  268.     if not id: return None
  269.     self._open()
  270.     try:
  271.       expire, state = None, None
  272.       if self.dbm.has_key(id):
  273.         expire, state = pickle.loads(self.dbm[id])
  274.       if expire!=None and time.time() > expire:
  275.         self.delete(id)
  276.         state = None
  277.       return state
  278.     finally:
  279.       self._close()
  280.   def delete(self, id):
  281.     self._open()
  282.     try:
  283.       if self.dbm.has_key(id):
  284.         del self.dbm[id]
  285.     finally:
  286.       self._close()
  287.   def clear(self):
  288.     if os.path.exists(self.filename):
  289.       os.unlink(self.filename)
  290.   def set(self, state, expire, id=None):
  291.     self._open()
  292.     try:
  293.       if not id:
  294.         id = generateKey(self.dbm, self.childnum)
  295.       value = pickle.dumps( (int(time.time())+expire, state), self.BINARY_MODE)
  296.       self.dbm[id] = value
  297.       return id
  298.     finally:
  299.       self._close()
  300.   def keys(self):
  301.     self._open()
  302.     try:
  303.       return self.dbm.keys()
  304.     finally:
  305.       self._close()
  306.  
  307. def opendb(dbm_session_handler, module, filename, flags):
  308.   mod = __import__(module)
  309.   if not dbm_session_handler.dbm:
  310.     dbm_session_handler.dbm = mod.open(filename, flags)
  311.   
  312. class session_gdbm(sessionHandlerDBM):
  313.   def __init__(self, sessionModule, filename):
  314.     sessionHandlerDBM.__init__(self, sessionModule, filename)
  315.     self.dbm_type = 'gdbm'
  316.   def _open(self):
  317.     opendb(self, self.dbm_type, self.filename, 'cu')
  318.  
  319. class session_bsddb(sessionHandlerDBM):
  320.   def __init__(self, sessionModule, filename):
  321.     sessionHandlerDBM.__init__(self, sessionModule, filename)
  322.     self.dbm_type = 'bsddb'
  323.   def _open(self):
  324.     opendb(self, 'dbhash', self.filename, 'c')
  325.  
  326. def generateKey(hash, prefix, max = 1000000):
  327.   prefix = str(prefix)+'_'
  328.   key = random.randrange(max)
  329.   while hash.has_key(prefix+str(key)):
  330.     key = random.randrange(max)
  331.   key = prefix+str(key)
  332.   hash[key] = pickle.dumps(None, 1)
  333.   return key
  334.  
  335.  
  336. ##################################################
  337. # User callback session handlers
  338. #
  339.  
  340. class session_user(sessionHandler):
  341.   '''User-callback session handler'''
  342.   def __init__(self, sessionModule, getf, setf, delf, idsf, info=None):
  343.     self.serverID = sessionModule._api.getServerID()
  344.     self.info = info
  345.     self.getf = getf
  346.     self.setf = setf
  347.     self.delf = delf
  348.     self.idsf = idsf
  349.   def getHandlerID(self):
  350.     return 'session_user', self.serverID, self.info
  351.   def get(self, id):  # method should delete, if session is stale
  352.     return self.getf(self.info, id)
  353.   def set(self, state, expire, id):
  354.     return self.setf(self.info, state, expire, self.serverID, id)
  355.   def delete(self, id):
  356.     return self.delf(self.info, id)
  357.   def keys(self):
  358.     return self.idsf(self.info)
  359.   def clear(self):
  360.     for id in self.keys():
  361.       self.delete(id)
  362.  
  363. ##################################################
  364. # database-based session handlers
  365. #
  366.  
  367. # rimtodo: database-based session handler
  368.  
  369.