1 #$Id: sessions.py,v 1.6 2003-09-05 21:05:18 jlgijsbers Exp $
2 """
3 This module defines a very basic store that's used by the CGI interface
4 to store session and one-time-key information.
6 Yes, it's called "sessions" - because originally it only defined a session
7 class. It's now also used for One Time Key handling too.
9 """
11 import anydbm, whichdb, os, marshal
13 class BasicDatabase:
14 ''' Provide a nice encapsulation of an anydbm store.
16 Keys are id strings, values are automatically marshalled data.
17 '''
18 _db_type = None
20 def __init__(self, config):
21 self.config = config
22 self.dir = config.DATABASE
23 # ensure files are group readable and writable
24 os.umask(0002)
26 def clear(self):
27 path = os.path.join(self.dir, self.name)
28 if os.path.exists(path):
29 os.remove(path)
30 elif os.path.exists(path+'.db'): # dbm appends .db
31 os.remove(path+'.db')
33 def cache_db_type(self, path):
34 ''' determine which DB wrote the class file, and cache it as an
35 attribute of __class__ (to allow for subclassed DBs to be
36 different sorts)
37 '''
38 db_type = ''
39 if os.path.exists(path):
40 db_type = whichdb.whichdb(path)
41 if not db_type:
42 raise hyperdb.DatabaseError, "Couldn't identify database type"
43 elif os.path.exists(path+'.db'):
44 # if the path ends in '.db', it's a dbm database, whether
45 # anydbm says it's dbhash or not!
46 db_type = 'dbm'
47 self.__class__._db_type = db_type
49 def get(self, infoid, value):
50 db = self.opendb('c')
51 try:
52 if db.has_key(infoid):
53 values = marshal.loads(db[infoid])
54 else:
55 return None
56 return values.get(value, None)
57 finally:
58 db.close()
60 def getall(self, infoid):
61 db = self.opendb('c')
62 try:
63 return marshal.loads(db[infoid])
64 finally:
65 db.close()
67 def set(self, infoid, **newvalues):
68 db = self.opendb('c')
69 try:
70 if db.has_key(infoid):
71 values = marshal.loads(db[infoid])
72 else:
73 values = {}
74 values.update(newvalues)
75 db[infoid] = marshal.dumps(values)
76 finally:
77 db.close()
79 def list(self):
80 db = self.opendb('r')
81 try:
82 return db.keys()
83 finally:
84 db.close()
86 def destroy(self, infoid):
87 db = self.opendb('c')
88 try:
89 if db.has_key(infoid):
90 del db[infoid]
91 finally:
92 db.close()
94 def opendb(self, mode):
95 '''Low-level database opener that gets around anydbm/dbm
96 eccentricities.
97 '''
98 # figure the class db type
99 path = os.path.join(os.getcwd(), self.dir, self.name)
100 if self._db_type is None:
101 self.cache_db_type(path)
103 db_type = self._db_type
105 # new database? let anydbm pick the best dbm
106 if not db_type:
107 return anydbm.open(path, 'c')
109 # open the database with the correct module
110 dbm = __import__(db_type)
111 return dbm.open(path, mode)
113 def commit(self):
114 pass
116 class Sessions(BasicDatabase):
117 name = 'sessions'
119 class OneTimeKeys(BasicDatabase):
120 name = 'otks'