CGI: VBScript CGI Property Class 2
VBScript and JavaScript CGI
VBScript CGI Property Class 2
The previous page concluded with a class capable obtaining any CGI variable in particular variables sent to a page from a form using either the Get or Post method and an anchor (link) which uses Get. This page expands the class to include variables that have been previously set using cookies.
HTTP Header
The following line is part of the HTTP header, which is sent to a browser allowing it to understand the content of a page.
"Content-type: text/html"&vbLF&vbLF
A header is mandatory otherwise a browser will not understand what to do with the page received. The above is a minimum header indicating a page is plain text containing html mark-up and to process it accordingly.
The following table lists most commonly used custom headers in CGI scripts.
Header | Description |
---|---|
Content-type | This is a MIME string defining the file format being returned. For example Content-type:text/html covered above |
Expires | A date when the content becomes invalid. A browser uses this to refresh a cashed page. Date format 14 Feb 2011 12:00:00 GMT. |
Location | Returns a different URL instead of the URL requested. This can redirect a request to any page for example "Location:http://www.example.com" |
Last-modified | Date a page resource was last modified. |
Content-length | Length in bytes of the data being returned. Allows a browser to report estimated download time for a file. |
Set-Cookie | Sends a cookie to the browser for storing |
For this tutorial we are interested in the Set-Cookie header.
Cookies and CGI
The HTTP protocol is a stateless protocol meaning nothing is saved between serving one page to another or even the same page. A server because of the stateless protocol has no way of knowing if a page has been requested before. To overcome this cookies are used. A page containing set cookies header asks a browser to store its cookies for this server. Next time this page or another page is requested from the same server the stored cookies are sent along with the page request. These cookies are passed to a page as environment variables these can be extracted and processed.
A browser stores cookies in a list consisting of name-value pairs for a specific named server. It sends this list back to only that specific named server with every request.
Each cookie consists of a Name=Value pair followed by these optional attributes
- Expires The date the cookie will expire. If this is blank, the cookie will expire when the visitor quits the browser.
- Domain The domain name of your site.
- Path The path to the directory or web page that set the cookie. This may be blank if you want to retrieve the cookie from any directory or page.
- Secure If this field contains the word "secure" then the cookie may only be retrieved with a secure server. If this field is blank, no such restriction exists.
The format for setting a cookie is shown below. Each cookie attribute is separated by a semi-colon
Set-Cookie: Name=Value; Domain=localhost; Path=/vbs_test; expires=Fri, 22 Sep 2011 21:00:00 GMT
Note: The first attribute Name=Value is required all others are optional.
Header format
The header sent to a browser is the first string written by your CGI script. A blank new-line signifying end of header follows this. The header string must contain a Content-type as the last entry. This header string can become rather long hence split it into smaller and more manageable strings as shown in this example
Dim header header = "Set-Cookie: Name1=Value1; Domain=localhost; expires=Fri, 22 Sep 2011 21:00:00 GMT" &vbLF header = header & "Set-Cookie: Name2=Value2; Path=/; expires=Fri, 22 Sep 2011 21:00:00 GMT" &vbLF header = header & "Set-Cookie: Name3=Value3; Path=/vbs_test; expires=Sat, 23 Sep 2011 21:00:00 GMT" &vbLF header = header & "Set-Cookie: Name4=Value4" &vbLF header = header & "Content-type: text/html"&vbLF&vbLF Wscript.Echo header
The above code snippet sets four cookies Name1 to Name4. A browser will send only the name-value pair of a set cookie, it does not send any other attributes for example the following is sent after setting the above cookies:
- HTTP_COOKIE = Name1=Value1; Name4=Value4; Name3=Value3; Name2=Value2
Extract cookie name value pairs
The HTTP_COOKIE CGI variable is passed to your script with the following format. Each name-value pair is semi-colon delimited this is used for spliting the cookie string. Each name-value pair is separated by an equal sign, again easily split to give component parts.
The following code extracts cookie variables into key (name) and item (value) pairs and adds them to the dictionary.
'--Save any cookie variables If my_hash.Exists("HTTP_COOKIE") Then 'Does cgi_variable HTTP_COOKIE exist cookie_array = split(my_hash.Item("HTTP_COOKIE"), ";") 'Yes: Split variable-value pairs For each str in cookie_array 'Scan cookie pairs pairs_split_array = split(str, "=") 'Split these pairs pairs_split_array(0) = Trim(pairs_split_array(0)) 'Clean pairs_split_array(1) = Trim(pairs_split_array(1)) 'Clean my_hash.add pairs_split_array(0),pairs_split_array(1)'Add to dictionary Next 'Get next pair End If
Expand class to include cookies
Adding the above snippet of code expands our CGI Property Class to include extraction of any cookie variables sent with the page. The full code for our complete class is shown below:
Note: This is the final CGI property class edit file common_function.vbs and replace the old class with this new one.
Class cgi_get_var_class Private my_hash 'Local storage '--Constructor Private Sub Class_Initialize() 'Set inital Set my_hash = CreateObject("Scripting.Dictionary")'Create associative array save_cgi_variables End Sub '-- Load cgi variables into local storage Sub save_cgi_variables Dim wshShell,wshUserEnv,strItem,objRegEx,colMatches,pair1,pair2 Dim method,data_string,variable_array,cgi_variable,decoded_value,i Dim key_array,strKey,cookie_array,pairs_split_array,str '---Save process cgi variables Set wshShell = CreateObject( "WScript.Shell" ) 'Create shell object Set wshUserEnv = wshShell.Environment( "Process" ) 'Read process collection Set objRegEx = New RegExp 'Create new reg obj objRegEx.Pattern = "^(.+?)=(.+)" 'Pattern to search for '(.+?) non-greedy (.+) greedy For Each strItem In wshUserEnv 'Scan returned collection '--Perform regex Set colMatches = objRegEx.Execute(strItem) 'Return collection of Matched objects If colMatches.Count > 0 Then 'Match found pair1 = colMatches(0).SubMatches(0) 'Extract first capturing group pair2 = colMatches(0).SubMatches(1) 'Extract second capturing group my_hash.Add pair1,pair2 'Save locally 'WScript.Echo pair1 & "====" & pair2 & "<br />"'Test code End If Next 'get next item '---Save Post or Get variables method = wshUserEnv("REQUEST_METHOD") 'Get method data_string = wshUserEnv("QUERY_STRING") 'Get query string If method="POST" Then 'If post data read stdin data_string = WScript.Stdin.ReadAll 'Get post data End IF Set wshShell = Nothing 'clean-up Set wshUserEnv = Nothing variable_array = split (data_string, "&") 'split data save to array '--Save internally to my_hash - scripting dictionary for i = 0 to ubound(variable_array) 'Scan array cgi_variable = split (variable_array(i), "=") 'Split variable-value pairs decoded_value1 = replace(cgi_variable(0), "+", " ")'Replace special character decoded_value1 = unescape(decoded_value1) 'Decode encoded value decoded_value2 = replace(cgi_variable(1), "+", " ")'Replace special character decoded_value2 = unescape(decoded_value2) 'Decode encoded value my_hash.add decoded_value1, decoded_value2 'Add to dictionary next 'Get next pair '--Save any cookie variables If my_hash.Exists("HTTP_COOKIE") Then 'Does cgi_variable HTTP_COOKIE exist cookie_array = split(my_hash.Item("HTTP_COOKIE"), ";") 'Yes: Split variable-value pairs For each str in cookie_array 'Scan cookie pairs pairs_split_array = split(str, "=") 'Split these pairs pairs_split_array(0) = Trim(pairs_split_array(0)) 'Clean pairs_split_array(1) = Trim(pairs_split_array(1)) 'Clean my_hash.add pairs_split_array(0),pairs_split_array(1)'Add to dictionary Next 'Get next pair End If End Sub '--Get named variable from my_hash Public Function getvar(key) getvar = my_hash.Item(key) 'return item End Function '--List all data in my_hash used for testing Public Sub list() Dim key_array, strKey key_array = my_hash.Keys 'Get all Keys For Each strKey in key_array 'Scan array Wscript.Echo strKey & " = " & my_hash.Item(strKey) & "<br />" Next End Sub '--Clean-up this class Private Sub Class_Terminate() 'Cleaning up code. Set my_hash = Nothing 'clean-up End Sub End Class
Test script 16 - CGI get property class cookie example
This script demonstrates use of cookies and sending data to the server. It requests a user to login with a name allowing the page content to be viewable. Once logged in the user name is stored as a cookie. Every time this page is revisited the cookie is checked, if set there is no need to re-enter a name. This is demonstrated by clicking the Reload Page link several times. Clicking the Reset Cookie link resets the cookie and returns to the login section.
The first thing to note only a single page is used. This is split into three sections:
Common to the above is the header section. This always sets a cookie before sending the Content-type. Cookie value is either blank or set to a name provided by the user. Note the cookie value is the result of either a user setting a new name or that of an existing value previously set.
|
'!c:/windows/system32/cscript //nologo <job> '-- Include any external files <script language="VBScript" src="common_functions.vbs"/> '-- Main script --- <script language="VBScript"> Option Explicit Dim cgi,header,name,login,my_cookie set cgi = New cgi_get_var_class 'Create new cgi object If cgi.getvar("name") = "" Then 'Cookie not set. Not logged in If cgi.getvar("form_user") = "" Then 'User has not set name in form login = False 'Reset logged in flag Else 'User has set new name logged in login = True 'Set logged in flag my_cookie = cgi.getvar("form_user") 'Ensure returned page sets cookie name = my_cookie 'logged in hence use cookie name End If Else 'Cookie is set. Logged in If cgi.getvar("reset") = "reset" Then 'User wants to reset cookie login = False 'Reset login flag my_cookie = cgi.getvar("") 'Reset cookie Else 'Reset link not clicked login = True 'Remain logged in name = cgi.getvar("name") 'Get logged in name from cookie my_cookie = name 'Set cookie (keeps same name) End if End If '-- Header common to both sections header="" header = "Set-Cookie: name=" & my_cookie &vbLF header = header & "Content-type: text/html"&vbLF&vbLF Wscript.Echo header WScript.Echo "<title>Test 16</title>" '== Not logged in section === If not login then 'Not logged in display login form '--Login page uses form method post WScript.Echo "<b>Use name required</b><br />" WScript.Echo "<form method=""POST"" action=""cooki_1.wsf"" >" WScript.Echo " <input type=""text"" name=""form_user"" value="""">" WScript.Echo " <input type=""submit"" value=""Post"">" WScript.Echo "</form>" End If '=== Logged in section === If login Then 'Logged in display this section '--Main page when logged in Wscript.Echo "Hello <b>" & name & "</b> Welcome<br /><br />" Wscript.Echo "Click the reload link. No login required<br />" Wscript.Echo "Click the reset link. Cookie reset and<br />" Wscript.Echo "returns to login page (section)<br />" End If '--Control for demo always displyed Wscript.Echo "<br />======================<br />" WScript.Echo "<a href=""cooki_1.wsf"">Reload Page</a>" Wscript.Echo " " WScript.Echo "<a href=""cooki_1.wsf?reset=reset"">Reset Cookie</a>" </script> </job> |
Run script
- Create a new file cooki_1.wsf with content as shown on right.
- Save to test folder \www\vbs_test
- Start Apache if not already running
- Enter: http://localhost:8081/vbs_test/cooki_1.wsf into browser.
Test script 17 - CGI get property class cookie password example
This script is based on the above and demonstrates use of cookies to remember a password. Only minor modifications are required, it uses a password hard coded into the script however it could equally have been obtained from a database of file.
If cgi.getvar("form_password") = pass Then login = True my_cookie = cgi.getvar("form_password") my_pass = my_cookie Else login = False End if Note:
|
'!c:/windows/system32/cscript //nologo <job> '-- Include any external files <script language="VBScript" src="common_functions.vbs"/> '-- Main script --- <script language="VBScript"> Option Explicit Dim cgi,header,my_pass,login,my_cookie,pass pass = "fred123" 'The password is hard coded set cgi = New cgi_get_var_class 'Create new cgi object If cgi.getvar("my_pass") = "" Then 'Cookie not set. Not logged in If cgi.getvar("form_password") = "" Then 'User has not set password in form login = False 'Reset logged in flag Else 'User has set new password logged in If cgi.getvar("form_password") = pass Then 'Check against known password/s login = True 'Set logged in flag my_cookie = cgi.getvar("form_password") 'Ensure returned page sets cookie my_pass = my_cookie 'logged in hence use cookie password Else 'Incorrect password login = False 'Reset logged in flag End if End If Else 'Cookie is set. Logged in If cgi.getvar("reset") = "reset" Then 'User wants to reset cookie login = False 'Reset login flag my_cookie = cgi.getvar("") 'Reset cookie Else 'Reset link not clicked login = True 'Remain logged in my_pass = cgi.getvar("my_pass") 'Get logged in password from cookie my_cookie = my_pass 'Set cookie (keeps same password) End if End If '-- Header common to both sections header="" header = "Set-Cookie: my_pass=" & my_cookie &vbLF header = header & "Content-type: text/html"&vbLF&vbLF Wscript.Echo header WScript.Echo "<title>Test 17</title>" '== Not logged in section === If not login then 'Not logged in display login form '--Login page uses form method post WScript.Echo "<b>Password required</b><br />" WScript.Echo "<form method=""POST"" action=""cooki_2.wsf"" >" WScript.Echo " <input type=""text"" name=""form_password"" value="""">" WScript.Echo " <input type=""submit"" value=""Post"">" WScript.Echo "</form>" End If '=== Logged in section === If login Then 'Logged in display this section '--Main page when logged in Wscript.Echo "Your password is <b>" & my_pass & "</b> Welcome<br /><br />" Wscript.Echo "Click the reload link. No login required<br />" Wscript.Echo "Click the reset link. Cookie reset and<br />" Wscript.Echo "returns to login page (section)<br />" End If '--Control for demo always displyed Wscript.Echo "<br />======================<br />" WScript.Echo "<a href=""cooki_2.wsf"">Reload Page</a>" Wscript.Echo " " WScript.Echo "<a href=""cooki_2.wsf?reset=reset"">Reset Cookie</a>" </script> </job> |
Summary
The CGI get property class allows you to easily obtain any CGI variable in particular variables sent to a page from a form, an anchor (link) and previously set cookies.
The above two scripts have shown how to use this class for setting and reading cookies and to read data sent from a form and links. The technique above avoids using a separate page for logging in this may be desirable for some applications.
Where to next
Next page covers a File DB class this class allows you to store a database (Scripting Dictionary) to a file.