31 from Domain import Domain |
31 from Domain import Domain |
32 |
32 |
33 SALTCHARS = './0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' |
33 SALTCHARS = './0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' |
34 RE_ASCII_CHARS = """^[\x20-\x7E]*$""" |
34 RE_ASCII_CHARS = """^[\x20-\x7E]*$""" |
35 RE_DOMAIN = """^(?:[a-z0-9-]{1,63}\.){1,}[a-z]{2,6}$""" |
35 RE_DOMAIN = """^(?:[a-z0-9-]{1,63}\.){1,}[a-z]{2,6}$""" |
|
36 RE_DOMAIN_SRCH = """^[a-z0-9-\.]+$""" |
36 RE_LOCALPART = """[^\w!#$%&'\*\+-\.\/=?^_`{\|}~]""" |
37 RE_LOCALPART = """[^\w!#$%&'\*\+-\.\/=?^_`{\|}~]""" |
37 RE_MAILLOCATION = """^[\w]{1,20}$""" |
38 RE_MAILLOCATION = """^[\w]{1,20}$""" |
38 re.compile(RE_ASCII_CHARS) |
|
39 re.compile(RE_DOMAIN) |
|
40 |
39 |
41 ENCODING_IN = sys.getfilesystemencoding() |
40 ENCODING_IN = sys.getfilesystemencoding() |
42 ENCODING_OUT = sys.stdout.encoding or sys.getfilesystemencoding() |
41 ENCODING_OUT = sys.stdout.encoding or sys.getfilesystemencoding() |
43 |
42 |
44 gettext.bindtextdomain('vmm', '/usr/local/share/locale') |
43 gettext.bindtextdomain('vmm', '/usr/local/share/locale') |
115 raise |
114 raise |
116 |
115 |
117 def __dbConnect(self): |
116 def __dbConnect(self): |
118 """Creates a pyPgSQL.PgSQL.connection instance.""" |
117 """Creates a pyPgSQL.PgSQL.connection instance.""" |
119 try: |
118 try: |
120 self.__dbh = PgSQL.connect( |
119 self.__dbh = PgSQL.connect( |
121 database=self.__Cfg.get('database', 'name'), |
120 database=self.__Cfg.get('database', 'name'), |
122 user=self.__Cfg.get('database', 'user'), |
121 user=self.__Cfg.get('database', 'user'), |
123 host=self.__Cfg.get('database', 'host'), |
122 host=self.__Cfg.get('database', 'host'), |
124 password=self.__Cfg.get('database', 'pass'), |
123 password=self.__Cfg.get('database', 'pass'), |
125 client_encoding='utf8', unicode_results=True) |
124 client_encoding='utf8', unicode_results=True) |
174 """Validates the domain name of an e-mail address. |
173 """Validates the domain name of an e-mail address. |
175 |
174 |
176 Keyword arguments: |
175 Keyword arguments: |
177 domainname -- the domain name that should be validated |
176 domainname -- the domain name that should be validated |
178 """ |
177 """ |
|
178 re.compile(RE_ASCII_CHARS) |
179 if not re.match(RE_ASCII_CHARS, domainname): |
179 if not re.match(RE_ASCII_CHARS, domainname): |
180 domainname = self.__idn2ascii(domainname) |
180 domainname = self.idn2ascii(domainname) |
181 if len(domainname) > 255: |
181 if len(domainname) > 255: |
182 raise VMMException((_('The domain name is too long.'), |
182 raise VMMException((_('The domain name is too long.'), |
183 ERR.DOMAIN_TOO_LONG)) |
183 ERR.DOMAIN_TOO_LONG)) |
|
184 re.compile(RE_DOMAIN) |
184 if not re.match(RE_DOMAIN, domainname): |
185 if not re.match(RE_DOMAIN, domainname): |
185 raise VMMException((_('The domain name is invalid.'), |
186 raise VMMException((_('The domain name is invalid.'), |
186 ERR.DOMAIN_INVALID)) |
187 ERR.DOMAIN_INVALID)) |
187 return domainname |
188 return domainname |
188 |
189 |
452 def domain_info(self, domainname, detailed=None): |
453 def domain_info(self, domainname, detailed=None): |
453 dom = self.__getDomain(domainname) |
454 dom = self.__getDomain(domainname) |
454 dominfo = dom.getInfo() |
455 dominfo = dom.getInfo() |
455 if dominfo['domainname'].startswith('xn--'): |
456 if dominfo['domainname'].startswith('xn--'): |
456 dominfo['domainname'] += ' (%s)'\ |
457 dominfo['domainname'] += ' (%s)'\ |
457 % self.__ace2idna(dominfo['domainname']) |
458 % self.ace2idna(dominfo['domainname']) |
458 if dominfo['aliases'] is None: |
459 if dominfo['aliases'] is None: |
459 dominfo['aliases'] = 0 |
460 dominfo['aliases'] = 0 |
460 if detailed is None: |
461 if detailed is None: |
461 return dominfo |
462 return dominfo |
462 elif detailed == 'detailed': |
463 elif detailed == 'detailed': |
463 return dominfo, dom.getAccounts(), dom.getAliases() |
464 return dominfo, dom.getAccounts(), dom.getAliases() |
464 else: |
465 else: |
465 raise VMMDomainException(('%s: »%s«' % (_('Invalid argument'), |
466 raise VMMDomainException(('%s: »%s«' % (_('Invalid argument'), |
466 detailed), ERR.INVALID_OPTION)) |
467 detailed), ERR.INVALID_OPTION)) |
467 |
468 |
|
469 def domain_list(self, pattern=None): |
|
470 from Domain import search |
|
471 like = False |
|
472 if pattern is not None: |
|
473 if pattern.startswith('%') or pattern.endswith('%'): |
|
474 like = True |
|
475 if pattern.startswith('%') and pattern.endswith('%'): |
|
476 domain = pattern[1:-1] |
|
477 elif pattern.startswith('%'): |
|
478 domain = pattern[1:] |
|
479 elif pattern.endswith('%'): |
|
480 domain = pattern[:-1] |
|
481 re.compile(RE_DOMAIN_SRCH) |
|
482 if not re.match(RE_DOMAIN_SRCH, domain): |
|
483 raise VMMException(( |
|
484 _(u'The pattern »%s« contains invalid characters.') % |
|
485 pattern, ERR.DOMAIN_INVALID)) |
|
486 else: |
|
487 pattern = self.__chkDomainname(pattern) |
|
488 self.__dbConnect() |
|
489 return search(self.__dbh, pattern=pattern, like=like) |
|
490 |
468 def user_add(self, emailaddress, password): |
491 def user_add(self, emailaddress, password): |
469 acc = self.__getAccount(emailaddress, password) |
492 acc = self.__getAccount(emailaddress, password) |
470 acc.save(self.__Cfg.get('maildir', 'folder'), |
493 acc.save(self.__Cfg.get('maildir', 'folder'), |
471 self.__Cfg.getboolean('services', 'smtp'), |
494 self.__Cfg.getboolean('services', 'smtp'), |
472 self.__Cfg.getboolean('services', 'pop3'), |
495 self.__Cfg.getboolean('services', 'pop3'), |