Form validation lib
Posted: Fri Apr 13, 2007 3:01 pm
First shot at a cgi form validation library.
Code: Select all
#!/usr/bin/env newlisp
;; Validation routines library
;;
;; The validation library handles the task of validating fields in a cgi form.
;; After assigning fields (see the examples below), run validation:run with
;; your post-data (from cgi.lsp or elsewhere). The library will validate all
;; fields and assign errors and post values to assoc lists in this context.
;;
;; If validation:run evaluates to nil, you can then use the errors and values
;; to repopulate the form and let the user know they need to fix certain values.
;; If validation:run evaluates as true, you can process the data and continue
;; on however you wish.
;; Examples
;
;(validation:add-field "username" '((validation:required
; "Username is required")
; (validation:min-length 6
; "Username must be at least 5 chars")
; (validation:alpha-numeric
; "Username can only contain letters, numbers, and -/_.")))
;(validation:add-field "password" '((validation:required
; "Password is required")
; (validation:min-length 6
; "Password must be at least 5 chars")
; (validation:alpha-numeric
; "Password can only contain letters, numbers, and -/_.")))
;
;(if (nil? (validation:get-validation-errors post-data))
; ;;Load form again. Errors are available as an assoc list
; ;;(validation:errors) or individually (validation:error "fieldname").
; ;;You can repopulate the form values using (validation:value "fieldname").
; (if validation:errors (println validation:errors) (println "No errors"))
; (println (validation:error "username") (validation:value "username"))
(context 'validation)
;; Handlers
(set 'rules '())
(set 'values '())
(set 'errors '())
(define (add-field fld-name fld-rules)
"Adds field fld-name with fld-rules as a list of
'((validation-function error-string) ...)."
(push (list fld-name fld-rules) rules -1))
(define (vldt value conditions)
"Takes value and tests against parameter list conditions
((function [function-argument] error-string)...). It evaluates the function
with the function-argument as the first parameter and the value as the second.
If there is an error, it throws the error-string. Otherwise, it returns nil."
(dolist (condition conditions)
(if (> 3 (length condition))
(if (nil? (eval (cons (condition 0) value)))
(throw (condition 1)) nil)
(if (nil? (eval (list (condition 0) (condition 1) value)))
(throw (condition 2)) nil))))
(define (run post-data)
(dolist (pair rules)
(let ((err (catch (vldt ((assoc (pair 0) post-data) 1) (pair 1)))))
(if err (begin
(push (list (pair 0) err) errors)
(push (list (pair 0) ((assoc (pair 0) post-data) 1))
values)))))
(if (< 0 (length errors)) nil true))
(define (error fld-name)
(if (assoc fld-name errors) ((assoc fld-name errors) 1) ""))
(define (value fld-name)
(if (assoc fld-name values) ((assoc fld-name values) 1) ""))
;; Validator functions
(define (required value)
"Value exists (not zero length)"
(< 0 (length value)))
(define (max-length len value)
"Value has a maximum length of len"
(<length>= (length value) len))
(define (exact-length len value)
"Value is exactly length len"
(= (length value) len))
(define (alpha? value)
"Value only contains letters, underscores, and whitespace."
(not (regex {[^a-zA-Z_ ]} value 4)))
(define (alpha-dash? value)
"Value only contains letters, underscores, dashes, and whitespace."
(not (regex {[^a-zA-Z_\- ]} value 4)))
(define (alpha-numeric? value)
"Value only contains letters, underscores, dashes, numbers and whitespace."
(not (regex {[^a-zA-Z_\- 0-9]} value 4)))
(define (valid-phone? value)
"Value is a valid (U.S.) phone number (format: 555-555-5555)."
(regex {^\d{3}-\d{3}-\d{4}$} value))
(define (valid-ip? value)
"Value is a valid IPV4 ip address (0-255 for x.x.x.x)."
(= 4 (length (filter (lambda (val) (and (number? val) (>= val 0) (< val 256)))
(map int (parse value "."))))))
(define (valid-email? value)
"Reasonably usable predicate for email validation.
The regular expression was yanked from Code Igniter."
(regex {^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$}
value))
(context MAIN)