diff -r d0425225ce52 -r 6e1ef32fbd82 VirtualMailManager/__init__.py --- a/VirtualMailManager/__init__.py Thu Feb 04 19:08:01 2010 +0000 +++ b/VirtualMailManager/__init__.py Fri Feb 05 20:13:32 2010 +0000 @@ -8,8 +8,25 @@ import re import locale -from constants.VERSION import * -import constants.ERROR as ERR +from encodings.idna import ToASCII, ToUnicode + +from VirtualMailManager.constants.ERROR import \ + DOMAIN_INVALID, DOMAIN_TOO_LONG, NOT_EXECUTABLE, NO_SUCH_BINARY, \ + NO_SUCH_DIRECTORY +from VirtualMailManager.constants.VERSION import * +from VirtualMailManager.Exceptions import VMMException + + +__all__ = [ + # imported modules + 'os', 're', 'locale', + # version information from VERSION + '__author__', '__date__', '__version__', + # error codes + 'ENCODING', 'ace2idna', 'chk_domainname', 'exec_ok', 'expand_path', + 'get_unicode', 'idn2ascii', 'is_dir', +] + # Try to set all of the locales according to the current # environment variables and get the character encoding. @@ -19,24 +36,9 @@ locale.setlocale(locale.LC_ALL, 'C') ENCODING = locale.nl_langinfo(locale.CODESET) -def w_std(*args): - """Writes each arg of args, encoded in the current ENCODING, to stdout and - appends a newline.""" - _write = os.sys.stdout.write - for arg in args: - _write(arg.encode(ENCODING, 'replace')) - _write('\n') +RE_ASCII_CHARS = """^[\x20-\x7E]*$""" +RE_DOMAIN = """^(?:[a-z0-9-]{1,63}\.){1,}[a-z]{2,6}$""" -def w_err(code, *args): - """Writes each arg of args, encoded in the current ENCODING, to stderr and - appends a newline. - This function additional interrupts the program execution and uses 'code' - system exit status.""" - _write = os.sys.stderr.write - for arg in args: - _write(arg.encode(ENCODING, 'replace')) - _write('\n') - os.sys.exit(code) def get_unicode(string): """Converts `string` to `unicode`, if necessary.""" @@ -44,14 +46,61 @@ return string return unicode(string, ENCODING, 'replace') -__all__ = [ - # imported modules - 'os', 're', 'locale', - # version information from VERSION - '__author__', '__date__', '__version__', - # error codes - 'ERR', - # defined stuff - 'ENCODING', 'get_unicode', 'w_std', 'w_err' - ] -# EOF +def expand_path(path): + """Expands paths, starting with ``.`` or ``~``, to an absolute path.""" + if path.startswith('.'): + return os.path.abspath(path) + if path.startswith('~'): + return os.path.expanduser(path) + return path + +def is_dir(path): + """Checks if ``path`` is a directory. + + Throws a `VMMException` if ``path`` is not a directory. + """ + path = expand_path(path) + if not os.path.isdir(path): + 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. + + Throws a `VMMException` if the ``binary`` isn't a file or is not + executable. + """ + binary = expand_path(binary) + if not os.path.isfile(binary): + raise VMMException(_(u'“%s” is not a file') % get_unicode(binary), + NO_SUCH_BINARY) + if not os.access(binary, os.X_OK): + raise VMMException(_(u'File is not executable: “%s”') % \ + 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): + """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 + like a valid domain name (label.label.label). + """ + if not re.match(RE_ASCII_CHARS, 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, + DOMAIN_INVALID) + return domainname