def is_plaintext(v, extra=None, messages=None): """ Checks that the value contains only alpha-numberics :arg extra: A list of extra characters that are allowed """ if v is None: return if extra: extra.replace('-', '\-') regex = r"^[a-zA-Z0-9%s]*$" % extra _messages = { 'type-string': "must be a string", 'characters-and-numbers': "must consist of characters and numbers only", 'characters-and-numbers-extra': "must consist of characters and numbers plus any of %(extra)s", } if messages: _messages.update(messages) if not isinstance(v, basestring): raise Invalid(_messages['type-string']) msg = _messages['characters-and-numbers'] if extra is not None: msg = _messages['characters-and-numbers-extra'] % {'extra': extra} p = re.compile(regex, re.UNICODE) if not p.match(v): raise Invalid(msg)
def is_in_range(v, min=None, max=None, messages=None): """ Check that the value is not less than an optional min value and not greater than an optional max value :arg max: optional max value :arg min: optional min value """ if min is None and max is None: return if min is None and max is None: return _messages = { 'between': "must be between %(min)s and %(max)s", 'greater-than': "must be greater than or equal to %(min)s", 'less-than': "must be less than or equal to %(max)s", } if messages: _messages.update(messages) if min is not None and max is not None: error = _messages['between'] % {'min': min, 'max': max} elif min is not None: error = _messages['greater-than'] % {'min': min} else: error = _messages['less-than'] % {'max': max} if max is not None and v > max: raise Invalid(error) if min is not None and v < min: raise Invalid(error)
def __call__(self, v): if not isinstance(v, datetime.datetime): msg = "Must be a valid datetime." raise Invalid(msg, validator=self) if v.year < 1900: msg = "Year must be greater than or equal to 1900." raise Invalid(msg, validator=self)
def is_url(v, full=True, absolute=True, relative=True, with_scheme=False, messages=None): """ Uses a simple regex from FormEncode to check for a url """ _messages = {'type-url': "must be a url"} if messages: _messages.update(messages) if v is None: return if not isinstance(v, basestring): raise Invalid(_messages['type-url']) exp = [] if full: exp.append( r"(https?://)([a-z0-9][a-z0-9\-\.\_]*\.[a-z]+)(:[0-9]+)?(/.*)?") if absolute and not with_scheme: exp.append('/.*') if relative and not with_scheme: exp.append('[^/(https?://)].*') urlRE = re.compile('^(' + ')$|^('.join(exp) + ')$', re.I) if not urlRE.search(v): raise Invalid(_messages['type-url'])
def has_length(v, min=None, max=None, messages=None): """ Check that the length of the string or sequence is not less than an optional min value and not greater than an optional max value :arg max: optional max value :arg min: optional min value """ if v is None: return if min is None and max is None: return _messages = { 'between': "must have between %(min)s and %(max)s %(unit)s", 'fewer-than': "must have %(max)s or fewer %(unit)s", 'more-than': "must have %(min)s or more %(unit)s", } if messages: _messages.update(messages) if isinstance(v, basestring): unit = 'characters' else: unit = 'items' if max is not None and min is not None and (len(v) > max or len(v) < min): raise Invalid(_messages['between'] % { 'min': min, 'max': max, 'unit': unit }) if max is not None and len(v) > max: raise Invalid(_messages['fewer-than'] % {'max': max, 'unit': unit}) if min is not None and len(v) < min: raise Invalid(_messages['more-than'] % {'min': min, 'unit': unit})
def __call__(self, v): if not v: return site = find_site(self.context) try: target = find_resource(site, v) except KeyError: raise Invalid("Path not found: %s" % v) else: if target is site: raise Invalid("Path must not point to the site root")
def is_integer(v, messages=None): """ Checks that the value can be converted into an integer """ if v is None: return _messages = { 'type-integer': "must be a integer", } if messages: _messages.update(messages) try: if v != int(v): raise Invalid(_messages['type-integer']) except (ValueError, TypeError): raise Invalid(_messages['type-integer'])
def is_number(v, messages=None): """ Checks that the value is not a string but can be converted to a float """ if v is None: return _messages = { 'type-number': "must be a number", } if messages: _messages.update(messages) try: if isinstance(v, basestring): raise Invalid(_messages['type-number']) float(v) except (ValueError, TypeError): raise Invalid(_messages['type-number'])
def is_domain_name(value, messages=None): """ Validate the value looks like a domain name. """ if value is None: return _messages = { 'type-string': "must be a string", 'invalid': "is invalid", } if messages: _messages.update(messages) if not isinstance(value, basestring): raise Invalid(_messages['type-string']) if _domain_name_regex.match(value) is None: raise Invalid(_messages['invalid'])
def __call__(self, v): if v is None: return query = meta.Session.query(Account.id).filter(Account.login == v) if query.count(): raise Invalid(self.msg, validator=self)
def __call__(self, v): if v in self.exceptions: return try: make_name(self.container, v) except ValueError, why: raise Invalid(why[0])
def __call__(self, v): if v in self.exceptions: return title = v.lower() for page in self.container.values(): if page.title.lower() == title: raise Invalid('Title "%s" is already in use on this wiki' % v)
def __call__(self, v): if not v: return site = find_site(self.context) try: target = find_resource(site, v) except KeyError, e: raise Invalid("Path not found: %s" % v)
def __call__(self, v): # XXX: repoze.who.plugins.zodb.interfaces.IUsers # really should have a check_password(id, password) # method. We shouldn't have to use get_sha_password # directly. enc = get_sha_password(v) if enc != self.user['password']: raise Invalid('Incorrect password', v)
def __call__(self, v): if v: if v.startswith('www.'): v = 'http://%s' % v try: validate.is_url(v, with_scheme=True) except Invalid: msg = u"Must start with 'http://', 'https://', or 'www.'" raise Invalid(msg, validator=self)
def is_required(v, messages=None, none_zero=True): """ Checks the non_zero attribute but allows numberic zero to pass """ # XXX I still think it would be nicer if this just tested "is None". We did # discuss about the empty string "", but that's more of an input problem I # think, e.g. how does a higher layer interpret something that has not been # entered. _messages = { 'required': "is required", } if messages: _messages.update(messages) if none_zero: if not v and v != 0: raise Invalid(_messages['required']) else: if v is None: raise Invalid(_messages['required'])
def __call__(self, v): if v is None: return # The formish file manager gives us its cache file which starts # with internal data. PIL does not like that, so we need to create # our own file. position = v.file.tell() data = io.BytesIO(v.file.read()) v.file.seek(position, os.SEEK_SET) try: pil_data = PIL.Image.open(data) pil_data.load() except (IOError, OverflowError): raise Invalid(self.msg_format, validator=self) if pil_data.format not in ["GIF", "PNG", "JPEG"]: raise Invalid(self.msg_format, validator=self)
def is_string(v, messages=None): """ checks that the value is an instance of basestring """ if v is None: return _messages = { 'type-string': "must be a string", } if messages: _messages.update(messages) if not isinstance(v, basestring): raise Invalid(_messages['type-string'])
def is_one_of(v, set_of_values, messages=None): """ Check that the value is one of the set of values given :arg set_of_values: the set of values to check against """ if v is None: return _messages = { 'one-of-empty': "must be one of []", 'one-of': "must be one of %(values)r", } if messages: _messages.update(messages) if not set_of_values: raise Invalid(_messages['one-of-empty']) # XXX what's the following doing? if isinstance(v, list): v = tuple(v) # XXX Why create a set here? if v not in set(set_of_values): raise Invalid(_messages['one-of'] % {'values': set_of_values})
def __call__(self, v): if v and len(v) < int(self.min_pw_length): fmt = "Password must be at least %s characters" msg = fmt % self.min_pw_length raise Invalid(msg, v) # the easiest way is to piggyback all password checks here misses = 0 if v and not any(char.isdigit() for char in v): misses += 1 if v and not any(char.isupper() for char in v): misses += 1 if v and not any(char.islower() for char in v): misses += 1 if v and not any(char in self.special_chars for char in v): misses += 1 # 3 out of 4 if misses > 1: msg = ("Password must include three of the following four: " "At least one number, at least one special character, " "at least one capital letter or at least one lowercase " "letter.") raise Invalid(msg, v)
def __call__(self, v): if v: context = self.context # Let's not find conflicts with our own selves prev = getattr(context, 'short_address', None) if prev == v: # Nothing's changed, no need to check return root = find_site(context) if v in root.list_aliases: raise Invalid( "'short_address' is already in use by another mailing list.")
def is_equal(v, compared_to, messages=None): """ Check the value, v, is equal to the comparison value. :arg compared_to: the value to compare to """ _messages = { 'incorrect': "incorrect", } if messages: _messages.update(messages) if v is None or v == compared_to: return raise Invalid(_messages['incorrect'])
def is_email(v, messages=None): """ Validate the value looks like an email address. """ if v is None: return _messages = { 'type-string': "must be a string", 'contain-at': "must contain one @", 'username-incorrect': "username part before the @ is incorrect", 'domain-incorrect': "domain name part after the @ is incorrect", } if messages: _messages.update(messages) if not isinstance(v, basestring): raise Invalid(_messages['type-string']) parts = v.split('@') if len(parts) != 2: raise Invalid(_messages['contain-at']) username, address = parts if _domain_user_regex.match(username) is None: raise Invalid(_messages['username-incorrect']) if _domain_name_regex.match(address) is None: raise Invalid(_messages['domain-incorrect'])
def __call__(self, v): if v: context = self.context # Let's not find conflicts with our own selves prev = getattr(context, 'email', None) if prev == v: # Nothing's changed, no need to check return search = getAdapter(context, ICatalogSearch) result = search(interfaces=[IProfile], email=[v.lower()], limit=1) n = result[0] if n: raise Invalid( 'Email address is already in use by another user.')
def __call__(self, v): if v is not None: if not self.expr.match(v): raise Invalid(self.msg)
def __call__(self, v): if v in set(self.set_of_values): raise Invalid('%s already exists' % v, validator=self)
def __call__(self, v): if v: try: clean_html(v) except: raise Invalid('Unable to parse the provided HTML')
def __call__(self, v): if v and len(v) < int(self.min_pw_length): fmt = "Password must be at least %s characters" msg = fmt % self.min_pw_length raise Invalid(msg, v)
def __call__(self, v): if not self.users.check_password(v, userid=self.userid): raise Invalid('Incorrect password', v)
""" Ensures that a model object exists at the specified path, and that the model object is not the site root. """ def __init__(self, context): self.context = context def __call__(self, v): if not v: return site = find_site(self.context) try: target = find_resource(site, v) except KeyError, e: raise Invalid("Path not found: %s" % v) else: if target is site: raise Invalid("Path must not point to the site root") class PasswordLength(Validator): def __init__(self, min_pw_length): self.min_pw_length = min_pw_length def __call__(self, v): if v and len(v) < int(self.min_pw_length): fmt = "Password must be at least %s characters" msg = fmt % self.min_pw_length raise Invalid(msg, v) class CorrectUserPassword(Validator): def __init__(self, user):