-# Copyright 2004 James Bunton <james@delx.cjb.net>
+# Copyright 2004-2005 James Bunton <james@delx.cjb.net>
# Licensed for distribution under the GPL version 2, check COPYING for details
-import utils
-if(utils.checkTwisted()):
- from twisted.xish.domish import Element
-else:
- from tlib.domish import Element
-
+from tlib import xmlw
+from debug import LogEvent, INFO, WARN
import os
import os.path
-import debug
+import shutil
import config
-import legacy
-SPOOL_UMASK = 0177
+X = os.path.sep
+SPOOL_UMASK = 0077
+
+
+def unmangle(file):
+ chunks = file.split("%")
+ end = chunks.pop()
+ file = "%s@%s" % ("%".join(chunks), end)
+ return file
+
+def mangle(jid):
+ return jid.replace("@", "%")
+
class XDB:
"""
- Class for storage of data. Compatible with xdb_file from Jabberd1.4.x
- Allows PyMSN-t to be compatible with MSN-t
+ Class for storage of data.
Create one instance of the class for each XDB 'folder' you want.
Call request()/set() with the xdbns argument you wish to retrieve
"""
def __init__(self, name, mangle=False):
""" Creates an XDB object. If mangle is True then any '@' signs in filenames will be changed to '%' """
- self.name = utils.doPath(config.spooldir) + '/' + name
- if not os.path.exists(self.name) :
+ self.name = os.path.join(os.path.abspath(config.spooldir), name)
+ if not os.path.exists(self.name):
os.makedirs(self.name)
self.mangle = mangle
def __getFile(self, file):
if(self.mangle):
- file = file.replace('@', '%')
+ file = mangle(file)
- document = utils.parseFile(self.name + "/" + file + ".xml")
+ hash = file[0:2]
+ document = xmlw.parseFile(self.name + X + hash + X + file + ".xml")
return document
def __writeFile(self, file, text):
if(self.mangle):
- file = file.replace('@', '%')
+ file = mangle(file)
prev_umask = os.umask(SPOOL_UMASK)
- f = open(self.name + "/" + file + ".xml", "w")
- f.write(text)
- f.close()
+ hash = file[0:2]
+ pre = self.name + X + hash + X
+ if not os.path.exists(pre):
+ os.makedirs(pre)
+ try:
+ f = open(pre + file + ".xml.new", "w")
+ f.write(text)
+ f.close()
+ shutil.move(pre + file + ".xml.new", pre + file + ".xml")
+ except IOError, e:
+ LogEvent(WARN, "", "IOError " + str(e))
+ raise
os.umask(prev_umask)
+ def files(self):
+ """ Returns a list containing the files in the current XDB database """
+ files = []
+ for dir in os.listdir(self.name):
+ if(os.path.isdir(self.name + X + dir)):
+ files.extend(os.listdir(self.name + X + dir))
+ if self.mangle:
+ files = [unmangle(x)[:-4] for x in files]
+ else:
+ files = [x[:-4] for x in files]
+
+ while files.count(''):
+ files.remove('')
+
+ return files
def request(self, file, xdbns):
""" Requests a specific xdb namespace from the XDB 'file' """
except IOError:
pass
if(not document):
- document = Element((None, "xdb"))
+ document = xmlw.Element((None, "xdb"))
# Remove the existing node (if any)
for child in document.elements():
document.addChild(element)
self.__writeFile(file, document.toXml())
- except:
- debug.log("XDB error writing entry %s to file %s" % (xdbns, file))
+ except IOError, e:
+ LogEvent(WARN, "", "IOError " + str(e))
raise
def remove(self, file):
""" Removes an XDB file """
- file = self.name + "/" + file + ".xml"
+ file = self.name + X + file[0:2] + X + file + ".xml"
if(self.mangle):
- file = file.replace('@', '%')
+ file = mangle(file)
try:
os.remove(file)
- except:
- debug.log("XDB error removing file " + file)
+ except IOError, e:
+ LogEvent(WARN, "", "IOError " + str(e))
raise
+
+