]> code.delx.au - pymsnt/blobdiff - src/xdb.py
Use md5 hashes for spool dir. Moved avatar dir to root of spool dir.
[pymsnt] / src / xdb.py
index 98cdfadcc1688596cdac593023a13c2d9c1fcdc1..e3caf0e97b50d7ff8b24ddf7b220f0f4e290099c 100644 (file)
@@ -1,53 +1,88 @@
-# 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 md5
 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(file):
+       return file.replace("@", "%")
+
+def makeHash(file):
+       return md5.md5(file).hexdigest()[0:3]
+
 
 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 = makeHash(file)
+               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 = makeHash(file)
+               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' """
@@ -69,7 +104,7 @@ class XDB:
                        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():
@@ -79,18 +114,20 @@ class XDB:
                        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
+       
+