1# Authors:
2#   Trevor Perrin
3#   Martin von Loewis - python 3 port
4#
5# See the LICENSE file for legal information regarding use of this file.
6
7"""Base class for SharedKeyDB and VerifierDB."""
8
9try:
10    import anydbm
11except ImportError:
12    # Python 3
13    import dbm as anydbm
14import threading
15
16class BaseDB(object):
17    def __init__(self, filename, type):
18        self.type = type
19        self.filename = filename
20        if self.filename:
21            self.db = None
22        else:
23            self.db = {}
24        self.lock = threading.Lock()
25
26    def create(self):
27        """Create a new on-disk database.
28
29        @raise anydbm.error: If there's a problem creating the database.
30        """
31        if self.filename:
32            self.db = anydbm.open(self.filename, "n") #raises anydbm.error
33            self.db["--Reserved--type"] = self.type
34            self.db.sync()
35        else:
36            self.db = {}
37
38    def open(self):
39        """Open a pre-existing on-disk database.
40
41        @raise anydbm.error: If there's a problem opening the database.
42        @raise ValueError: If the database is not of the right type.
43        """
44        if not self.filename:
45            raise ValueError("Can only open on-disk databases")
46        self.db = anydbm.open(self.filename, "w") #raises anydbm.error
47        try:
48            if self.db["--Reserved--type"] != self.type:
49                raise ValueError("Not a %s database" % self.type)
50        except KeyError:
51            raise ValueError("Not a recognized database")
52
53    def __getitem__(self, username):
54        if self.db == None:
55            raise AssertionError("DB not open")
56
57        self.lock.acquire()
58        try:
59            valueStr = self.db[username]
60        finally:
61            self.lock.release()
62
63        return self._getItem(username, valueStr)
64
65    def __setitem__(self, username, value):
66        if self.db == None:
67            raise AssertionError("DB not open")
68
69        valueStr = self._setItem(username, value)
70
71        self.lock.acquire()
72        try:
73            self.db[username] = valueStr
74            if self.filename:
75                self.db.sync()
76        finally:
77            self.lock.release()
78
79    def __delitem__(self, username):
80        if self.db == None:
81            raise AssertionError("DB not open")
82
83        self.lock.acquire()
84        try:
85            del(self.db[username])
86            if self.filename:
87                self.db.sync()
88        finally:
89            self.lock.release()
90
91    def __contains__(self, username):
92        """Check if the database contains the specified username.
93
94        @type username: str
95        @param username: The username to check for.
96
97        @rtype: bool
98        @return: True if the database contains the username, False
99        otherwise.
100
101        """
102        if self.db == None:
103            raise AssertionError("DB not open")
104
105        self.lock.acquire()
106        try:
107            return self.db.has_key(username)
108        finally:
109            self.lock.release()
110
111    def check(self, username, param):
112        value = self.__getitem__(username)
113        return self._checkItem(value, username, param)
114
115    def keys(self):
116        """Return a list of usernames in the database.
117
118        @rtype: list
119        @return: The usernames in the database.
120        """
121        if self.db == None:
122            raise AssertionError("DB not open")
123
124        self.lock.acquire()
125        try:
126            usernames = self.db.keys()
127        finally:
128            self.lock.release()
129        usernames = [u for u in usernames if not u.startswith("--Reserved--")]
130        return usernames
131