from twisted.internet import defer
import re
from decorator import decorator
from inspect import getcallargs
import types
from .error import ValidateException, InvalidTel, InvalidMail
from .telnumber import Telnumber
def vBool(value, field):
'''Validator for boolean values'''
t=[True, 1, "true", "True", "TRUE"]
f=[False, 0, "false", "False", "FALSE"]
if value in t:
return True
elif value in f:
return False
else:
raise ValidateException(field=field, msg='%s is not boolean' % field)
def vInteger(value, field, minv=None, maxv=None, none_allowed=False):
if none_allowed and value in [None,'']:
return None
try:
ret = int(value)
except ValueError:
raise ValidateException(field=field)
except TypeError:
raise ValidateException(field=field)
if minv is not None and ret < minv:
raise ValidateException(field=field)
if maxv is not None and ret > maxv:
raise ValidateException(field=field)
return ret
def vHash(value,field,minlength=None,maxlength=None):
'''Validator for hash values'''
if not re.match(r'^[a-f0-9]*$', value.lower()):
raise ValidateException(field=field)
if minlength and len(value)<minlength:
raise ValidateException(field=field)
if maxlength and len(value)>maxlength:
raise ValidateException(field=field)
return value.lower()
def vTel(value,field):
'''Validator for Telefonnumbers'''
ret = []
for v in value:
try:
tel=Telnumber(v)
if tel not in ret:
ret.append(tel)
except InvalidTel, e:
e.field=field
raise e
return ret
def vEmail(value, field, allowString=True, allowList=True):
'''validator for emailadresses (see wikipeda for strange mailadresses and RFC3696)
valid:
"very.(),:;<>[]\\".VERY.\\"very@\\\ \\"very\\".unusual"@strange.example.com
""@example.org
"very.unusual.@.unusual.com"@example.com'
not valid:
Abc.@example.com
Abc..123@example.com
thisis."notallowed@example.com
this\\ still\\"not\\allowed@example.com
'''
ret = []
str_=False
if type(value) is types.StringType:
if not allowString:
raise ValidateException('%s must be a list of email addresses.'%field)
str_=True
value=[value]
elif not allowList:
raise ValidateException('%s must be a email address - No list of email addresses.'%field)
for v in value:
parts= re.match(r'^(.*)@(.+?)$',v)
if not parts:
raise InvalidMail(v,field)
local=parts.group(1)
domain=parts.group(2)
if not re.match(r'^(\[[0-9\.]{7,16}\]|\[[0-9a-f:]{3,}\]|([a-z0-9+\-%_]+\.)+[a-z]{2,6})$',domain.lower()):
raise InvalidMail(v,field)
if local == "":
ret.append(v)
continue
if local.startswith(".") or local.endswith("."):
raise InvalidMail(v,field)
unquote = True
parts = local.split('"')
c=0
i=0
for part in parts:
if unquote and part != "": #unquoted is not allowd so much
if not re.match(r'^[^\\,\[\];\(\)@<>: ]+$',part) or ".." in part:
raise InvalidMail(v,field)
if i == 0:
if unquote and part != "" and len(parts) > 1 and part[-1] != '.': #quoted parts must be seperated by a dot
raise InvalidMail(v,field)
unquote = not unquote
c+=1
elif part == '' or part[-1] != "\\":
if unquote and part != "": #quoted parts must be seperated by a dot
if part[0] != ".":
raise InvalidMail(v,field)
if i < len(parts)-1 and part[-1] != '.':
raise InvalidMail(v,field)
unquote = not unquote
c += 1
i += 1
if c%2 == 0 and c > 1: #no single quote allowed
raise InvalidMail(v,field)
if v not in ret:
ret.append(v)
if str_:
ret=ret[0]
return ret
def validate(kwd,func, need=True,*args,**kargs):
'''validate decorator
use it like this:
@validate(kwd=userhash, func=vuserhash)
f(userhash)
that will validate usrhash with the function vuserhash.
Every validate function should raise an Exception, if the the value is not valid.
All args and kargs are used to call the validate function.
if need is True, the kwd can't be None.'''
@decorator
def v(f,*a,**k):
kp=getcallargs(f,*a,**k)
def dfunc(*x,**y):
return None
try:
if kp[kwd] is not None:
dfunc=func
elif need:
raise ValidateException(field=kwd,msg="%s is nessasary"%kwd)
except KeyError:
if need:
raise ValidateException(field=kwd,msg="%s is nessasary"%kwd)
kp[kwd] = None
def _gotResult(value):
kp[kwd] = value
e = defer.maybeDeferred(f,**kp)
return e
d = defer.maybeDeferred(dfunc, kp[kwd],kwd,*args,**kargs)
return d.addCallback(_gotResult)
return v