]> code.delx.au - pymsnt/blob - src/xdb.py
Google Talk fixes
[pymsnt] / src / xdb.py
1 # Copyright 2004-2005 James Bunton <james@delx.cjb.net>
2 # Licensed for distribution under the GPL version 2, check COPYING for details
3
4 from tlib import xmlw
5 from debug import LogEvent, INFO, WARN
6 import os
7 import os.path
8 import shutil
9 import config
10
11 X = os.path.sep
12 SPOOL_UMASK = 0077
13
14
15 def unmangle(file):
16 chunks = file.split("%")
17 end = chunks.pop()
18 file = "%s@%s" % ("%".join(chunks), end)
19 return file
20
21 def mangle(jid):
22 return jid.replace("@", "%")
23
24
25 class XDB:
26 """
27 Class for storage of data.
28
29 Create one instance of the class for each XDB 'folder' you want.
30 Call request()/set() with the xdbns argument you wish to retrieve
31 """
32 def __init__(self, name, mangle=False):
33 """ Creates an XDB object. If mangle is True then any '@' signs in filenames will be changed to '%' """
34 self.name = os.path.join(os.path.abspath(config.spooldir), name)
35 if not os.path.exists(self.name):
36 os.makedirs(self.name)
37 self.mangle = mangle
38
39 def __getFile(self, file):
40 if(self.mangle):
41 file = mangle(file)
42
43 hash = file[0:2]
44 document = xmlw.parseFile(self.name + X + hash + X + file + ".xml")
45
46 return document
47
48 def __writeFile(self, file, text):
49 if(self.mangle):
50 file = mangle(file)
51
52 prev_umask = os.umask(SPOOL_UMASK)
53 hash = file[0:2]
54 pre = self.name + X + hash + X
55 if not os.path.exists(pre):
56 os.makedirs(pre)
57 try:
58 f = open(pre + file + ".xml.new", "w")
59 f.write(text)
60 f.close()
61 shutil.move(pre + file + ".xml.new", pre + file + ".xml")
62 except IOError, e:
63 LogEvent(WARN, "", "IOError " + str(e))
64 raise
65 os.umask(prev_umask)
66
67 def files(self):
68 """ Returns a list containing the files in the current XDB database """
69 files = []
70 for dir in os.listdir(self.name):
71 if(os.path.isdir(self.name + X + dir)):
72 files.extend(os.listdir(self.name + X + dir))
73 if self.mangle:
74 files = [unmangle(x)[:-4] for x in files]
75 else:
76 files = [x[:-4] for x in files]
77
78 while files.count(''):
79 files.remove('')
80
81 return files
82
83 def request(self, file, xdbns):
84 """ Requests a specific xdb namespace from the XDB 'file' """
85 try:
86 document = self.__getFile(file)
87 for child in document.elements():
88 if(child.getAttribute("xdbns") == xdbns):
89 return child
90 except:
91 return None
92
93 def set(self, file, xdbns, element):
94 """ Sets a specific xdb namespace in the XDB 'file' to element """
95 try:
96 element.attributes["xdbns"] = xdbns
97 document = None
98 try:
99 document = self.__getFile(file)
100 except IOError:
101 pass
102 if(not document):
103 document = xmlw.Element((None, "xdb"))
104
105 # Remove the existing node (if any)
106 for child in document.elements():
107 if(child.getAttribute("xdbns") == xdbns):
108 document.children.remove(child)
109 # Add the new one
110 document.addChild(element)
111
112 self.__writeFile(file, document.toXml())
113 except IOError, e:
114 LogEvent(WARN, "", "IOError " + str(e))
115 raise
116
117 def remove(self, file):
118 """ Removes an XDB file """
119 file = self.name + X + file[0:2] + X + file + ".xml"
120 if(self.mangle):
121 file = mangle(file)
122 try:
123 os.remove(file)
124 except IOError, e:
125 LogEvent(WARN, "", "IOError " + str(e))
126 raise
127
128
129