Lynn Rees avatar Lynn Rees committed 099c426

[svn]

Comments (0)

Files changed (1)

branches/0.2/wsgiform/validators.py

 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-_zip = re.compile(r'(^\d{5}$)|(^\d{5}-*\d{4}$)')
+'''Form validation utilities.'''
 
-def istext(text):
-    return isinstance(text, basestring)
+import re, urllib
+from xml.dom.expatbuilder import parseString
+from HTMLParser import HTMLParser
 
-def isint(num):
-    return isinstance(int(num), num)
+# Miscellaneous specialized regexes
+_patterns = {
+# US Social Security Number - Dennis Flynn - regexlib.com 
+'ssn':r'(^|\s)(00[1-9]|0[1-9]0|0[1-9][1-9]|[1-6]\d{2}|7[0-6]\d|77[0-2])(-?|[\. ])([1-9]0|0[1-9]|[1-9][1-9])\3(\d{3}[1-9]|[1-9]\d{3}|\d[1-9]\d{2}|\d{2}[1-9]\d)($|\s|[;:,!\.\?])',
+# US currency checker - Michael Ash - regexlib.com
+'usd':r'^\$(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?$',
+# MAC Address - Ted Rudyk - regexlib.com 
+'macaddr':r'^([0-9a-fA-F][0-9a-fA-F]:){5}([0-9a-fA-F][0-9a-fA-F])$',
+# IP4 address - Andrew Polshaw - regexlib.com
+'ip4':r'^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$',
+# IP6 address - Glynn Beeken - regexlib.com
+'ip6':r'^(^(([0-9A-F]{1,4}(((:[0-9A-F]{1,4}){5}::[0-9A-F]{1,4})|((:[0-9A-F]{1,4}){4}::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,1})|((:[0-9A-F]{1,4}){3}::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,2})|((:[0-9A-F]{1,4}){2}::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,3})|(:[0-9A-F]{1,4}::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,4})|(::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,5})|(:[0-9A-F]{1,4}){7}))$|^(::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,6})$)|^::$)|^((([0-9A-F]{1,4}(((:[0-9A-F]{1,4}){3}::([0-9A-F]{1,4}){1})|((:[0-9A-F]{1,4}){2}::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,1})|((:[0-9A-F]{1,4}){1}::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,2})|(::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,3})|((:[0-9A-F]{1,4}){0,5})))|([:]{2}[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,4})):|::)((25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{0,2})\.){3}(25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{0,2})$$',
+# Complex password enforcer 1 upper 1 lower 1 num 1 special min/max - Matthew Hazzard - regexlib.com
+'password':r'(?=^.{8,255}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*',
+# Name check - tom ferguson - regexlib.com
+'namecheck':r'(^([ \u00c0-\u01ffa-zA-Z\'])+$)|(^[a-z\.]*\s?([a-z\-\']+\s)+[a-z\-\']+$)',
+# US state abbreviations - Michael Ash - regexlib.com
+'usstates':r'^(A[LKSZRAEP]|C[AOT]|D[EC]|F[LM]|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEHINOPST]|N[CDEHJMVY]|O[HKR]|P[ARW]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$',
+# Canada provice abbeviations - Matthew Hartman - regexlib.com
+'canada':r'^(N[BLSTU]|[AMN]B|[BQ]C|ON|PE|SK)$',
+# Credit Card - David Conorozzo - regexlib.com
+'creditcard':r'^3(?:[47]\d([ -]?)\d{4}(?:\1\d{4}){2}|0[0-5]\d{11}|[68]\d{12})$|^4(?:\d\d\d)?([ -]?)\d{4}(?:\2\d{4}){2}$|^6011([ -]?)\d{4}(?:\3\d{4}){2}$|^5[1-5]\d\d([ -]?)\d{4}(?:\4\d{4}){2}$|^2014\d{11}$|^2149\d{11}$|^2131\d{11}$|^1800\d{11}$|^3\d{15}$',
+# Malice protection - Shahar Bracha - regexlib.com
+'demalice':r'((script)|(&lt;)|(&gt;)|(%3c)|(%3e)|(SELECT) |(UPDATE) |(INSERT) |(DELETE)|(GRANT) |(REVOKE)|(UNION)|(&amp;lt;)|(&amp;gt;))|(^[^<>`~!/@\#}$%:;)(_^{&*=|\'+]+$)',
+# Email - Shaune Stark - regexlib.com
+'email':r'^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@(([0-9a-zA-Z])+([-\w]*[0-9a-zA-Z])*\.)+[a-zA-Z]{2,9})$',
+# URL - Brian Bothwell - regexlib.com
+'url':r'^(file|ftp|gopher|hdl|http|https|imap|mailto|mms|news|nntp|prospero|rsync|rtsp|rtspu|shttp|sip|snews|svn|svn+ssh|telnet|wais)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&amp;%\$\-]+)*@)?((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.[a-zA-Z]{2,4})(\:[0-9]+)?(/[^/][a-zA-Z0-9\.\,\?\'\\/\+&amp;%\$#\=~_\-@]*)*$',
+# DateTime mm/dd/yyyy hh:MM:ss - Michael Ash - regexlib.com
+'datetime':r'(?=\d)^(?:(?!(?:10\D(?:0?[5-9]|1[0-4])\D(?:1582))|(?:0?9\D(?:0?[3-9]|1[0-3])\D(?:1752)))((?:0?[13578]|1[02])|(?:0?[469]|11)(?!\/31)(?!-31)(?!\.31)|(?:0?2(?=.?(?:(?:29.(?!000[04]|(?:(?:1[^0-6]|[2468][^048]|[3579][^26])00))(?:(?:(?:\d\d)(?:[02468][048]|[13579][26])(?!\x20BC))|(?:00(?:42|3[0369]|2[147]|1[258]|09)\x20BC))))))|(?:0?2(?=.(?:(?:\d\D)|(?:[01]\d)|(?:2[0-8])))))([-.\/])(0?[1-9]|[12]\d|3[01])\2(?!0000)((?=(?:00(?:4[0-5]|[0-3]?\d)\x20BC)|(?:\d{4}(?!\x20BC)))\d{4}(?:\x20BC)?)(?:$|(?=\x20\d)\x20))?((?:(?:0?[1-9]|1[012])(?::[0-5]\d){0,2}(?:\x20[aApP][mM]))|(?:[01]\d|2[0-3])(?::[0-5]\d){1,2})?$',
+# DateTime yyyy/mm/dd hh:MM:ss - Michael Ash - regexlib.com
+'eurodatetime':r'^(?=\d)(?:(?!(?:1582(?:\.|-|\/)10(?:\.|-|\/)(?:0?[5-9]|1[0-4]))|(?:1752(?:\.|-|\/)0?9(?:\.|-|\/)(?:0?[3-9]|1[0-3])))(?=(?:(?!000[04]|(?:(?:1[^0-6]|[2468][^048]|[3579][^26])00))(?:(?:\d\d)(?:[02468][048]|[13579][26]))\D0?2\D29)|(?:\d{4}\D(?!(?:0?[2469]|11)\D31)(?!0?2(?:\.|-|\/)(?:29|30))))(\d{4})([-\/.])(0?\d|1[012])\2((?!00)[012]?\d|3[01])(?:$|(?=\x20\d)\x20))?((?:(?:0?[1-9]|1[012])(?::[0-5]\d){0,2}(?:\x20[aApP][mM]))|(?:[01]\d|2[0-3])(?::[0-5]\d){1,2})?$',
+# US Phone - Tim N Tousley - regexlib.com 
+'usphone':r'^([a-zA-Z,#/ \.\(\)\-\+\*]*[2-9])([a-zA-Z,#/ \.\(\)\-\+\*]*[0-9]){2}([a-zA-Z,#/ \.\(\)\-\+\*]*[2-9])([a-zA-Z,#/ \.\(\)\-\+\*]*[0-9]){6}[0-9a-zA-Z,#/ \.\(\)\-\+\*]*$',
+# UK Phone - M h - regexlib.com 
+'ukphone':r'^\s*\(?(020[7,8]{1}\)?[ ]?[1-9]{1}[0-9{2}[ ]?[0-9]{4})|(0[1-8]{1}[0-9]{3}\)?[ ]?[1-9]{1}[0-9]{2}[ ]?[0-9]{3})\s*$',
+# International phone - Dmitry Kandiner - regexlib.com
+'intlphone':r'^(\+[1-9][0-9]*(\([0-9]*\)|-[0-9]*-))?[0]?[1-9][0-9\- ]*$',
+# Phone checker - Tim N Tousley - regexlib.com 
+'phone':r'^([a-zA-Z,#/ \.\(\)\-\+\*]*[0-9]){7}[0-9a-zA-Z,#/ \.\(\)\-\+\*]*$',
+# US-Canada postal/zip codes - Matthew Aznoe - regexlib.com 
+'napost':r'^((\d{5}-\d{4})|(\d{5})|([AaBbCcEeGgHhJjKkLlMmNnPpRrSsTtVvXxYy]\d[A-Za-z]\s?\d[A-Za-z]\d))$',
+# US Zip codes 5+4 +/- hyphen
+'zip':r'(^\d{5}$)|(\d{5}-*\d{4}$)',
+# UK postal codes - Scott Pite - regexlib.com
+'ukpost':r'^[A-Za-z]{1,2}[\d]{1,2}([A-Za-z])?\s?[\d][A-Za-z]{2}$',
+# ISBN - Michael Ash - regexlib.com
+'isbn':r'ISBN\x20(?=.{13}$)\d{1,5}([- ])\d{1,7}\1\d{1,6}\1(\d|X)$',
+# Number checker - Paul Auger - regexlib.com
+'num':r'^((\d?)|(([-+]?\d+\.?\d*)|([-+]?\d*\.?\d+))|(([-+]?\d+\.?\d*\,\ ?)*([-+]?\d+\.?\d*))|(([-+]?\d*\.?\d+\,\ ?)*([-+]?\d*\.?\d+))|(([-+]?\d+\.?\d*\,\ ?)*([-+]?\d*\.?\d+))|(([-+]?\d*\.?\d+\,\ ?)*([-+]?\d+\.?\d*)))$',
+# Euro VAT - Michal Valasek - regexlib.com
+'vat':r'((DK|FI|HU|LU|MT|SI)(-)?\d{8})|((BE|EE|DE|EL|LT|PT)(-)?\d{9})|((PL|SK)(-)?\d{10})|((IT|LV)(-)?\d{11})|((LT|SE)(-)?\d{12})|(AT(-)?U\d{8})|(CY(-)?\d{8}[A-Z])|(CZ(-)?\d{8,10})|(FR(-)?[\dA-HJ-NP-Z]{2}\d{9})|(IE(-)?\d[A-Z\d]\d{5}[A-Z])|(NL(-)?\d{9}B\d{2})|(ES(-)?[A-Z\d]\d{7}[A-Z\d])',
+}
+
+patterns = dict((k, re.compile(_patterns[k])) for k in _patterns) 
+
+def _validate(key, data):
+    '''Validates data by key.'''
+    if patterns[key].match(data): return True
+    
+def isascii(data):
+    '''Validates data is ASCII'''
+    return isinstance(str(text), str)
+
+def isunicode(data):
+    '''Validates data is unicode.'''
+    return isinstance(unicode(text), str)
+
+def isnumber(data):
+    '''Validates data is number.'''
+    return data.isdigits()
+
+def isalpha(data):
+    '''Validates data is all alphabetical.'''   
+    return data.isalpha()
+
+def isalphanum(data):
+    '''Validates data is alphanumeric.'''
+    return data.isalnum()
+
+def isspace(data):
+    '''Validates data is all spaces.'''
+    return data.isspace()
+
+def istitle(data):
+    '''Validates data is in title form.'''
+    return data.istitle()
+
+def isupper(data):
+    '''Validates data is uppercase.'''
+    return data.isupper()
+
+def islower(data):
+    '''Validates data is lowercase.'''
+    return data.islower()
 
 def islength(data, length):
-    return len(data) == length
+    '''Validates data is under or equals a defined length.'''
+    return len(data) <= length
 
 def iszipcode(data):
-    if _zip.match(data): return True
+    '''Validates data is a valid US ZIP code.'''
+    return _validate('zip', data)
+
+def isukpost(data):
+    '''Validates data is a valid UK postal code.'''
+    return _validate('ukpost', data)
+
+def iscnabbr(data):
+    '''Validates data is a valid Canadian provincial abbreviation.'''
+    return _validate('canada', data)
+
+def iscreditcardnum(data):
+    '''Validates data is a valid format for a credit card number.'''
+    return _validate('creditcard', data)
+
+def isdatetime(data):
+    '''Validates data is a valid format for mm/dd/yyyy hh:MM:ss.'''
+    return _validate('datetime', data)
+
+def notmalice(data):
+    '''Validates data is free of some potentially malicious content.'''
+    return _validate('demalice', data)
+
+def isemail(data):
+    '''Validates data is a valid email address.'''
+    return _validate('email', data)
+
+def isedatetime(data):
+    '''Validates data is a valid format for yyyy/mm/dd hh:MM:ss.'''
+    return _validate('eurodatetime', data)
+
+def isip4(data):
+    '''Validates data is a valid IPv4 address.'''
+    return _validate('ip4', data)
+
+def isip6(data):
+    '''Validates data is a valid IPv6 address.'''
+    return _validate('ip6', data)
+
+def isurl(data):
+    '''Validates data is a valid URL.'''
+    return _validate('url', data)
+
+def isliveurl(data):
+    '''Validates data is a live URL.'''
+    try:
+        urllib.urlopen(data)
+    except:
+        return False
+    return True        
+
+def isisbn(data):
+    '''Validates data is ISBN.'''
+    return _validate('isbn', data)
+
+def ismacaddr(data):
+    '''Validates data is a valid MAC address.'''
+    return _validate('macaddr', data)
+
+def isname(data):
+    '''Validates data is seems like a valid personal name.'''
+    return _validate('namecheck', data)
+
+def isnapost(data):
+    '''Validates data is a US ZIP or Canadian postal code.'''
+    return _validate('napost', data)
+
+def ispassword(data):
+    '''Validates that data is a password has 1 upper 1 lower 1 num
+    1 and at least 8 characters.
+    '''
+    return _validate('password', data)
+
+def isphone(data):
+    '''Validates that data is a phone number.'''
+    return _validate('phone', data)
+
+def isssn(data):
+    '''Validates that data is a social security number.'''
+    return _validate('ssn', data)
+
+def isukphone(data):
+    '''Validates that data is a UK phone number.'''
+    return _validate('ukphone', data)
+
+def isusd(data):
+    '''Validates that data is a UK phone number.'''
+    return _validate('usd', data)
+
+def isusphone(data):
+    '''Validates that data is a US phone number.'''
+    return _validate('usphone', data)
+
+def isusstateabbr(data):
+    '''Validates that data is a US state abbreviation.'''
+    return _validate('usstates', data)
+
+def isvat(data):
+    '''Validates that data is a EU VAT number.'''
+    return _validate('vat', data)
+
+def isxml(data):
+    '''Validates data is well-formed XML.'''
+    try:
+        parseString(data)
+    except:
+        return False
+    return True
+
+def ishtml(data):
+    '''Validates that data is not obviously broken HTML.'''
+    try:
+        parser = HTMLParser()
+        parser.feed(data)
+    except:
+        return False
+    return True
+
+def isempty(data):
+    '''Validates data is not empty.'''
+    return data.strip == ''
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.