1 #$Id: sessions.py,v 1.4 2003-02-25 10:19:32 richard 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 def __init__(self, config):
19 self.config = config
20 self.dir = config.DATABASE
21 # ensure files are group readable and writable
22 os.umask(0002)
24 def clear(self):
25 path = os.path.join(self.dir, self.name)
26 if os.path.exists(path):
27 os.remove(path)
28 elif os.path.exists(path+'.db'): # dbm appends .db
29 os.remove(path+'.db')
31 def determine_db_type(self, path):
32 ''' determine which DB wrote the class file
33 '''
34 db_type = ''
35 if os.path.exists(path):
36 db_type = whichdb.whichdb(path)
37 if not db_type:
38 raise hyperdb.DatabaseError, "Couldn't identify database type"
39 elif os.path.exists(path+'.db'):
40 # if the path ends in '.db', it's a dbm database, whether
41 # anydbm says it's dbhash or not!
42 db_type = 'dbm'
43 return db_type
45 def get(self, infoid, value):
46 db = self.opendb('c')
47 try:
48 if db.has_key(infoid):
49 values = marshal.loads(db[infoid])
50 else:
51 return None
52 return values.get(value, None)
53 finally:
54 db.close()
56 def getall(self, infoid):
57 db = self.opendb('c')
58 try:
59 return marshal.loads(db[infoid])
60 finally:
61 db.close()
63 def set(self, infoid, **newvalues):
64 db = self.opendb('c')
65 try:
66 if db.has_key(infoid):
67 values = marshal.loads(db[infoid])
68 else:
69 values = {}
70 values.update(newvalues)
71 db[infoid] = marshal.dumps(values)
72 finally:
73 db.close()
75 def list(self):
76 db = self.opendb('r')
77 try:
78 return db.keys()
79 finally:
80 db.close()
82 def destroy(self, infoid):
83 db = self.opendb('c')
84 try:
85 if db.has_key(infoid):
86 del db[infoid]
87 finally:
88 db.close()
90 def opendb(self, mode):
91 '''Low-level database opener that gets around anydbm/dbm
92 eccentricities.
93 '''
94 # figure the class db type
95 path = os.path.join(os.getcwd(), self.dir, self.name)
96 db_type = self.determine_db_type(path)
98 # new database? let anydbm pick the best dbm
99 if not db_type:
100 return anydbm.open(path, 'c')
102 # open the database with the correct module
103 dbm = __import__(db_type)
104 return dbm.open(path, mode)
106 def commit(self):
107 pass
109 class Sessions(BasicDatabase):
110 name = 'sessions'
112 class OneTimeKeys(BasicDatabase):
113 name = 'otks'