I have a script that processes user sign in/out request.
One of a few things this script has to do is remove/set appropriate
cookies to control user sessions. The problem that I've encountered
with the script was that while setting a cookie works 100% of the time,
removing a cookie is sometimes problematic.
In order to investigate this problem, I've written a simple cookie manipulation
test script. It would display a form with a single submit button, which
function is to either 'Remove Cookie' or 'Set Cookie'.
The code for this test page is included at the end of this post.
To remove a cookie, I simply create one using CGI's cookie() method and passing it appropriate
cookie parameters/values. Finally, I invoke CGI::redirect to create
a redirect header containing cookie string (I redirect to the page itself).
Having played with the test script a few times (on Mozilla 5.0 rv:0.9.7) I have made
a somewhat 'chilly' discovery. Setting -expires option of an existing cookie to 'now' (which will
get translated to time() right?) wouldn't remove it immediately.
And, I end up having to retry a few times (by hitting the 'Remove Cookie' button) in order
to actually make the cookie go. However, setting the -expires option to 1, makes things work the first time.
I also noticed that the 'now' value wouldn't remove my cookie on IE5.0 browsers at all ;/,
no matter how many times you try.
Frankly, I'm buffled by this problem. I looked at redirect header data produced
in two cases, and they don't seem to be all that different (unless I missed something ;-),
except for expire times. However, now did produce 'current' expire time.. which had to
work, logically.
Any idea why, contrary to perldoc CGI documentation, setting -expires to 'now' wouldn't work?
Actually, I've learnt that -value property has to be set to a 'non-false' value (neither 0 nor
undef is allowed), otherwise, cookie wouldn't get removed either.
Thanks.
Here goes the source code for cookie_test.cgi
use strict;
use lib qw(.);
use CGI;
use CGI::Cookie;
my $cgi = new CGI;
my $op = $cgi->param('op');
$main::cookie_name = $cgi->param('cookie_name');
$main::full_url = $ENV{SERVER_URL} . $ENV{SCRIPT_NAME};
$main::domain = $cgi->param('domain');
$main::path = $cgi->param('path');
$main::cookie_value = $cgi->param('cookie_value');
$main::domain ||= '.mybc.com';
$main::path ||= '/';
$main::cookie_value ||= 'na';
#$main::domain = $ENV{HTTP_HOST};
#($main::path) = ($ENV{SCRIPT_NAME} =~ m|(.*)/[^/]+$|);
$main::cookie = $cgi->cookie($main::cookie_name);
#$op='rm';$main::cookie=1;
set_cookie($cgi) if ($op eq 'set');
remove_cookie($cgi) if ($op eq 'rm');
%main::cookies = fetch CGI::Cookie;
my ($html_cookie_table, $html_cookie_select);
parse_all_cookies({
html_table => \$html_cookie_table,
html_select => \$html_cookie_select,
});
print $cgi->header();
print qq|
<html>
<title>Cookie Test</title>
<body>
<pre>
Cookie set/remove test.
<form method=POST>
<input type=hidden name=op value="$op">
<table border=0>
<tr>
<td></td><td></td>
</tr>
<tr>
<td align=left>Name:</td>
<td align=left nowrap>
<input name=cookie_name value="$main::cookie_name">
<script>
function select_cookie(sel_obj)
{
if (sel_obj.selectedIndex) {
sel_obj.form.cookie_name.value = sel_obj.options[sel_obj.s
+electedIndex].value;
} else {
sel_obj.form.cookie_name.value = "";
}
}
</script>
<select name=cookie_name_select onChange="select_cookie(this);">
<option value=0>Select existing ...</option>
$html_cookie_select
</select>
</td>
</tr>
<tr>
<td>Value:</td><td><input name=cookie_value value="$main::cookie_valu
+e"></td>
</tr>
<tr>
<td align=left>Domain:</td><td align=left><input name=domain value="$
+main::domain"></td>
</tr>
<tr>
<td align=left>Path:</td><td align=left> <input name=path value="$mai
+n::path"></td>
</tr>
<tr><td colspan=2 align=center>
<input type=button value="Remove Cookie" onclick="this.form.op.value
+= 'rm';this.form.submit();">
<input type=button value="Set Cookie" onclick="this.form.op.value = '
+set';this.form.submit();">
<input type=submit value="Refresh" onclick="this.form.op.value = '';"
+>
</td></tr>
</table>
</form>
</pre>
<hr>
$html_cookie_table
</body>
</html>
|;
exit;
##
## SUBS
##
sub set_cookie {
my $cgi = shift;
unless ($main::cookie) {
$main::cookie = $cgi->cookie(
-name => $main::cookie_name,
-value => $main::cookie_value,
-expires=> '+1h',
-path => $main::path,
-domain => $main::domain,
);
print CGI::redirect(-location => $main::full_url, -cookie => [$mai
+n::cookie]);
exit;
}
}
sub remove_cookie {
my $cgi = shift;
$DB::single = 1;
if ($main::cookie) {
my $cookie = $cgi->cookie(
-name => $main::cookie_name,
-value => 1, # also this one can't be 0
+ or undef!
# Setting expires to 'now' doesn't quite
+ work.
# I have to hit the 'Remove Cookie' butt
+on
# 2/3 times (# of remove attempts) to ac
+tually
# remove the cookie.
# -expires => 'now',
# however, this works well all the time.
# what's the trick?
-expires=> 1,
-path => $main::path,
-domain => $main::domain,
);
# print $cgi->header();
# print qq|
# <pre>
# REMOVING COOKIE:
# -name => $main::cookie_name,
# -value => 'foobar',
# -expires=> 'now',
# -path => $main::path,
# -domain => $main::domain,
# </pre>
# |;
print CGI::redirect(-location => $main::full_url, -cookie => [$coo
+kie]);
exit;
}
}
sub parse_all_cookies {
my ($r_html_table, $r_html_select) = @{$_[0]}{qw(html_table html_s
+elect)};
$$r_html_table = qq|
<table border=0 cellpadding=2 cellspacing=3 bgcolor=lightg
+rey>
<tr><td><b>Cookie Name</b></td><td><b>Content</b></td></tr
+>
|;
foreach (keys %main::cookies) {
$$r_html_select .= "<option value='$_'>$_</option>";
$$r_html_table .= "<tr><td>$_</td><td>".$main::cookies{$_}."</
+td></tr>";
}
$$r_html_table .= "</table>";
}
|
"There is no system but GNU, and Linux is one of its kernels." -- Confession of Faith
|
Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
Read Where should I post X? if you're not absolutely sure you're posting in the right place.
Please read these before you post! —
Posts may use any of the Perl Monks Approved HTML tags:
- a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
| |
For: |
|
Use: |
| & | | & |
| < | | < |
| > | | > |
| [ | | [ |
| ] | | ] |
Link using PerlMonks shortcuts! What shortcuts can I use for linking?
See Writeup Formatting Tips and other pages linked from there for more info.