#1
  1. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Location
    Cincinnati, Ohio
    Posts
    25
    Rep Power
    0

    Form Field Validation via Regular Expressions


    I have a problem. Of course, or I wouldn't be posting here. Ok, now that Mr. Obvious is out of the way ...

    I'm looking for some ideas. Take a look at the code below. I'm looking for the most efficient way to validate form field input on the server-side. I'll provide what I have. What I'm looking for are improvements.

    Code:
    <%
    Function Validate_Input(Expression,Pattern)
    	
    	Dim objRegExp
    		
    	if Expression <> "" and Pattern <> "" then
    		
    		Set objRegExp = New RegExp
    			
    		select case (Pattern)
    			
    			case "US_PHONE"
    			' sample matches: 1-(123)-123-1234 / 123 123 1234 / 1-800-ALPHNUM 
    			' sample non-matches: 1.123.123.1234 / (123)-1234-123 / 123-1234 
    			
    				objRegExp.Pattern		= "^([0-9]( |-)?)?(\(?[0-9]{3}\)?|[0-9]{3})( |-)?([0-9]{3}( |-)?[0-9]{4}|[a-zA-Z0-9]{7})$"
    					
    			case "US_DATE"
    			' sample matches: 02/29/2084 / 01/31/2000 / 11/30/2000 
    			' sample non-matches: 	02/29/2083 / 11/31/2000 / 01/32/2000 
    
    				objRegExp.Pattern		= "(((0[13578]|10|12)([-./])(0[1-9]|[12][0-9]|3[01])([-./])(\d{4}))|((0[469]|11)([-./])([0][1-9]|[12][0-9]|30)([-./])(\d{4}))|((2)([-./])(0[1-9]|1[0-9]|2[0-8])([-./])(\d{4}))|((2)(\.|-|\/)(29)([-./])([02468][048]00))|((2)([-./])(29)([-./])([13579][26]00))|((2)([-./])(29)([-./])([0-9][0-9][0][48]))|((2)([-./])(29)([-./])([0-9][0-9][2468][048]))|((2)([-./])(29)([-./])([0-9][0-9][13579][26])))"
    	
    			case "EMAIL_ADDRESS"
    			' sample matches: asmith@mactec.com / foo12@foo.edu / bob.smith@foo.tv 
    			' sample non-matches: joe / @foo.com / a@a 
    			
    				objRegExp.Pattern		= "^([a-zA-Z0-9_\-\.\47]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,7}|[0-9]{1,3})(\]?)$"
    					
    				'The next line is supposed to be an RFC 2822 address compliant validation expression
    				'objRegExp.Pattern		= "^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$
    					
    			case "ZIP"
    			' sample matches: 78754 / 78754-1234 / G3H 6A3 
    			' sample non-matches: 78754-12aA / 7875A / g3h6a3
    				
    				objRegExp.Pattern		= "^(\d{5}-\d{4}|\d{5})$|^([a-zA-Z]\d[a-zA-Z] \d[a-zA-Z]\d)$"
    					
    			case "CREDIT_CARD"
    			' sample matches: 6011-1111-1111-1111 / 5423-1111-1111-1111 / 341111111111111 
    			' sample non-matches: 4111-111-111-111 / 3411-1111-1111-111 / Visa 
    				
    				objRegExp.Pattern		= "^((4\d{3})|(5[1-5]\d{2})|(6011))-?\d{4}-?\d{4}-?\d{4}|3[4,7]\d{13}$"
    					
    			case "NAME"
    			' sample matches: T.F. Johnson / John O'Neil / Mary-Kate Johnson
    			' sample non-matches: sam_johnson / Joe--Bob Jones / dfjsd0rd 
    				
    				objRegExp.Pattern		= "^[a-zA-Z]+(([\'\,\.\- ][a-zA-Z ])?[a-zA-Z]*)*$"
    				
    			case "ADDRESS"
    			' sample matches:  2222 Mock St. / 1 A St. / 555-1212  
    			' sample non-matches: [A Street] / (3 A St.) / {34 C Ave.} 
    				
    				objRegExp.Pattern		= "^[a-zA-Z0-9\s.\-]+$"
    					
    			case "CURRENCY"
    			' sample matches: $3,023,123.34 / 9,876,453 / 123456.78 
    			' sample non-matches: 4,33,234.34 / $1.234 / abc
    				
    				objRegExp.Pattern		= "^\$?([0-9]{1,3},([0-9]{3},)*[0-9]{3}|[0-9]+)(.[0-9][0-9])?$"
    					
    			case else
    				
    				Response.Write("Invalid syntax used to call form validation function.")
    				Response.End
    
    		end select
    				
    		Validate_Input = objRegExp.Test(Expression)
    		
    	else
    		
    		Response.Write("Invalid syntax used to call form validation function.")
    		Response.End
    			
    	end if
    
    End Function
    
    
    	' Get data from the form collection and assign to variables
    	dim str_Customer_Email
    	dim str_Customer_Phone
    	dim str_Customer_Name
    	dim str_Customer_Zip
    
    	str_Customer_Email		= Request.Form("email")
    	str_Customer_Phone		= Request.Form("phone")
    	str_Customer_Name		= Request.Form("name")
    	str_Customer_Zip		= Request.Form("zip")
    
    	if not (Validate_Input(str_Customer_Email,"EMAIL_ADDRESS")) then response.write ("error")
    	if not (Validate_Input(str_Customer_Phone,"US_PHONE")) then response.write ("error")
    	if not (Validate_Input(str_Customer_Name,"NAME")) then response.write ("error")
    	if not (Validate_Input(str_Customer_Zip,"ZIP")) then response.write ("error")
    
    response.end
    %>
    Now, I'll obviously want to do more than write "error" to the screen with the validated input. What I *really* want ideas on is a more efficient way to validate the fields. In this small example doing them as one-offs isn't bad. On a form that has 20-30 fields it becomes cumbersome.

    Thanks for the assistance,

    dot
    Last edited by dotMATRIX; March 6th, 2003 at 03:26 PM.
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Posts
    138
    Rep Power
    12
    You should try testing for the more obvious errors such as, is the input null, are there between 10 and 14 characters, are there any non apha characters, are there two words separated by a space etc.
    If these fail then you should go on to the more extensive and time consuming testing. You might want to do some statistical analysis on the most common type of errors that your set of everyday users produce. Then make the tests for the most common errors the first and fastest.

    If you just want to make the validation calls more tidy you can put the names of the input fields you have in the form in an dictionary named "inputs" and an place the type of validation needed in another dictionary named "valid"

    Then do a "For Each" on the Request.Form object making sure that the form element exists in your dictionary. If it isn't then somebody added an extra field to your form!
    Then just call the appropriate validation function depending on the type stored for that input. Loop until you have done all fields on the form.

    You could also use arrays instead of dictionaries but dictionaries have efficient methods for testing existance and lookup.
    --

    ngibsonau
  4. #3
  5. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2003
    Location
    Cincinnati, Ohio
    Posts
    25
    Rep Power
    0
    Sorry for not getting back sooner. I've been working through the dictionary object.

    Interesting solution. I'm working through a similar modification to what you suggested.

    1. I'm creating a single dictionary object to hold the fields and their values.

    2. I'm calling the validate function for each item: ugly, but it's working.

    3. I've modified the validation function to accept things like:

    Min_Length
    Max_Length
    Can_Be_NULL
    HTML_Enabled
    Required

    This allows me to check, within my function, the various things that are important. If certain criteria are met then I create a second dictionary object containing the fields with errors.

    My thought is to pass the errors dictionary object back to the form in a session variable and redirect using "server.transfer" to maintain the form collection. This will allow me to re-populate the form with the current data and use the session to mark bad input.

    Thoughts?

    dot

IMN logo majestic logo threadwatch logo seochat tools logo