summaryrefslogtreecommitdiffstats
path: root/ipalib/parameters.py
diff options
context:
space:
mode:
authorMartin Basti <mbasti@redhat.com>2014-03-27 14:36:39 +0100
committerMartin Kosek <mkosek@redhat.com>2014-06-03 15:55:32 +0200
commit64d8da21c6515315d19c8bc76128d15474f4031e (patch)
treec27d5f03789ec6af56a25c00fc71233d5f97a613 /ipalib/parameters.py
parent9c7b0ad156cacbc3afc7d319245090d67ac37e88 (diff)
downloadfreeipa-64d8da21c6515315d19c8bc76128d15474f4031e.tar.gz
freeipa-64d8da21c6515315d19c8bc76128d15474f4031e.tar.xz
freeipa-64d8da21c6515315d19c8bc76128d15474f4031e.zip
DNSNameParam parameter
New param type for domain names Part of ticket: IPA should allow internationalized domain names https://fedorahosted.org/freeipa/ticket/3169 Reviewed-By: Jan Cholasta <jcholast@redhat.com>
Diffstat (limited to 'ipalib/parameters.py')
-rw-r--r--ipalib/parameters.py69
1 files changed, 69 insertions, 0 deletions
diff --git a/ipalib/parameters.py b/ipalib/parameters.py
index 728faee53..1dff13cc1 100644
--- a/ipalib/parameters.py
+++ b/ipalib/parameters.py
@@ -114,6 +114,9 @@ from constants import TYPE_ERROR, CALLABLE_ERROR, LDAP_GENERALIZED_TIME_FORMAT
from text import Gettext, FixMe
from util import json_serialize
from ipapython.dn import DN
+from ipapython.dnsutil import DNSName
+import dns.name
+import encodings.idna
def _is_null(value):
return not value and value != 0 # NOTE: False == 0
@@ -1919,3 +1922,69 @@ def create_param(spec):
TYPE_ERROR % ('spec', (str, Param), spec, type(spec))
)
return Str(spec)
+
+
+class DNSNameParam(Param):
+ """
+ Domain name parameter type.
+
+ :only_absolute a domain name has to be absolute
+ (makes it absolute from unicode input)
+ :only_relative a domain name has to be relative
+ """
+ type = DNSName
+ type_error = _('must be DNS name')
+ kwargs = Param.kwargs + (
+ ('only_absolute', bool, False),
+ ('only_relative', bool, False),
+ )
+
+ def __init__(self, name, *rules, **kw):
+ super(DNSNameParam, self).__init__(name, *rules, **kw)
+ if self.only_absolute and self.only_relative:
+ raise ValueError('%s: cannot be both absolute and relative' %
+ self.nice)
+
+ def _convert_scalar(self, value, index=None):
+ if isinstance(value, unicode):
+ error = None
+
+ try:
+ domain_name = DNSName(value)
+ except dns.name.BadEscape:
+ error = _('invalid escape code in domain name')
+ except dns.name.EmptyLabel:
+ error = _('empty DNS label')
+ except dns.name.NameTooLong:
+ error = _('domain name cannot be longer than 255 characters')
+ except dns.name.LabelTooLong:
+ error = _('DNS label cannot be longer than 63 characters')
+ except dns.exception.SyntaxError:
+ error = _('invalid domain name')
+
+ #compare if IDN normalized and original domain match
+ #there is N:1 mapping between unicode and IDNA names
+ #user should use normalized names to avoid mistakes
+ normalized_domain_name = encodings.idna.nameprep(value)
+ if value != normalized_domain_name:
+ error = _("domain name '%(domain)s' and normalized domain name"
+ " '%(normalized)s' do not match. Please use only"
+ " normalized domains") % {'domain': value,
+ 'normalized': normalized_domain_name}
+ if error:
+ raise ConversionError(name=self.get_param_name(), index=index,
+ error=error)
+ value = domain_name
+
+ if self.only_absolute and not value.is_absolute():
+ value = value.make_absolute()
+
+ return super(DNSNameParam, self)._convert_scalar(value, index)
+
+ def _rule_only_absolute(self, _, value):
+ if self.only_absolute and not value.is_absolute():
+ return _('must be absolute')
+
+ def _rule_only_relative(self, _, value):
+ if self.only_relative and value.is_absolute():
+ return _('must be relative')