Code

remove unused, deprecated import
[roundup.git] / roundup / password.py
index a2f01f52c4c71e569f5b877f3f419c46a3272a03..201a6a979edd837918fdb5c6dd8e16c8039994c4 100644 (file)
 # FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-# 
-# $Id: password.py,v 1.9 2003-04-10 05:12:41 richard Exp $
+#
+# $Id: password.py,v 1.15 2005-12-25 15:38:40 a1s Exp $
 
-__doc__ = """
-Password handling (encoding, decoding).
+"""Password handling (encoding, decoding).
 """
+__docformat__ = 'restructuredtext'
 
-import sha, re, string, random
+import re, string, random
+from roundup.anypy.hashlib_ import md5, sha1
 try:
     import crypt
-except:
+except ImportError:
     crypt = None
+
+class PasswordValueError(ValueError):
+    """ The password value is not valid """
     pass
 
 def encodePassword(plaintext, scheme, other=None):
-    '''Encrypt the plaintext password.
-    '''
+    """Encrypt the plaintext password.
+    """
     if plaintext is None:
         plaintext = ""
     if scheme == 'SHA':
-        s = sha.sha(plaintext).hexdigest()
+        s = sha1(plaintext).hexdigest()
+    elif scheme == 'MD5':
+        s = md5(plaintext).hexdigest()
     elif scheme == 'crypt' and crypt is not None:
         if other is not None:
-            salt = other[:2]
+            salt = other
         else:
             saltchars = './0123456789'+string.letters
             salt = random.choice(saltchars) + random.choice(saltchars)
@@ -45,7 +51,7 @@ def encodePassword(plaintext, scheme, other=None):
     elif scheme == 'plaintext':
         s = plaintext
     else:
-        raise ValueError, 'Unknown encryption scheme "%s"'%scheme
+        raise PasswordValueError, 'unknown encryption scheme %r'%scheme
     return s
 
 def generatePassword(length=8):
@@ -53,10 +59,10 @@ def generatePassword(length=8):
     return ''.join([random.choice(chars) for x in range(length)])
 
 class Password:
-    '''The class encapsulates a Password property type value in the database. 
+    """The class encapsulates a Password property type value in the database.
 
-    The encoding of the password is one if None, 'SHA' or 'plaintext'. The
-    encodePassword function is used to actually encode the password from
+    The encoding of the password is one if None, 'SHA', 'MD5' or 'plaintext'.
+    The encodePassword function is used to actually encode the password from
     plaintext. The None encoding is used in legacy databases where no
     encoding scheme is identified.
 
@@ -73,43 +79,47 @@ class Password:
     1
     >>> 'not sekrit' != p
     1
-    '''
+    """
 
     default_scheme = 'SHA'        # new encryptions use this scheme
     pwre = re.compile(r'{(\w+)}(.+)')
 
-    def __init__(self, plaintext=None, scheme=None):
-        '''Call setPassword if plaintext is not None.'''
+    def __init__(self, plaintext=None, scheme=None, encrypted=None):
+        """Call setPassword if plaintext is not None."""
         if scheme is None:
             scheme = self.default_scheme
         if plaintext is not None:
-            self.password = encodePassword(plaintext, self.default_scheme)
-            self.scheme = self.default_scheme
+            self.setPassword (plaintext, scheme)
+        elif encrypted is not None:
+            self.unpack(encrypted, scheme)
         else:
-            self.password = None
             self.scheme = self.default_scheme
+            self.password = None
+            self.plaintext = None
 
-    def unpack(self, encrypted):
-        '''Set the password info from the scheme:<encryted info> string
+    def unpack(self, encrypted, scheme=None):
+        """Set the password info from the scheme:<encryted info> string
            (the inverse of __str__)
-        '''
+        """
         m = self.pwre.match(encrypted)
         if m:
             self.scheme = m.group(1)
             self.password = m.group(2)
+            self.plaintext = None
         else:
             # currently plaintext - encrypt
-            self.password = encodePassword(encrypted, self.default_scheme)
-            self.scheme = self.default_scheme
+            self.setPassword(encrypted, scheme)
 
     def setPassword(self, plaintext, scheme=None):
-        '''Sets encrypts plaintext.'''
+        """Sets encrypts plaintext."""
         if scheme is None:
             scheme = self.default_scheme
+        self.scheme = scheme
         self.password = encodePassword(plaintext, scheme)
+        self.plaintext = plaintext
 
     def __cmp__(self, other):
-        '''Compare this password against another password.'''
+        """Compare this password against another password."""
         # check to see if we're comparing instances
         if isinstance(other, Password):
             if self.scheme != other.scheme:
@@ -123,7 +133,7 @@ class Password:
             self.password))
 
     def __str__(self):
-        '''Stringify the encrypted password for database storage.'''
+        """Stringify the encrypted password for database storage."""
         if self.password is None:
             raise ValueError, 'Password not set'
         return '{%s}%s'%(self.scheme, self.password)
@@ -136,6 +146,13 @@ def test():
     assert 'sekrit' == p
     assert 'not sekrit' != p
 
+    # MD5
+    p = Password('sekrit', 'MD5')
+    assert p == 'sekrit'
+    assert p != 'not sekrit'
+    assert 'sekrit' == p
+    assert 'not sekrit' != p
+
     # crypt
     p = Password('sekrit', 'crypt')
     assert p == 'sekrit'
@@ -146,4 +163,4 @@ def test():
 if __name__ == '__main__':
     test()
 
-# vim: set filetype=python ts=4 sw=4 et si
+# vim: set filetype=python sts=4 sw=4 et si :