16 from encodings.idna import ToASCII, ToUnicode |
16 from encodings.idna import ToASCII, ToUnicode |
17 |
17 |
18 from VirtualMailManager.constants.ERROR import \ |
18 from VirtualMailManager.constants.ERROR import \ |
19 DOMAIN_INVALID, DOMAIN_TOO_LONG, LOCALPART_INVALID, LOCALPART_TOO_LONG, \ |
19 DOMAIN_INVALID, DOMAIN_TOO_LONG, LOCALPART_INVALID, LOCALPART_TOO_LONG, \ |
20 NOT_EXECUTABLE, NO_SUCH_BINARY, NO_SUCH_DIRECTORY |
20 NOT_EXECUTABLE, NO_SUCH_BINARY, NO_SUCH_DIRECTORY |
21 from VirtualMailManager.constants.VERSION import * |
21 from VirtualMailManager.constants.version import __author__, __date__, \ |
|
22 __version__ |
22 from VirtualMailManager.Exceptions import VMMException |
23 from VirtualMailManager.Exceptions import VMMException |
23 |
24 |
24 |
25 |
25 __all__ = [ |
26 __all__ = [ |
26 # imported modules |
|
27 'os', 're', 'locale', |
|
28 # version information from VERSION |
27 # version information from VERSION |
29 '__author__', '__date__', '__version__', |
28 '__author__', '__date__', '__version__', |
30 # defined stuff |
29 # defined stuff |
31 'ENCODING', 'ace2idna', 'check_domainname', 'check_localpart', 'exec_ok', |
30 'ENCODING', 'ace2idna', 'check_domainname', 'check_localpart', 'exec_ok', |
32 'expand_path', 'get_unicode', 'idn2ascii', 'is_dir', |
31 'expand_path', 'get_unicode', 'idn2ascii', 'is_dir', |
39 locale.setlocale(locale.LC_ALL, '') |
38 locale.setlocale(locale.LC_ALL, '') |
40 except locale.Error: |
39 except locale.Error: |
41 locale.setlocale(locale.LC_ALL, 'C') |
40 locale.setlocale(locale.LC_ALL, 'C') |
42 ENCODING = locale.nl_langinfo(locale.CODESET) |
41 ENCODING = locale.nl_langinfo(locale.CODESET) |
43 |
42 |
44 RE_DOMAIN = r"^(?:[a-z0-9-]{1,63}\.){1,}[a-z]{2,6}$" |
43 # there may be many domain and e-mail address checks |
45 RE_LOCALPART = r"[^\w!#$%&'\*\+-\.\/=?^_`{\|}~]" |
44 RE_DOMAIN = re.compile(r"^(?:[a-z0-9-]{1,63}\.){1,}[a-z]{2,6}$") |
|
45 RE_LOCALPART = re.compile(r"[^\w!#$%&'\*\+-\.\/=?^_`{\|}~]") |
|
46 |
|
47 gettext.install('vmm', '/usr/local/share/locale', unicode=1) |
46 |
48 |
47 |
49 |
48 # there may be many domain and e-mail address checks |
50 _ = lambda msg: msg |
49 re_obj_domain = re.compile(RE_DOMAIN) |
|
50 re_obj_localpart = re.compile(RE_LOCALPART) |
|
51 |
|
52 |
|
53 gettext.install('vmm', '/usr/local/share/locale', unicode=1) |
|
54 |
51 |
55 |
52 |
56 def get_unicode(string): |
53 def get_unicode(string): |
57 """Converts `string` to `unicode`, if necessary.""" |
54 """Converts `string` to `unicode`, if necessary.""" |
58 if isinstance(string, unicode): |
55 if isinstance(string, unicode): |
71 |
68 |
72 def is_dir(path): |
69 def is_dir(path): |
73 """Checks if `path` is a directory. |
70 """Checks if `path` is a directory. |
74 |
71 |
75 Throws a `VMMException` if `path` is not a directory. |
72 Throws a `VMMException` if `path` is not a directory. |
|
73 |
76 """ |
74 """ |
77 path = expand_path(path) |
75 path = expand_path(path) |
78 if not os.path.isdir(path): |
76 if not os.path.isdir(path): |
79 raise VMMException(_(u"'%s' is not a directory") % |
77 raise VMMException(_(u"'%s' is not a directory") % |
80 get_unicode(path), NO_SUCH_DIRECTORY) |
78 get_unicode(path), NO_SUCH_DIRECTORY) |
84 def exec_ok(binary): |
82 def exec_ok(binary): |
85 """Checks if the `binary` exists and if it is executable. |
83 """Checks if the `binary` exists and if it is executable. |
86 |
84 |
87 Throws a `VMMException` if the `binary` isn't a file or is not |
85 Throws a `VMMException` if the `binary` isn't a file or is not |
88 executable. |
86 executable. |
|
87 |
89 """ |
88 """ |
90 binary = expand_path(binary) |
89 binary = expand_path(binary) |
91 if not os.path.isfile(binary): |
90 if not os.path.isfile(binary): |
92 raise VMMException(_(u"'%s' is not a file") % get_unicode(binary), |
91 raise VMMException(_(u"'%s' is not a file") % get_unicode(binary), |
93 NO_SUCH_BINARY) |
92 NO_SUCH_BINARY) |
108 |
107 |
109 |
108 |
110 def check_domainname(domainname): |
109 def check_domainname(domainname): |
111 """Returns the validated domain name `domainname`. |
110 """Returns the validated domain name `domainname`. |
112 |
111 |
113 It also converts the name of the domain from IDN to ASCII, if necessary. |
112 It also converts the name of the domain from IDN to ASCII, if |
|
113 necessary. |
114 |
114 |
115 Throws an `VMMException`, if the domain name is too long or doesn't look |
115 Throws an `VMMException`, if the domain name is too long or doesn't |
116 like a valid domain name (label.label.label). |
116 look like a valid domain name (label.label.label). |
|
117 |
117 """ |
118 """ |
118 if not re_obj_domain.match(domainname): |
119 if not RE_DOMAIN.match(domainname): |
119 domainname = idn2ascii(domainname) |
120 domainname = idn2ascii(domainname) |
120 if len(domainname) > 255: |
121 if len(domainname) > 255: |
121 raise VMMException(_(u'The domain name is too long'), DOMAIN_TOO_LONG) |
122 raise VMMException(_(u'The domain name is too long'), DOMAIN_TOO_LONG) |
122 if not re_obj_domain.match(domainname): |
123 if not RE_DOMAIN.match(domainname): |
123 raise VMMException(_(u'The domain name %r is invalid') % domainname, |
124 raise VMMException(_(u'The domain name %r is invalid') % domainname, |
124 DOMAIN_INVALID) |
125 DOMAIN_INVALID) |
125 return domainname |
126 return domainname |
126 |
127 |
127 |
128 |
128 def check_localpart(localpart): |
129 def check_localpart(localpart): |
129 """Returns the validated local-part `localpart`. |
130 """Returns the validated local-part `localpart`. |
130 |
131 |
131 Throws a `VMMException` if the local-part is too long or contains |
132 Throws a `VMMException` if the local-part is too long or contains |
132 invalid characters. |
133 invalid characters. |
|
134 |
133 """ |
135 """ |
134 if len(localpart) > 64: |
136 if len(localpart) > 64: |
135 raise VMMException(_(u'The local-part %r is too long') % localpart, |
137 raise VMMException(_(u'The local-part %r is too long') % localpart, |
136 LOCALPART_TOO_LONG) |
138 LOCALPART_TOO_LONG) |
137 invalid_chars = set(re_obj_localpart.findall(localpart)) |
139 invalid_chars = set(RE_LOCALPART.findall(localpart)) |
138 if invalid_chars: |
140 if invalid_chars: |
139 i_chars = u''.join((u'"%s" ' % c for c in invalid_chars)) |
141 i_chars = u''.join((u'"%s" ' % c for c in invalid_chars)) |
140 raise VMMException(_(u"The local-part %(l_part)r contains invalid \ |
142 raise VMMException(_(u"The local-part %(l_part)r contains invalid \ |
141 characters: %(i_chars)s") % |
143 characters: %(i_chars)s") % |
142 {'l_part': localpart, 'i_chars': i_chars}, |
144 {'l_part': localpart, 'i_chars': i_chars}, |
143 LOCALPART_INVALID) |
145 LOCALPART_INVALID) |
144 return localpart |
146 return localpart |
|
147 |
|
148 |
|
149 del _ |