HTML Tips and Tricks: The Webmaster's Bakery
by Scott Clark
What is causing all this talk of subversion, espionage, and theft? Magic cookies, of course!
They're an invasion of my privacy." "Every time you get one, it reads your whole hard drive." "It's like getting a virus, and it can even read all of your private accounting documents!" What is causing all this talk of subversion, espionage, and theft? Magic cookies: a topic which seems to anger many people and bemuse the rest. What exactly are cookies, and what do they do? Why do some Web pages load cookies for no apparent reason? Are they an invasion of your privacy? What kind of information can cookies retrieve, and can you stop them? Since there seems to be so much confusion on the Internet about cookies, we're going to take off where Glenn Fleishman left off in his last "Web Talk for Wireheads" column (Web Developer® January/February 1997). We're going to make some cookies, and bake up a batch-showing you just what they're made of. Grab yourself a big glass of milk and a napkin: it's cookie time!
According to Netscape's document, Persistent Client State HTTP Cookies, cookies "are a general mechanism which server side connections (such as CGI scripts) can use to both store and retrieve information on the client side of the connection." When your browser contacts a Web server, the server may send a piece of data called "state information" that will be stored in your machine. This information includes a range of URLs that may access the information. If you once again request a document from any server within that range, the "state information" object is sent to the server as a part of the request.
This "state object" is known as a "cookie" or a "magic cookie." Why a cookie? Perhaps someone was just fond of cookies...no one really knows why.
So what information can a server get from you just by receiving your request? The information below has nothing to do with cookies, except that-like every other request that goes from your browser to a Web server-this information is passed from the client making the request to the server filling the request. This information is passed whether the request is for an image, audio clip, CGI file, text file, or a Web page:
Referrer - This is the Web page that referred the client; the page that the client is coming from.
UserAgent - The name of the browser.
RemoteAddress - IP address of the requesting client. This isn't necessarily the client's IP, as it may just be the IP of the host they are connected to. Also, those who connect with dynamic IPs will have a different IP address each time they log on to the Internet.
RemoteHost-This is the fully qualified domain name of the requesting client. If the server cannot decipher it, it's set to null.
RemoteUser - This is the user ID that is sent by the client, but the server must support user authentication, and 99% of Web servers are not set up to do so.
RequestMethod - Just as it suggests, the Request Method by the client. It is either GET, POST, HEAD, PUT, DELETE, LINK, and UNLINK. Nothing sinister here, just the actual method the client uses to retrieve data from the server.
The server cannot grab your e-mail address or any other information from your browser's user preferences, your hard drive, or anywhere else-unless you actually fill out a form online and send it in. If you did that, the information could then be saved inside a cookie, and the next time you visited the site, the server would be able to "remember" that information about you.
To see the contents of the cookie file, just use any text editor to view it (in Windows versions of Navigator, it's called cookies.txt, and is stored in the same directory or folder as Netscape. Mac users will find it in their Netscape folder in the System|Preferences folder). Internet Explorer stores its cookies as separate files (one for each site) in folders named "Temporary Internet Files" or "Cookies" under the main Windows folder. You'll be able to see all the places that you've been that stored cookies, and a lot of the information that they've stored (although cookies.txt is a text file, much of the stored cookie information may be difficult to decipher). A cookie generally tells the server:
- the domain from which the cookie originated
- if the cookie requires a secure transmission or not
- specific URLs that may access the cookie
- the cookie's expiration date
- the name of the cookie item
- the actual data for the cookie item
Each domain has a limit of one cookie per page with Microsoft's Internet Explorer, while Netscape Navigator's limit is 20 per page, and Navigator limits the total number of cookies in the cookies.txt file to 300.
If you want to know each time you are being sent a cookie, both the latest Navigator and Internet Explorer can be configured to notify you when a cookie is sent. Once you've done that, you'll see just how many sites are using cookies.
Some Web servers, such as Apache, use cookies for each visit to a page (unless specifically set not to), while others are using cookies to track which banner ad you've seen so they can show you a different one the next time you visit.
Another use for cookies is site navigation. On the Web Developer® site, [This was before the new (June97) design -- Ed.] we use cookies to see which of our own pages you're coming from. That way, if you're coming from a no-frame FAQ page, and want to go to the framed version, it checks for the FAQ cookie. If it finds it, then it takes you straight to the framed FAQ page, instead of the framed intro page. If it doesn't find any WD cookies, then you haven't been there yet, so it settles for the default framed intro page. The cookies are only stored for the current visit, and when you close the browser, they're gone.
So how do these cookies get set? The code, boss, the code! Cookies are pretty straightforward; the hard stuff is using the information that you store in them effectively. Netscape's cookie page explains the syntax for setting cookies using CGI, and the January/February 1997 issue's "Web Talk for Wireheads" went into details on the use of CGI for setting cookies, so we won't spend any time here on that.
Since the release of Netscape 2.0, JavaScript has been available for developers to use to enhance their Web pages. Microsoft Internet Explorer also now has JavaScript support, in the form of JScript. Although IE handles cookies, JScript's support for cookies is minimal at this time (IE 4.0 will have more JScript functions and capabilities). Using Netscape's Navigator, cookies can be set with JavaScript by simply using this syntax:
document.cookie = "OurCookie=isnowset; PATH = /";
This sets the new cookie, "OurCookie," with a value of "isnowset." The PATH is set so that any pages served from the root directory outward are okay, as long as they are coming from the same domain. If no expiration date is set, as with this example, the cookie is kept in memory, and isn't written to the cookie.txt file.
So what kind of stuff can you do using a simple batch of cookies? How about letting a visitor specify whether or not they want frames, and using that decision to write the page accordingly, on the fly? I've set this up so that when the visitor first goes to the page, the non-framed page has a checkbox to click if they prefer frames. When the page is reloaded, frames are displayed, and later, when they go back to the site, their preferences are noted, and frames are again loaded. If the visitor changes their mind, the frames version features the same checkbox to turn frames off.
This script starts with some public cookie functions for setting and retrieving cookies that Bill Dortch has been so kind as to freely give to the Web community.
<SCRIPT LANGUAGE= "JavaScript">
<!---
// Public domain cookie code written by:
// Bill Dortch, hIdaho Design
// (bdortch@netw.com)
function getCookieVal (offset) {
var endstr = document.cookie.indexOf (";", offset);
if (endstr == -1)
endstr = document.cookie.length;
return unescape(document.cookie.substring(offset, endstr));
}
function GetCookie (name) {
var arg = name + "=";
var alen = arg.length;
var clen = document.cookie.length;
var i = 0;
while (i < clen) {
var j = i + alen;
if (document.cookie.substring(i, j) == arg)
return getCookieVal (j);
i = document.cookie.indexOf(" ", i) + 1;
if (i == 0) break;
}
return null;
}
// end public cookie functions
//--><br>
</SCRIPT>
Now starts the actual page. We test for the frames cookie that would be there if the viewer had already been to the site. If we find it, and it's not set to frames, we write a <BODY> tag to the page. If we find it and it is set to frames, then we write out a <FRAMESET> tag. Document.write() is a simple JavaScript function we'll use to write to the current document.
<SCRIPT LANGUAGE= "JavaScript">
<!---
if(GetCookie("frames") != "on")
document.write("<BODY>");
else document.write("<FRAMESET COLS=\"130,*\">
<frame src=/old?u=http%3A%2F%2Fwww.webdeveloper.com%2Fjavascript%2F%5C&y=1999"left.htm\">
<frame src=/old?u=http%3A%2F%2Fwww.webdeveloper.com%2Fjavascript%2F%5C&y=1999"right.htm\">
</FRAMESET>");
// the document.write statement must actually be on
// one line, or MSIE gives an error...go figure?
function setcookie(){
document.cookie = "frames=on; PATH=/";
}
//-->
</SCRIPT>
This little form allows us to use a checkbox to indicate if we want frames or not. We could have also used a graphic or button, and we could have had the button refresh the page as well, but we'll save that for a later column.
<FORM>
<INPUT TYPE = "checkbox" onClick = setcookie()>
<B>I WANT FRAMES FROM NOW ON!</B>
</FORM>
<FONT SIZE=+2>The software industry</FONT>
is still reeling after today's announcement that
Microsoft and Netscape have merged their browsers
into a single browser called Internet Navigator.
</BODY>
</HTML>
And we need some code for the framed version so the viewer can still
change their mind and go back to the no-frames version. Once again we
first call upon Bill Dortch's cookie functions:
<html>
<head>
<title></title>
<SCRIPT LANGUAGE="JavaScript">
// Public domain cookie code written
// by Bill Dortch, hIdaho Design
// (bdortch@netw.com)
function getCookieVal (offset) {
var endstr = document.cookie.indexOf (";", offset);
if (endstr == -1)
endstr = document.cookie.length;
return
unescape(document.cookie.substring(offset, endstr));
}
function GetCookie (name) {
var arg = name + "=";
var alen = arg.length;
var clen = document.cookie.length;
var i = 0;
while (i < clen) {
var j = i + alen;
if (document.cookie.substring(i, j) ==arg)
return getCookieVal (j);
i = document.cookie.indexOf(" ", i) + 1;
if (i == 0) break;
}
return null;
}
// end public cookie functions
//-->
</SCRIPT>
</head>
<SCRIPT LANGUAGE="JavaScript">
<!---
function setcookie(){
document.cookie = "frames =off; PATH = /";
}
//-->
</SCRIPT>
<FORM>
<INPUT TYPE = "checkbox" onClick = setcookie()>
<b>
I WANT NO FRAMES FROM NOW ON!
</b>
</FORM>
</BODY>
</HTML>
This allows the viewer to click the checkbox to return to the non-framed version (by refreshing the page) if they so desire (see screen shot). This is just one of the many excellent functions that cookies can provide, and this example gives you an idea of how to go about using cookies and simple JavaScript. Cookies aren't necessary for every site, but they do provide an versatile, extendible tool for developers. As long as folks are clear about exactly what cookies do, they'll be a lot less likely to resent them. After all, they don't just have to be used for marketing, as the above example proves. Cookies are your friends!
Bring Out Your Best
We'd like to use this column to show developers the greatest HTML tips and tricks. To accomplish this task, we need you, the reader, to send in your slickest Web tricks that use HTML, JavaScript, or other inline coding technologies. If we publish your tip, you'll get a free Web Developer® carry bag loaded with interesting and valuable goodies, as well as fame, glory, and professional adulation. Show the world how clever you are, and we can all improve our techniques and Web sites. Please send your annotated code to me at
sclark@webdeveloper.com.
A side note: At the Fall Internet World in New York, Pretty Good Privacy announced their new product, PGPcookie.cutter. Selling for $19.95, this utility lets you figure out exactly which Web sites are setting cookies. You can even block all cookies except the ones that you've chosen. (Both new versions of Navigator and Internet Explorer also allow you to be notified). Cookie.cutter allows you to specify a domain or list of domains for which cookies are to be accepted. Also, ZDNet has released a free CookieMaster software utility (www.hotfiles.com) which allows users to identify pages that use cookies and delete the cookies they don't want.
Scott Clark, Technical Editor of Web Developer®, never dunks cookies in his milk.
Reprinted from Web Developer® magazine, Vol. 3 No.2 Mar/Apr 1997 (c) 1997 internet.com Corporation. All rights reserved.
Web Developer® Site Feedback
Web Developer®
Copyright © 1999 internet.com Corporation. All rights reserved.