VMM: renamed function chk_domainname() -> check_domainname(). v0.6.x
authorPascal Volk <neverseen@users.sourceforge.net>
Thu, 11 Feb 2010 03:08:11 +0000
branchv0.6.x
changeset 199 0684790fff7c
parent 198 02d467e4fbab
child 200 983cf98d5881
VMM: renamed function chk_domainname() -> check_domainname(). Moved EmailAddress.check_localpart() -> VirtualMailManager.check_localpart(). Some small code cleanups in class EmailAddress.
VirtualMailManager/AliasDomain.py
VirtualMailManager/Domain.py
VirtualMailManager/EmailAddress.py
VirtualMailManager/__init__.py
--- a/VirtualMailManager/AliasDomain.py	Wed Feb 10 08:55:51 2010 +0000
+++ b/VirtualMailManager/AliasDomain.py	Thu Feb 11 03:08:11 2010 +0000
@@ -5,7 +5,7 @@
 """Virtual Mail Manager's AliasDomain class to manage alias domains."""
 
 import VirtualMailManager.constants.ERROR as ERR
-from VirtualMailManager import chk_domainname
+from VirtualMailManager import check_domainname
 from VirtualMailManager.Exceptions import VMMAliasDomainException as VADE
 
 class AliasDomain(object):
@@ -13,7 +13,7 @@
     __slots__ = ('__gid', '__name', '_domain', '_dbh')
     def __init__(self, dbh, domainname, targetDomain=None):
         self._dbh = dbh
-        self.__name = chk_domainname(domainname)
+        self.__name = check_domainname(domainname)
         self.__gid = 0
         self._domain = targetDomain
         self._exists()
--- a/VirtualMailManager/Domain.py	Wed Feb 10 08:55:51 2010 +0000
+++ b/VirtualMailManager/Domain.py	Thu Feb 11 03:08:11 2010 +0000
@@ -6,7 +6,7 @@
 
 from random import choice
 
-from VirtualMailManager import chk_domainname
+from VirtualMailManager import check_domainname
 from VirtualMailManager.constants.ERROR import \
      ACCOUNT_AND_ALIAS_PRESENT, ACCOUNT_PRESENT, ALIAS_PRESENT, \
      DOMAIN_ALIAS_EXISTS, DOMAIN_EXISTS, NO_SUCH_DOMAIN
@@ -29,7 +29,7 @@
         transport -- default vmm.cfg/misc/transport  (str)
         """
         self._dbh = dbh
-        self._name = chk_domainname(domainname)
+        self._name = check_domainname(domainname)
         self._basedir = basedir
         if transport is not None:
             self._transport = Transport(self._dbh, transport=transport)
@@ -281,7 +281,7 @@
 
 def search(dbh, pattern=None, like=False):
     if pattern is not None and like is False:
-        pattern = chk_domainname(pattern)
+        pattern = check_domainname(pattern)
     sql = 'SELECT gid, domainname, is_primary FROM domain_name'
     if pattern is None:
         pass
@@ -317,7 +317,7 @@
 
     Raises an `VMMDomainException` if the domain does not exist.
     """
-    domainname = chk_domainname(domainname)
+    domainname = check_domainname(domainname)
     dbc = dbh.cursor()
     dbc.execute('SELECT gid FROM domain_name WHERE domainname=%s', domainname)
     gid = dbc.fetchone()
--- a/VirtualMailManager/EmailAddress.py	Wed Feb 10 08:55:51 2010 +0000
+++ b/VirtualMailManager/EmailAddress.py	Thu Feb 11 03:08:11 2010 +0000
@@ -8,15 +8,14 @@
     Virtual Mail Manager's EmailAddress class to handle e-mail addresses.
 """
 
-import re
-
-from VirtualMailManager import chk_domainname
+from VirtualMailManager import check_domainname, check_localpart
 from VirtualMailManager.constants.ERROR import \
-     DOMAIN_NO_NAME, INVALID_ADDRESS, LOCALPART_INVALID, LOCALPART_TOO_LONG
+     DOMAIN_NO_NAME, INVALID_ADDRESS, LOCALPART_INVALID
 from VirtualMailManager.Exceptions import VMMEmailAddressException as VMMEAE
 
 
 RE_LOCALPART = """[^\w!#$%&'\*\+-\.\/=?^_`{\|}~]"""
+_ = lambda msg: msg
 
 
 class EmailAddress(object):
@@ -58,48 +57,28 @@
         return "EmailAddress('%s@%s')" % (self._localpart, self._domainname)
 
     def __str__(self):
-        return "%s@%s" % (self._localpart, self._domainname)
+        return '%s@%s' % (self._localpart, self._domainname)
 
     def _chk_address(self, address):
         """Checks if the string ``address`` could be used for an e-mail
-        address."""
+        address. If so, it will assign the corresponding values to the
+        attributes `_localpart` and `_domainname`."""
         parts = address.split('@')
         p_len = len(parts)
-        if p_len is 2:
-            self._localpart = check_localpart(parts[0])
-            if len(parts[1]) > 0:
-                self._domainname = chk_domainname(parts[1])
-            else:
-                raise VMMEAE(_(u"Missing domain name after “%s@”.") %
-                             self._localpart, DOMAIN_NO_NAME)
-        elif p_len < 2:
-            raise VMMEAE(_(u"Missing '@' sign in e-mail address “%s”.") %
-                         address, INVALID_ADDRESS)
+        if p_len < 2:
+            raise VMMEAE(_(u"Missing the '@' sign in address %r") % address,
+                         INVALID_ADDRESS)
         elif p_len > 2:
-            raise VMMEAE(_(u"Too many '@' signs in e-mail address “%s”.") %
-                         address, INVALID_ADDRESS)
-
-
-_ = lambda msg: msg
+            raise VMMEAE(_(u"Too many '@' signs in address %r") % address,
+                         INVALID_ADDRESS)
+        if not parts[0]:
+            raise VMMEAE(_(u"Missing local-part in address %r") % address,
+                         LOCALPART_INVALID)
+        if not parts[1]:
+            raise VMMEAE(_(u"Missing domain name in address %r") % address,
+                         DOMAIN_NO_NAME)
+        self._localpart = check_localpart(parts[0])
+        self._domainname = check_domainname(parts[1])
 
 
-def check_localpart(localpart):
-    """Validates the local-part of an e-mail address.
-
-    Argument:
-    localpart -- local-part of the e-mail address that should be validated
-    """
-    if len(localpart) < 1:
-        raise VMMEAE(_(u'No local-part specified.'), LOCALPART_INVALID)
-    if len(localpart) > 64:
-        raise VMMEAE(_(u'The local-part “%s” is too long') % localpart,
-                     LOCALPART_TOO_LONG)
-    invalid_chars = set(re.findall(RE_LOCALPART, localpart))
-    if invalid_chars:
-        i_chrs = u''.join((u'“%s” ' % c for c in invalid_chars))
-        raise VMMEAE(_(u"The local-part “%(l_part)s” contains invalid\
- characters: %(i_chrs)s") % {'l_part': localpart, 'i_chrs': i_chrs},
-                     LOCALPART_INVALID)
-    return localpart
-
 del _
--- a/VirtualMailManager/__init__.py	Wed Feb 10 08:55:51 2010 +0000
+++ b/VirtualMailManager/__init__.py	Thu Feb 11 03:08:11 2010 +0000
@@ -12,8 +12,8 @@
 from encodings.idna import ToASCII, ToUnicode
 
 from VirtualMailManager.constants.ERROR import \
-     DOMAIN_INVALID, DOMAIN_TOO_LONG, NOT_EXECUTABLE, NO_SUCH_BINARY, \
-     NO_SUCH_DIRECTORY
+     DOMAIN_INVALID, DOMAIN_TOO_LONG, LOCALPART_INVALID, LOCALPART_TOO_LONG, \
+     NOT_EXECUTABLE, NO_SUCH_BINARY, NO_SUCH_DIRECTORY
 from VirtualMailManager.constants.VERSION import *
 from VirtualMailManager.Exceptions import VMMException
 
@@ -24,8 +24,8 @@
     # version information from VERSION
     '__author__', '__date__', '__version__',
     # error codes
-    'ENCODING', 'ace2idna', 'chk_domainname', 'exec_ok', 'expand_path',
-    'get_unicode', 'idn2ascii', 'is_dir',
+    'ENCODING', 'ace2idna', 'check_domainname', 'check_localpart', 'exec_ok',
+    'expand_path', 'get_unicode', 'idn2ascii', 'is_dir',
 ]
 
 
@@ -37,18 +37,26 @@
     locale.setlocale(locale.LC_ALL, 'C')
 ENCODING = locale.nl_langinfo(locale.CODESET)
 
-RE_ASCII_CHARS = """^[\x20-\x7E]*$"""
-RE_DOMAIN = """^(?:[a-z0-9-]{1,63}\.){1,}[a-z]{2,6}$"""
+RE_ASCII_CHARS = r"^[\x20-\x7E]*$"
+RE_DOMAIN = r"^(?:[a-z0-9-]{1,63}\.){1,}[a-z]{2,6}$"
+RE_LOCALPART = r"[^\w!#$%&'\*\+-\.\/=?^_`{\|}~]"
+
+
+# there may be many domain and e-mail address checks
+re_obj_domain = re.compile(RE_DOMAIN)
+re_obj_localpart = re.compile(RE_LOCALPART)
 
 
 gettext.install('vmm', '/usr/local/share/locale', unicode=1)
 
+
 def get_unicode(string):
     """Converts `string` to `unicode`, if necessary."""
     if isinstance(string, unicode):
         return string
     return unicode(string, ENCODING, 'replace')
 
+
 def expand_path(path):
     """Expands paths, starting with ``.`` or ``~``, to an absolute path."""
     if path.startswith('.'):
@@ -57,6 +65,7 @@
         return os.path.expanduser(path)
     return path
 
+
 def is_dir(path):
     """Checks if ``path`` is a directory.
 
@@ -64,10 +73,11 @@
     """
     path = expand_path(path)
     if not os.path.isdir(path):
-        raise VMMException(_(u'“%s” is not a directory') % get_unicode(path),
-                           NO_SUCH_DIRECTORY)
+        raise VMMException(_(u'“%s” is not a directory') %
+                            get_unicode(path), NO_SUCH_DIRECTORY)
     return path
 
+
 def exec_ok(binary):
     """Checks if the ``binary`` exists and if it is executable.
 
@@ -83,27 +93,49 @@
                            get_unicode(binary), NOT_EXECUTABLE)
     return binary
 
+
 def idn2ascii(domainname):
     """Converts the idn domain name `domainname` into punycode."""
     return '.'.join([ToASCII(lbl) for lbl in domainname.split('.') if lbl])
 
+
 def ace2idna(domainname):
     """Converts the domain name `domainname` from ACE according to IDNA."""
     return u'.'.join([ToUnicode(lbl) for lbl in domainname.split('.') if lbl])
 
-def chk_domainname(domainname):
+
+def check_domainname(domainname):
     """Returns the validated domain name `domainname`.
 
     It also converts the name of the domain from IDN to ASCII, if necessary.
 
-    Throws an VMMException, if the domain name is too long or doesn't look
+    Throws an `VMMException`, if the domain name is too long or doesn't look
     like a valid domain name (label.label.label).
     """
-    if not re.match(RE_ASCII_CHARS, domainname):
+    if not re_obj_domain.match(domainname):
         domainname = idn2ascii(domainname)
     if len(domainname) > 255:
-        raise VMMException(_(u'The domain name is too long.'), DOMAIN_TOO_LONG)
-    if not re.match(RE_DOMAIN, domainname):
-        raise VMMException(_(u'The domain name “%s” is invalid.') % domainname,
+        raise VMMException(_(u'The domain name is too long'), DOMAIN_TOO_LONG)
+    if not re_obj_domain.match(domainname):
+        raise VMMException(_(u'The domain name %r is invalid') % domainname,
                            DOMAIN_INVALID)
     return domainname
+
+
+def check_localpart(localpart):
+    """Returns the validated local-part *localpart*.
+
+    Throws a `VMMException` if the local-part is too long or contains
+    invalid characters.
+    """
+    if len(localpart) > 64:
+        raise VMMException(_(u'The local-part %r is too long') % localpart,
+                           LOCALPART_TOO_LONG)
+    invalid_chars = set(re_obj_localpart.findall(localpart))
+    if invalid_chars:
+        i_chars = u''.join((u'"%s" ' % c for c in invalid_chars))
+        raise VMMException(_(u"The local-part %(l_part)r contains invalid \
+characters: %(i_chars)s") %
+                           {'l_part': localpart, 'i_chars': i_chars},
+                           LOCALPART_INVALID)
+    return localpart