N342 Visitor Data - Hidden Variables and Cookies

Modified:

Web servers are generally stateless. One problem with the stateless nature of Web servers is that no previous information about the client browser state is held by the server. Though it greatly simplifies the server design, it means that the server remembers nothing from one connection to the next; each new page or refresh makes a new connection to the server. If you were playing a Tic-Tac-Toe game on a server, the server needs information about the current state of the game (i.e. the board positions occupied). In stateless operation, the server starts each connection anew, so would always be starting a fresh game unless the game state were supplied by the browser.

For the Tic-Tac-Toe game state, the browser might hold the board and player state information, sending with each move to the server. The URL with player x in board position 1, o in board positions 4 and 5, and player x moving to position 3 might appear as:

    tictactoe.asp?board=0x23oo78&x=3

With the browser client holding the state, the server can remain stateless, receiving the current game state each time the browser connects and sends the game state of: board=0x23oo78&x=3 in the URL.

 

Hidden Variables

Hidden variables provide one means for the client to hold and send state to the server. Hidden variables are basically the same as buttons, text, etc. except the browser doesn't display the variables, they're hidden.

Recall that user input can be sent from the browser text and button entries using the GET or POST form methods. For example, the HTML of

<form action="http://localhost/CGI/tictactoe.exe" method="GET">
   Your move? <input type="text" name="move" size="2" />
</form>

displays a text box of 2 characters in the browser. Typing 4 into the text box and pressing Enter executes the http://localhost/CGI/tictactoe.exe action and GETs 4 as standard input of move=4.

Your move?
4
http://localhost/CGI/tictactoe.exe?move=4  

Hidden variables are data held by the browser client and returned to the server through the GET or POST form method just as a variable that is not hidden. What differs is that nothing is displayed by the browser, no text or buttons, and a value is assigned the variable in the HTML. For example, the HTML of:
 

<form action="http://localhost/CGI/tictactoe.exe" method="GET">
    <input type="hidden" name="board" value="0x234o678" />
</form>

displays nothing but assigns a hidden variable board = "0x234o678".

http://localhost/CGI/tictactoe.exe?board=0x234o678  

 

Hidden Variables
URL

http://localhost/CGI/tictactoe.exe



HTML

<b>TicTacToe</b><br>
Enter Move X.<br>
<pre>
<form action="tictactoe.exe" method="GET">
<input type="text" name="move" size=2>
  0|x|2    <br>
  _|_|_    <br>
  3|4|o    <br>
  _|_|_    <br>
  6|7|8    <br>
</pre>
<input type="hidden" name="board" value="0x234o678">
</form>



URL with move and board GET data

http://localhost/CGI/tictactoe.exe?move=6&board=0x234o678

TicTacToe source code

 

Cookies

Before discussing cookies, an understanding of the server/browser communication is necessary. Recall the typical communication between a browser client and a Web server.

  1. Browser connects to the server IP address and sends a request for a file to be returned, for example:


  2.         GET /rwisman/Hello.htm HTTP/1.1
     
  3. The server retrieves an HTML file, or executes a CGI or server script, returning the results to the browser.
     
  4. The server or browser disconnects, breaking the connection.

Because the server is stateless, it maintains no data about a client between connections, effectively forgetting about the client. We have seen that user data can be maintained in a database on the server but that the user is required to identify themselves, perhaps by logging into an application. We've also seen that hidden variables can be used to maintain data temporarily on the page loaded by the client. Using a server database to maintain long-term data, hidden variables to maintain short-term data, and logins to provide initial user identification, state-full systems can be implemented.

Cookies provide a simple method for maintaining state on the client and are often used in combination with the server database, hidden variables, and user login. Cookies consist of data stored at the behest of the server by the browser on the client's file-system and are sent to the server by the client.  A complete specification is at http://www.netscape.com/newsref/std/cookie_spec.html.

In contrast to hidden variables, which only exist as long as the browser holds the HTML page, cookies are relatively long lived, stored on the client file-system. Typically, the server stores a cookie on the client machine during the first visit, to read and possibly update the cookie data on subsequent visits. Because cookies are stored on a client file-system, the cookie is only available through that computer, so someone using multiple machines for logging into a system would need to go through the process of creating the cookie again on other clients.

 

Sending a cookie

The cookie is sent by the browser whenever a URL in the cookie domain is accessed. For example, the following is the full request sent from a browser to www.google.com which had previously stored a cookie.

GET /search?hl=en&lr=&ie=UTF-8&oe=UTF-8&q=babble HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)
Host: www.google.com
Connection: Keep-Alive
Cookie: PREF=ID=6badbe492bad4u60:TM=1055825476:LM=1055825476:S=PY-bEWHY-ONOTSPY

 

Receiving a cookie

The partial server response sends a new cookie for the domain google.com meaning that the browser should send the cookie whenever contacting any URL in that domain.

HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/html
Set-Cookie: PREF=ID=6badbe492bad4u60:TM=1073216819:LM=1073216819:S=X60DAR7nmCtEjlxa;
expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com
Server: GWS/2.1
Transfer-Encoding: chunkedDate: Mon, 19 Jan 2004 16:40:19 GMT

 

Storing cookies

Netscape stored cookies in a file named cookie.txt in the c:\Program Files\NetScape\Users\name directory where name is the user name.

At one time, Internet Explorer stored cookies in directory C:\Documents and Settings\username\Cookies where each cookie is a separate file named similar to: ray@google[1].txt. More recent versions attempt to hide the cookies.

Netscape

The format of the fields generally follows:

  1. Domain. - www.southwest.com
  2. Path. - /cgi-bin
  3. Whether cookie must travel on a secure connection. - TRUE
  4. Expiration date of cookie. - 1016513978
  5. Name of cookie information. - resPurchasePage
  6. Value of cookie information. - &CC_FIRSTNAME=Raymond&CC_LASTNAME=Wisman
# Netscape HTTP Cookie File
# http://www.netscape.com/newsref/std/cookie_spec.html
# This is a generated file!  Do not edit.
www.southwest.com  TRUE /cgi-bin TRUE 1016513978 resPurchasePage &CC_FIRSTNAME=Raymond&CC_LASTNAME=Wisman
localhost       FALSE   /N342/Cookies   FALSE   955670399       N342Student     Ray
.cheaptickets.com TRUE / FALSE 1135987200 referrer http%3A//www2.travelocity.com/LastMinuteDeals/
www.ticketmaster.com FALSE / FALSE 2145801577 NGUserID cf5834ce-235-954257833-1
.amazon.com TRUE / FALSE 955439972 session-id 104-2727763-7122841
www.perlscripters.com FALSE / FALSE 1293753514 WEBTRENDS_ID 149.160.29.92-2415653776.29335619

Internet Explorer

The files includes variables and data defined by the browser and server, most of which is encoded and not obviously readable:

PREF
ID=74502d5f99c8b0f7:TM=1117665947:LM=1117665947:S=hUnqRK_Aj9wghDLM
google.com/
1536
2618878336
32111634
2806618384
29714171
*

 

Cookies are text information stored on the browser by a the server or client JavaScript for temporarily or for a specified amount of time. Cookies are often used to personalize visits but not always reliable when several people use one machine.

 The following sets the temporary WHO cookie to Ray.

<a href="" onClick='document.cookie = "WHO=Ray;"; return false;'> Set Cookie</a>
<script language="JavaScript">
   var theCookie = unescape(document.cookie);   // Read cookie and find WHO
   var start = theCookie.indexOf("WHO=")+"WHO=".length;
   var end = theCookie.indexOf(";",start);
   if(end==-1) end=theCookie.length;
   document.write("Hello "+theCookie.substring(start,end));
</script> 

 

Sending Cookies

Cookies are set from within a HTTP request, before the Content-type header. The minimal information sent is:

  1. NAME=VALUE - The name and value of the cookie information. For example, N342Student=Ray, would have NAME of N342Student and VALUE of Ray.
     
  2. Expiration date - Necessary for browser to store the cookie to the cookie file, defines the last valid date and time for the cookie. The cookie is not saved if set to a past date. An example is: expires=Wednesday, 13-June-2007 23:59:59.

An example of setting a cookie with N342Student=Ray is given below. Note that the path that is stored with the cookie is the server URL path. If the paths differ, then more than one cookie is created and stored, if a cookie already exists it is replaced. Only CGIs or ASPs located in that original path can receive that cookie from the browser.

     

    ASP - The effect of setting a cookie is the same in any language. ASP Response.Cookies can set a cookie. One point of note, the cookie must be written before the <HTML> tag, since the cookie is written before the Content-type of the HTTP header.

    Setting a Cookie in ASP
    URL

    http://localhost/N342/SendCookie.asp


    ASP SendCookie.Asp

    <%@ LANGUAGE = JScript %>
     <%
         Response.Cookies("N342Student")="Ray";
         Response.Cookies("N342Student").Expires = "June 12, 2008";
     %>
     <HTML>
     <H1>A cookie has been sent to your machine.</H1>
     </HTML>


    Sent to browser

    Set-Cookie: N342Student=Ray; expires=Thursday, 12-June-2008 23:59:59
    Content-type: text/html

    <H1>A cookie has been set on your machine.</H1>


    Stored in C:\Users\rwisman\AppData\Roaming\Microsoft\Windows\Cookies

    rwisman@localhost[1].txt by IE, note localhost is the path where cookie originated.  

    N342Student
    Ray
    localhost/N342
    1024
    1586061312
    29716428
    1527165296
    29715124
    *

Exercise 1 - Sending Cookies

Send a cookie to the browser.

  1. Locate the IE Cookie directory and files. Under XP, for rwisman in C:\Documents and Settings\rwisman\Cookies. An Ebay cookie is in file rwisman@ebay[1].txt.
  2. Examine it for the cookie sent. Note that some browsers do not write the cookie to the file immediately but holds in cache memory. You may need to close all browser windows and restart to see any changes in the cookie file.
  3. Copy and paste the above SendCookie.Asp to send a cookie with an expiration date a few days in the future. Use GMT in the form of: expires=13-June-2007 23:59:59 GMT
  4. Change the value of the cookie and send again. Then repeat Step 1.

 

    Setting a Cookie in Perl
    URL

    http://localhost/CGI/SendCookie.pl


    Perl SendCookie.pl program

    print << "EndOfHeader";
    Set-Cookie: N342Student=Ray; expires=Wednesday, 13-June-2007 23:59:59
    Content-type: text/html

    <H1>A cookie has been sent to your machine.</H1>
    EndOfHeader



    Sent to browser

    Set-Cookie: N342Student=Ray; expires=Wednesday, 13-June-2007 23:59:59
    Content-type: text/html

    <H1>A cookie has been set on your machine.</H1>



    Stored in Cookie.txt by Netscape, note CGI is the path where cookie originated.  

    localhost FALSE /CGI FALSE 955670399 N342Student Ray

 

Receiving Cookies 

As noted, unless a different domain path was designated when the cookie was created, cookies are sent from the browser to a CGI or ASP in the original path.

To receive the cookie, the GetCookie.asp program must be in the same path from which the cookie was originally created.

The browser returns all cookies that were sent from that path, regardless of the requesting program. The cookies are sent as a list in the environment variable name HTTP_COOKIES. The receiving program must then parse the HTTP_COOKIE list of returned cookies to locate the one of interest.

ASP - ASP Request.Cookie can get a cookie value. To get the value of the cookie set in the above example is trivial.

Getting a Cookie in ASP
GetCookie.Asp

<%@ LANGUAGE = JScript %>
    Cookie value of N342Student is <%= Request.Cookies("N342Student")  %>
 

Browser output

Cookie value of N342Student is Ray


Retrieving a Cookie in Perl
URL

http://localhost/CGI/GetCookie.pl



Browser output

N342Student=Ray



HTTP_COOKIE Returned

HTTP_COOKIE=N342Student=Ray

Perl GetCookie.pl program

print << "EndOfHeader";
Content-type: text/html

   $ENV{'HTTP_COOKIE'}
EndOfHeader

 

 

 

 

 

 

 

 

 

 

Exercise 2 - Retrieving Cookies

Receive the cookies sent.

  1. Copy and run the GetCookie.asp program from the same directory where the cookies were sent.
  2. All cookies sent from that path should be listed.
  3. Copy the GetCookie.asp program to another virtual directory and run again. None of the cookies should be listed.
  4. Display the environment variables to see what the cookies look like in the raw.
    1. Copy the following ASP program that displays all server variables to the same directory used to send the cookies.
    2. Run from a browser.
    3. Locate the HTTP_COOKIES environment variable.

ServerVariables.asp - List ALL environment variables
<%@ Language=JavaScript%>

<%
    for(i=1; i<=Request.ServerVariables.Count(); i++) {
       strKeyName = Request.ServerVariables.Key(i);
       strKeyValue = Request.ServerVariables.Item(strKeyName);
       Response.Write(
             i + " " + strKeyName + "=" + strKeyValue + "<br>");
    }
 %>
 
Output (partial)
HTTP_HOST=localhost
HTTP_USER_AGENT=Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
HTTP_COOKIE=N342Student=Ray; ASPSESSIONIDCCRABSCB=HFBBDMDCHHONCBPDCFICGGFF

 

Example - A more realistic example gathers SSN user information and stores as a cookie. Later, when the user visits the site again, the SSN cookie is used to lookup the name of the person from the EMPLOYEE database.

Example of Sending and Getting a Cookie for Lookup in an Access Database
HTML

<TITLE>Win BIG Money</TITLE>

<FORM Method='GET' 
              Action='http://localhost/N342/SSNsend.asp'>

To be eligible to win just enter your SSN
    <Input Type='Text' name="SSN">
</FORM>


ASP to send cookie - http://localhost/N342/SSNsend.asp

<%@ Language=JavaScript%>

<%
  SSN = Request("SSN"); 
  Response.Cookies("SSN")=SSN;
  Response.Cookies("SSN").Expires = "June 13, 2007";
%>
<H1>Thanks! <%= SSN %></H1><br>

SSN Cookie stored by NetScape

localhost FALSE /N342 FALSE 955670399 SSN 999887777

URL to execute ASP to get SSN cookie

http://localhost/N342/SSNget.asp


ASP to get SSN cookie - http://localhost/N342/SSNget.asp

<%@ Language=JScript%>
<%
  conn = Server.CreateObject("ADODB.Connection");
  conn.Open ("DRIVER={Microsoft Access Driver (*.mdb)};DBQ=" +
                     Server.MapPath("Comp-2000.mdb"));
  rs = conn.Execute("SELECT Fname, Lname FROM Employee Where SSN='" +
              Request.Cookies('SSN') +"';");
%>
<H1>Cookie Winner</H1>
Hello <%= rs("Fname")+" "+rs("Lname")+" "+Request.Cookies('SSN') %>

Cookie Winner

Hello Alicia Zelaya 999887777

 

Exercise 3 - Using Cookies

Use the cookies sent from the browser.

  1. Set up the above HTML and ASP programs in a new virtual directory. You'll need to edit the Action of the HTML form.
  2. Run the HTML to set a cookie from the new virtual directory. Use SSN=999887777.
  3. Examine the Cookie directory and files.
  4. Run the SSNGet.asp program to verify that it does work.

 

Exercise 4 - State

Cookies offers a means to maintain state, similar to an exercise from Client Side Programming Exercise 3 - URL State.

Create a modulus 4 counter using a cookie.

  1. Create an ASP or CGI file named Exercise3.Asp, etc. using any language but C++.
  2. Collect the four different image files (right click on the image to save). Name them "digit0.gif", "digit1.gif", etc. for example.
  3. Define an HREFs with an image source of "digit0.gif". HREF linking should occur, that is generate:

  4.       <A HREF="Exercise3.Asp"><IMG SRC="digit0.gif"></A> ) when the digit image is clicked.
  5. When the digit link is clicked, increment the image displayed to the next image; digit0.gif, digit1.gif, etc. and back to digit0.gif. Use the cookie state to count which image is displayed. The modulus operator in JavaScript and PerlScript is %, VBScript is Mod.
  6. The Response object automatically handles the details of writing cookies. When writing cookies directly to the client, remember that the cookie must be sent before the Content-type header part is written, for example in Perl:
    • print <<EndOfHeader;
    • Set-Cookie: counter=3; expires=Wednesday, 11-June-2008 23:59:59
    • Content-type: text/html
    • EndOfHeader

Some JavaScript for handling cookies:

  • if (Request.Cookies("count") != "")  - Test if the cookie "count" exists.
  • count = Request.Cookies("count"); - Get the value of cookie "count" as a string.
  • count = parseInt(Request.Cookies("count")); - Get the value of cookie "count" as an integer.
  • Response.Cookies("count")=3;  - Set cookie "count" to 3.
  • Response.Cookies("count").Expires = "June 13, 2007";  - Set cookie "count" expiration date.