home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 May / maximum-cd-2009-05.iso / DiscContents / XBMC_for_Windows-8.10.exe / system / python / spyce / modules / session.py < prev    next >
Encoding:
Python Source  |  2008-11-03  |  11.6 KB  |  363 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 5659 2006-04-27 16:15:15Z jwnmulder $
  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.  
  124. def sessionCleanup(registry):
  125.   """Iterates through all session handlers and sessions to perform session
  126.   cleanup"""
  127.   if random.randrange(SESSION_EXPIRE_CHECK): return
  128.   for handler in registry.list():
  129.     sessions = handler.keys()
  130.     for s in sessions:
  131.       handler.get(s)   # will delete stale sessions
  132.  
  133. ##################################################
  134. # Session handlers
  135. #
  136.  
  137. class sessionHandler:
  138.   '''All session handlers should subclass this, and implement the methods
  139.   marked: 'not implemented'.'''
  140.   def __init__(self, sessionModule):
  141.     self.childnum = sessionModule._api.getServerID()
  142.   def getHandlerID(self):
  143.     raise 'not implemented'
  144.   def get(self, id):  # method should delete, if session is stale
  145.     raise 'not implemented'
  146.   def delete(self, id):
  147.     raise 'not implemented'
  148.   def clear(self):
  149.     raise 'not implemented'
  150.   def set(self, state, expire, id=None):
  151.     raise 'not implemented'
  152.   def keys(self):
  153.     raise 'not implemented'
  154.   def __getitem__(self, key):
  155.     return self.get(key)
  156.   def __delitem__(self, key):
  157.     return self.delete(key)
  158.  
  159. ##################################################
  160. # File-based session handler
  161. #
  162.  
  163. class session_dir(sessionHandler):
  164.   def __init__(self, sessionModule, dir):
  165.     sessionHandler.__init__(self, sessionModule)
  166.     if not os.path.exists(dir):
  167.       raise "session directory '%s' does not exist" % dir
  168.     self.dir = dir
  169.     self.prefix = 'spy'
  170.     self.BINARY_MODE = 1
  171.   def getHandlerID(self):
  172.     return 'session_dir', self.childnum, self.dir
  173.   def get(self, id):
  174.     if not id: return None
  175.     filename = os.path.join(self.dir, self.prefix+id)
  176.     f=None
  177.     sessionInfo = None
  178.     try:
  179.       f=open(filename, 'r')
  180.       sessionInfo = pickle.load(f)
  181.       f.close()
  182.     except:
  183.       try:
  184.         if f: f.close()
  185.         os.unlink(filename)
  186.       except: pass
  187.     if sessionInfo:
  188.       if time.time() > sessionInfo['expire']:
  189.         self.delete(id)
  190.         return None
  191.       else: return sessionInfo['state']
  192.     else: return None
  193.   def delete(self, id):
  194.     try:
  195.       filename = os.path.join(self.dir, self.prefix+id)
  196.       os.remove(filename)
  197.     except: pass
  198.   def clear(self):
  199.     for id in self.keys():
  200.       self.delete(id)
  201.   def set(self, state, expire, id=None):
  202.     f=None
  203.     try:
  204.       if id:
  205.         filename = os.path.join(self.dir, self.prefix+id)
  206.         f=open(filename, 'w')
  207.       else:
  208.         filename, f, id = openUniqueFile(self.dir, self.prefix, ('%d_' % self.childnum))
  209.       sessionInfo = {}
  210.       sessionInfo['expire'] = int(time.time())+expire
  211.       sessionInfo['state'] = state
  212.       pickle.dump(sessionInfo, f, self.BINARY_MODE)
  213.       f.close()
  214.     except:
  215.       try:
  216.         if f: f.close()
  217.       except: pass
  218.       raise
  219.     return id
  220.   def keys(self):
  221.     sessions = os.listdir(self.dir)
  222.     sessions = filter(lambda s, p=self.prefix: s[:len(p)]==p, sessions)
  223.     sessions = map(lambda s, self=self: s[len(self.prefix):], sessions)
  224.     return sessions
  225.  
  226. # requires unique (dir, prefix)
  227. def openUniqueFile(dir, prefix, unique, mode='w', max=1000000):
  228.   filelock = spyceLock.fileLock(os.path.join(dir, prefix))
  229.   filelock.lock(1)
  230.   try:
  231.     id = "%06d"%random.randrange(max)
  232.     filename = os.path.join(dir, prefix+unique+id)
  233.     while os.path.exists(filename):
  234.       id = str(random.randrange(max))
  235.       filename = os.path.join(dir, prefix+unique+id)
  236.     f = None
  237.     f = open(filename, mode)
  238.     return filename, f, unique+id
  239.   finally:
  240.     filelock.unlock()
  241.  
  242. ##################################################
  243. # Hash file session handlers
  244. #
  245.  
  246. class sessionHandlerDBM(sessionHandler):
  247.   def __init__(self, sessionModule, filename):
  248.     sessionHandler.__init__(self, sessionModule)
  249.     self.filename = filename
  250.     self.dbm = None
  251.     self.BINARY_MODE = 1
  252.     self.dbm_type = None  # redefine in subclass
  253.   def getHandlerID(self):
  254.     return 'session_'+self.dbm_type, self.childnum, self.filename
  255.   def _open(self):
  256.     raise 'need to implement'
  257.   def _close(self):
  258.     if self.dbm:
  259.       self.dbm.close()
  260.       self.dbm = None
  261.   def get(self, id):
  262.     if not id: return None
  263.     self._open()
  264.     try:
  265.       expire, state = None, None
  266.       if self.dbm.has_key(id):
  267.         expire, state = pickle.loads(self.dbm[id])
  268.       if expire!=None and time.time() > expire:
  269.         self.delete(id)
  270.         state = None
  271.       return state
  272.     finally:
  273.       self._close()
  274.   def delete(self, id):
  275.     self._open()
  276.     try:
  277.       if self.dbm.has_key(id):
  278.         del self.dbm[id]
  279.     finally:
  280.       self._close()
  281.   def clear(self):
  282.     if os.path.exists(self.filename):
  283.       os.unlink(self.filename)
  284.   def set(self, state, expire, id=None):
  285.     self._open()
  286.     try:
  287.       if not id:
  288.         id = generateKey(self.dbm, self.childnum)
  289.       value = pickle.dumps( (int(time.time())+expire, state), self.BINARY_MODE)
  290.       self.dbm[id] = value
  291.       return id
  292.     finally:
  293.       self._close()
  294.   def keys(self):
  295.     self._open()
  296.     try:
  297.       return self.dbm.keys()
  298.     finally:
  299.       self._close()
  300.  
  301. def opendb(dbm_session_handler, module, filename, flags):
  302.   mod = __import__(module)
  303.   if not dbm_session_handler.dbm:
  304.     dbm_session_handler.dbm = mod.open(filename, flags)
  305.   
  306. class session_gdbm(sessionHandlerDBM):
  307.   def __init__(self, sessionModule, filename):
  308.     sessionHandlerDBM.__init__(self, sessionModule, filename)
  309.     self.dbm_type = 'gdbm'
  310.   def _open(self):
  311.     opendb(self, self.dbm_type, self.filename, 'cu')
  312.  
  313. class session_bsddb(sessionHandlerDBM):
  314.   def __init__(self, sessionModule, filename):
  315.     sessionHandlerDBM.__init__(self, sessionModule, filename)
  316.     self.dbm_type = 'bsddb'
  317.   def _open(self):
  318.     opendb(self, 'dbhash', self.filename, 'c')
  319.  
  320. def generateKey(hash, prefix, max = 1000000):
  321.   prefix = str(prefix)+'_'
  322.   key = random.randrange(max)
  323.   while hash.has_key(prefix+str(key)):
  324.     key = random.randrange(max)
  325.   key = prefix+str(key)
  326.   hash[key] = pickle.dumps(None, 1)
  327.   return key
  328.  
  329.  
  330. ##################################################
  331. # User callback session handlers
  332. #
  333.  
  334. class session_user(sessionHandler):
  335.   '''User-callback session handler'''
  336.   def __init__(self, sessionModule, getf, setf, delf, idsf, info=None):
  337.     self.serverID = sessionModule._api.getServerID()
  338.     self.info = info
  339.     self.getf = getf
  340.     self.setf = setf
  341.     self.delf = delf
  342.     self.idsf = idsf
  343.   def getHandlerID(self):
  344.     return 'session_user', self.serverID, self.info
  345.   def get(self, id):  # method should delete, if session is stale
  346.     return self.getf(self.info, id)
  347.   def set(self, state, expire, id):
  348.     return self.setf(self.info, state, expire, self.serverID, id)
  349.   def delete(self, id):
  350.     return self.delf(self.info, id)
  351.   def keys(self):
  352.     return self.idsf(self.info)
  353.   def clear(self):
  354.     for id in self.keys():
  355.       self.delete(id)
  356.  
  357. ##################################################
  358. # database-based session handlers
  359. #
  360.  
  361. # rimtodo: database-based session handler
  362.  
  363.