home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Freelog 17
/
Freelog017.iso
/
BestOf
/
HtmlGate
/
htmlgate2000.exe
/
README
< prev
Wrap
Text File
|
1996-12-26
|
31KB
|
627 lines
##############################################################################
# HTTP Cookie Library Version 2.1 #
# Copyright 1996 Matt Wright mattw@worldwidemart.com #
# Created 07/13/96 Last Modified 12/23/96 #
# Scripts Archive at: http://www.worldwidemart.com/scripts/ #
# Parts of Code Contributed by Jeff Carnahan (http://terminalp.com/scripts/) #
##############################################################################
# If you run into any problems while trying to configure this script, help #
# is available. The steps you should take to get the fastest results, are: #
# 1) Read this file thoroughly #
# 2) Consult the Matt's Script Archive Frequently Asked Questions: #
# http://www.worldwidemart.com/scripts/faq/ #
# 3) If you are still having difficulty installing this script, send #
# e-mail to: scripts-help@tahoenet.com #
# Include any error messages you are receiving and as much detail #
# as you can so we can spot your problem. Also include the variable#
# configuration block that is located at the top of the script. #
# #
# Hopefully we will be able to help you solve your problems. Thank you. #
##############################################################################
# COPYRIGHT NOTICE #
# Copyright 1996 Matthew M. Wright All Rights Reserved. #
# #
# HTTP Cookie Library may be used and modified free of charge by anyone so #
# long as this copyright notice and the comments above remain intact. By #
# using this code you agree to indemnify Matthew M. Wright from any #
# liability that might arise from it's use. #
# #
# Selling the code for this program without prior written consent is #
# expressly forbidden. In other words, please ask first before you try and #
# make money off of my program. #
# #
# Obtain permission before redistributing this software over the Internet or #
# in any other medium. In all cases copyright and header must remain intact #
##############################################################################
TABLE OF CONTENTS:
==================
1) Overview
2) cookie.lib Configuration
a) $Cookie_Exp_Date
b) $Cookie_Path
c) $Cookie_Domain
d) $Secure_Cookie
e) @Cookie_Encode_Chars
f) %Cookie_Encode_Chars
g) @Cookie_Decode_Chars
h) %Cookie_Decode_Chars
3) Using this Library in your CGI script.
a) Requiring the library.
b) Subroutine calls.
+ &GetCookies
+ &SetCookieExpDate
+ &SetCookiePath
+ &SetCookieDomain
+ &SetSecureCookie
+ &SetCookies
+ &SetCompressedCookies
+ &GetCompressedCookies
4) Character Translation Information
5) Any Examples Available?
a) ccounter.pl
b) Scripts Around the World
6) Other Cookie Resources
7) History
##############################################################################
OVERVIEW
========
HTTP Cookie Library is a Perl 4 and 5 compatible library which allows you to
easily use Persistent Client State HTTP Cookies by allowing you to get the
cookies from the environment, prepare cookies, set cookies, change the
expiration date, domain and path all with easy subroutine calls.
Version 2.0 and 2.1 contain many changes, including the ability to compress
multiple cookies into one, the elimination of the &PrepareCookies subroutine,
and fixes allowing you to set more than one cookie at a time. The addition of
character URL-encoding and the fixing of a scoping bug brought on by
localizing the global variables used in this script are new to version 2.1.
NOTE: Anyone who used 2.0 and &UnCompressCookies should now change all
references from &UnCompressCookies to &GetCompressedCookies. The calls
to these routines are the same, however the name has been changed.
For more information on Cookies, and to see the preliminary specifications
of Persistent Client State HTTP Cookies to which this library conforms, visit
http://www.netscape.com/newsref/std/cookie_spec.html
There are three files included with this script:
1) README - This file; includes detailed installation
instructions.
2) cookie.lib - The Perl script which generates the random phrase
and displays it on your web page.
3) ccounter.pl - An example of how to use this library.
The cookie.lib perl library is not a stand-alone CGI script. It is meant to
be used in conjunction with a script that you build. It's only purpose is to
facilitate the usage of client side persistent HTTP cookies. This means, in
order to use this library, you should always have the following line in your
script somewhere:
require '/path/to/cookie.lib';
This will then tell Perl to retrieve this file and include it's code and
subroutines in your script. Nonetheless, there are some variables which you
can modify in the cookie.lib file before you place it on your system. All
of these variables can be modified through special subroutines in cookie.lib
so it is not necessary to edit any of them.
##############################################################################
COOKIE.LIB CONFIGURATION
========================
This program contains three variables which can be modified in the library, to
make it easier to use on your system. They can also be set through calling
subroutines, which is explained in: 'Using this Library in Your CGI Script,'
or by setting them in your main script, as they are local variables which can
be modified. The subroutines provide checks to make sure the value is valid.
$Cookie_Exp_Date = '';
This variable defines the expiration date of your cookie.
When this date arrives the browser will ask the user if
they want to delete the cookie, and that it is ok to do so.
This date must always be represented as:
Wdy, DD-Mon-YYYY HH:MM:SS GMT
and always has to be in GMT time. An example would be:
Wed, 09-Nov-1999 00:00:00 GMT. By default, if this is
not filled in, the browser will delete the cookie when the
session ends. Also see &SetCookieExpDate.
$Cookie_Path = '';
This path defines where under your domain the cookies
should be sent. For instance, if your URL is:
http://domain.xxx/your_dir/, there is no reason for the
browser to send the Cookie header to the base domain name.
Therefore, you would set this to '/your_dir'; However,
because this can be set through the script, set it to
whatever directory will use this most often or whichever
directory you want as default. If nothing is placed here,
the default will be assumed to be the script or page which
created the cookie. Also see &SetCookiePath.
$Cookie_Domain = '';
This defines the base domain to which the browse passes the
cookie. If you have a domain: www.host.xxx, your.host.xxx
and host.xxx, which all will use this, you would set this
variable to: '.host.xxx'; The following is an excerpt from
the Netscape Preliminary Specifications of Persistent Client
State HTTP Cookies:
"Only hosts within the specified domain can set a cookie for
a domain and domains must have at least two (2) or three (3)
periods in them to prevent domains of the form: ".com",
".edu", and "va.us". Any domain that fails within one of the
seven special top level domains listed below only require
two periods. Any other domain requires at least three. The
seven special top level domains are: "COM", "EDU", "NET",
"ORG", "GOV", "MIL", and "INT"."
Also see &SetCookieDomain.
$Secure_Cookie = '0';
This defines whether or not you want to restrict the
transmission of the cookie to a secure server. If this flag
is set to '1', by default the cookies you create will only be
sent to secure servers by the client. This can also be
changed through &SetSecureCookie.
@Cookie_Encode_Chars = ('\%', '\+', '\;', '\,', '\=', '\&', '\:\:', '\s');
This defines the order in which the special characters should
be encoded. More info can be found in section entitled
'Character Translation Information'.
%Cookie_Encode_Chars = ('\%', '%25',
'\+', '%2B',
'\;', '%3B',
'\,', '%2C',
'\=', '%3D',
'\&', '%26',
'\:\:', '%3A%3A',
'\s', '+');
This associative array defines the characters to be
translated as the keys, which can be referred to as:
$Cookie_Encode_Chars{key} and the values which these
characters should be translated into. More info can
be found in section entitled 'Character Translation
Information'.
@Cookie_Decode_Chars = ('\+', '\%3A\%3A', '\%26', '\%3D', '\%2C', '\%3B', '\%2B', '\%25');
This defines the order in which the special characters should
be decoded. More info can be found in section entitled
'Character Translation Information'.
%Cookie_Decode_Chars = ('\+', ' ',
'\%3A\%3A', '::',
'\%26', '&',
'\%3D', '=',
'\%2C', ',',
'\%3B', ';',
'\%2B', '+',
'\%25', '%');
This associative array defines the characters to be
translated as the keys, which can be referred to as:
$Cookie_Decode_Chars{key} and the values which these
characters should be decoded into. More info can be
found in section entitled 'Character Translation
Information'.
##############################################################################
USING THIS LIBRARY IN YOUR CGI SCRIPT.
======================================
HTTP Cookie Library is not meant as a standalone CGI script. It must be used
in conjunction with other scripts you have written, and provides a basic
outline and easy subroutines which makes implementing the cookies into your
perl program easy.
Also, to give cookies to the user, the browser must be pointed to the CGI
application or the CGI application must be imbedded in the HTML document
through Server Side Includes or other technology, such as JavaScript. If
you choose the JavaScript path, some browsers which support cookies won't
be able to receive them and JavaScript users have no use for this library
as it is only compatible in Perl scripted CGI applications.
Requiring the Library:
----------------------
Near the top of your Perl CGI script (or before you make the first call to a
subroutine which is in cookie.lib), you will need to include the line:
require '/path/to/cookie.lib';
If you place the cookie.lib in the same directory as your CGI script, or in
a path which is defined in @INC, you can call it with:
require 'cookie.lib';
Now all of the subroutines which this script contains can be used in your CGI
Perl script. Here's is a summary of them, what they do and how to call them:
Subroutine Calls:
-----------------
&GetCookies('cookie_name1',...,'cookie_namen');
This function can be called as simply &GetCookies, or using arguments
such as &GetCookies('cookie1','cookie2'). Calling it without
arguments means that it will return a '1' if cookies are found, a 0
if they are not. This is useful, so that you can perform function
like:
if (&GetCookies) {
# Successful Code Here;
}
else {
# Give them a Cookie Here;
}
In the above circumstance, if cookies are found, the successful code
gets executed. Otherwise, you can give them a cookie. The
&GetCookies subroutine then takes the cookies from the environment
and places them in an associative array. This array is %Cookies.
So if you have set a cookie named 'visit' with a value which contains
whatever you set it for, then you would obtain this value by using
the scalar variable $Cookies{'visit'}.
Now, let's say that a lot of cookies are set for your base domain and
path. They would all get included in the return if you didn't
specify arguments for &GetCookies. For instance, in the above
example, since &GetCookies would return a value of '1' if any cookies
are set, that could mess up this script, if all we want to know is if
the visit cookie is set. Therefore, we would change the above program
to only need to 'visit' cookie:
if (&GetCookies('visit')) {
# Successful Code Here;
}
else {
# Give them a Cookie Here;
}
Now, only the $Cookies{'visit'} scalar will be set and if it is not
&GetCookies will return a 0 and the else { } statement will be
executed.
You can check for multiple cookies to be set by &GetCookies('name1',
'name2','etc...'); However this will return a true value (1) if any
of those cookies are set. You can get around this by calling them one
at a time, although this is tedious.
If you have compressed your cookies with &SetCompressedCookies, you
will need to look into the &GetCompressedCookies routine to do what
&GetCookies does.
&SetCookieExpDate('Wdy, DD-Mon-YYYY HH:MM:SS GMT');
By default in the script, the cookie is set to expire when the browser
session ends. If you wish for the cookie to expire at a later date,
then all you have to do is change the date by calling &SetCookieExpDate
with an argument containing the new date. The new date must be in the
format as shown above, or it will not set right. The following is an
example:
&SetCookieExpDate('Wed, 09-Nov-1999 00:00:00 GMT');
If your date does not match a regular expression which checks to see
if it is valid, it will return a 0. So it you catch the value, you
can do:
if (&SetCookieExpDate('Wdy, DD-Mon-YYYY HH:MM:SS GMT')) {
# Continue here.
}
else {
# Do Error Stuff Here. &SetCookieExpDate failed.
}
For any cookies which you wish to be able to detect if the user closes
the browser's session and then re-opens it, you will need to set this
to a specific date.
The $Cookie_Exp_Date variable can also be changed at the top of
cookie.lib, or at any point inside of the perl script which required
cookie.lib, simply with the statement:
$Cookie_Exp_Date = 'Wdy, DD-Mon-YYYY HH:MM:SS GMT';
The subroutine is provided to check the syntax of your date.
&SetCookiePath('/path');
By default, this is set to the path of the script or web page which sets
the cookie, so unless this has been set differently in cookie.lib to
contain a value, you need not call this function. However, if you wish
for those values to be passed to other scripts under the same domain,
you will need to have this set to that path of the URL. For
instance, if I only want my cookies passed to URLs which are at least:
http://www.worldwidemart.com/scripts, I would call this function as:
&SetCookiePath('/scripts');
You can also set the cookie path with the statement:
$Cookie_Path = '/path/you/want/to/set';
You can place this statement anywhere in your Perl programs after you
have required the cookie.lib library.
&SetCookieDomain('.host.xxx');
If the value of your desired domain suffix (.host.xxx) was assigned
a different value as default, you can change this by placing a domain
name in the call to &SetCookieDomain. Most of the time you shouldn't
have to worry about this. Below are the rules which this script
follows, taken directly from Netscape documentation:
"Only hosts within the specified domain can set a cookie for
a domain and domains must have at least two (2) or three (3)
periods in them to prevent domains of the form: ".com",
".edu", and "va.us". Any domain that fails within one of the
seven special top level domains listed below only require
two periods. Any other domain requires at least three. The
seven special top level domains are: "COM", "EDU", "NET",
"ORG", "GOV", "MIL", and "INT"."
The $Cookie_Domain can also be set using the statemement:
$Cookie_Domain = 'host.xxx';
You can place this statement anywhere in your Perl programs after you
have required the cookie.lib library.
&SetSecureCookie('0' || '1');
This defines whether or not this cookie should be relayed only to
secure servers. Calling &SetSecureCookie('1'); means that clients
will only pass those cookies you have set to secure servers.
Calling &SetSecureCookie('0'); means the cookies will be transferred
whenever the path and domain are correct, regardless of security issues.
Here is an excerpt from Netscape specs:
"If a cookie is marked secure, it will only be transmitted if the
communications channel with the host is a secure one. Currently
this means that secure cookies will only be sent to HTTPS (HTTP
over SSL) servers. If secure is not specified, a cookie is
considered safe to be sent in the clear over unsecured channels."
You can also change the value of $Secure_Cookie through a statement:
$Secure_Cookie = 1; or $Secure_Cookie = 0;
You can place this statement anywhere in your Perl programs after you
have required the cookie.lib library.
&SetCookies('cookie_name1','cookie_value1',...,'cookie_namen','cookie_valuen');
This function has been completely changed since Version 1.1.1, except
for the fact that it actually does set the cookies. There is no longer
a call to &PrepareCookies, but rather &SetCookies does it all.
If you wish to set the cookies name and email, and have the values of
these cookies in the variables $name and $email, you would set them with
the following code:
print "Content-type: text/html\n";
&SetCookies('name',"$name",'email',"$email");
print "\n";
The first line prints out the text/html header, with one new line
following it, rather than two, since the header sent to the browser is
not yet complete. Then, our call to &SetCookies is made. This call
will send two Set-Cookie: headers to the browser and set both of the
cookies for us.
You can send as many cookies to this subroutine as you wish to set.
Browsers do have a limit though, so if you are setting multiple
cookies, it is suggested that you look into the &SetCompressedCookies
subroutine.
&SetCompressedCookies('compressed_cookie_name','cookie_name1','cookie_value1',
...,'cookie_namen','cookie_valuen');
This subroutine does almost the same thing that &SetCookies does, but
instead it takes one extra argument. You call it with the name of the
compressed cookie which you wish to set and then the name/value pairs of
of the cookies which you wish to compress. This subroutine doesn't
actually compress cookies, but it takes multiple cookies and strings
them together, so to the browser they appear as one. The = signs are
converted into :: and the name/value pairs are separated from each other
by &, however there is no need to change these characters before hand,
as they will be translated back when uncompressed.
You may be saying, why should I bother compressing cookies when it takes
extra work? I can just set 50 cookies all for different things. The
main reason is, that according to Netscape's specification:
"There are limitations on the number of cookies that a client can
store at any one time. This is a specification of the minimum
number of cookies that a client should be prepared to receive and
store.
-- 300 total cookies
-- 4 kilobytes per cookie, where the name and the value combine
to form the 4 kilobyte limit.
-- 20 cookies per server or domain. (note that completely
specified hosts and domains are treated as separate entities
and have a 20 cookie limitation for each, not combined)
Servers should not expect clients to be able to exceed these
limits. When the 300 cookie limit or the 20 cookie per server
limit is exceeded, clients should delete the least recently used
cookie. When a cookie larger than 4 kilobytes is encountered the
cookie should be trimmed to fit, but the name should remain intact
as long as it is less than 4 kilobytes."
This also means that it is up to you to check and make sure that your
compressed cookie will not take more than 4KB. This is not going to be
a common problem most likely, though, as 4KB is 4,000 characters, which
if typed out on a common 80 column screen is about 50 lines, or almost
a full page of text. The 20 cookie limit on one server name is
definitely a common problem, and this helps save some of this space.
As cookies become more common, clients may start reaching the 300
cookie maximum more rapidly as well.
Let's take the example from &SetCookies above, with the name and email
cookies we wish to set. Now, rather than taking up two cookies, we
can set one cookie named user, which will contain the information
stored in the name and email cookies. To do this, make you make a call
like:
print "Content-type: text/html\n";
&SetCompressedCookies('user','name',$name,'email',$email);
print "\n";
This sets a cookie named user which contains the cookies name and email.
In order to uncompress this cookie, you need to use the
&GetCompressedCookies subroutine explained below. It acts much like
&GetCookies.
WARNING: It is a good idea not to set the compressed cookie name equal
to the name of a cookie being stored in the compressed cookie.
It can mess things up.
&GetCompressedCookies('compressed_cookie_name','cookie_name1',...,'cookie_namen');
This subroutine works in almost the same way as &GetCookies, except that
it needs the name of the compressed cookie first, followed by the names
of the cookies you wish to retrieve out of the compressed cookie. If
this subroutine is called with only the name of the compressed cookie,
it will retrieve all values and place them in the %Cookies array.
For instance, if we were to take the example used in
&SetCompressedCookies and we needed to only get the name of the user out
of the compressed cookie, we would do something like:
&GetCompressedCookies('user','name');
Where 'user' was the name of the cookie we specified to be set when we
compressed the cookies and 'name' was one of the cookies we compressed
into 'user'. The value of name can not be retrieved from
$Cookies{'name'}.
Or if you wished to get every cookie out of the compressed cookie, you
can simply say:
&GetCompressedCookies('user');
And now $Cookies{'name'} and $Cookies{'email'} are set.
##############################################################################
CHARACTER TRANSLATION INFORMATION
=================================
Version 2.1 of the HTTP Cookie Library introduces some simple character
URL-encoding which eases the use and fixes some common problems with cookies.
Previously, cookies would often not be set if they included spaces, semi-
colons, and a few other special characters. There was also the problem found
if information contained two :: or an & and you tried to compress the cookies,
because those two characters are used for the compression sequence that HTTP
Cookie Library uses.
According to Netscape's Persistent Client State HTTP Specification:
"This string is a sequence of characters excluding semi-colon, comma
and white space. If there is a need to place such data in the name
or value, some encoding method such as URL style %XX encoding is
recommended, though no encoding is defined or required."
HTTP Cookie Library does use the URL style %XX (also known as hex) encoding to
ensure that these characters are not lost and that the cookie is set.
##############################################################################
ANY EXAMPLES AVAILABLE?
=======================
ccounter.pl
-----------
ccounter.pl, an example of how to use some of the features in this
library comes bundled with the script. Hopefully the docs have been
written extensively enough and the library commented enough (this is
the most commented and well-documented script at MSA) that it should
be fairly easy to figure out.
Scripts Around the World
------------------------
You can find real-world implementations of this library listed at MSA
in the Scripts Around the World section. The HTTP Cookie Library page
for this can be found at:
http://www.worldwidemart.com/scripts/examples/cookielib.shtml
If you have used the library, please let us know so we can add it!
##############################################################################
OTHER COOKIE RESOURCES
======================
There are many other cookie resources available on the Internet. Below are
just a few that are the most useful and should help you out. Enjoy.
Netscape Persistent Client State HTTP Cookies Specification
http://www.netscape.com/newsref/std/cookie_spec.html
The specifications to which this library conforms. Contains a lot of
useful information on Cookies in general and how they can be used.
Andy's Netscape HTTP Cookie Info
http://www.illuminatus.com/cookie.fcgi
A lot of information on cookies, the security of them, Frequently Asked
Questions and much more. A LOT of cookie information. :-)
Malcolm's Guide to Persistent Cookies
http://www.emf.net/~mal/cookiesinfo.html
This guide to Persistant Cookies explains what cookies are, discusses
security and privacy issues, gives URLS to more documentation and shows
some examples of places using cookies.
Javascript Cookie Functions
http://www.hidaho.com/cookies/cookie.txt
A library much like this one with different subroutines, only
implemented in JavaScript.
HTTP State Management Mechanism RFC
http://portal.research.bell-labs.com/~dmk/cookie-2.36.txt
Looks very cookie-related. Maybe I should start conforming to this.
##############################################################################
HISTORY
Version 2.1 - 12/19/96 - Changed the local() scope of global
variables because they weren't setting at
the top of the script right.
- 12/20/96 - Added URL-encoding to the cookies for the
characters: '%', '+', ':', ',', '=', '&',
'::', and space. More on this explained
in the section, 'Character Translation'.
- &UnCompressCookies changed to
&GetCompressedCookies, making more sense.
- 12/23/96 - &SetCookieExpDate fixed to allow a blank
date.
Version 2.0 - 11/28/96 - &SetCookieExpDate still not working right,
and finall fixed.
- &SetCompressedCookies and &UnCompressCookies
subroutines added so multiple cookies can be
set as one cookie and take up less room in
the cookies.txt file.
- &PrepareCookie replaced by changing
&SetCookies to do all of the work. This
subroutine now actually takes values and
sets them.
- Multiple cookied can be set now. A bug
existed before which wouldn't set all of
the cookies.
- Checking now done when setting cookie domain
so you can know ifies. To ss very seren't seRe oh
###Tcookil+o &SetCoop t,
u