Forum Moderators: coopster & phranque

Message Too Old, No Replies

SSI and Cookies

         

helle2005

10:42 am on Aug 13, 2005 (gmt 0)

10+ Year Member



Hi, I have some problems to start a perl script from SSI and read and write Cookies from this perl script. Read and write Cookies works fine, when I start the perl script directly in the browser. I assume the problem is in the way the object CGI works. I use "use CGI" and print $cgi->header(-cookie=>$neuCookie); in my script. I asume that $cgi->header write additional information back to the browser, which is not needed in SSI. So my question is, is there any way to read and write Cookies without using "$cgi->header(-cookie=>$neuCookie);". I am pretty sure there is, but I found no documentation. Please let me know, when you have some docs for me. Thanks.

KevinADC

7:49 pm on Aug 13, 2005 (gmt 0)

10+ Year Member



what's the problem you are having? Are you seeing the cookie data printed to the browser?

WWMike

1:43 am on Aug 14, 2005 (gmt 0)

10+ Year Member



Here's a way to read and write cookies manually. I wrote it to do something specific but it should have the pieces you need. Upload it, run it and refresh the page every few seconds to see what it does then just look thru it and rip out the stuff you don't need or snatch out the cookie subroutines and merge them with your script:

#!/usr/bin/perl

######################################################
# The following cookie driver will check for the expiration of a cookie.
# If the cookie does not exist or has expired it will perform the code
# in the Cookie_Accepted subroutine and if the cookie has not yet
# expired it will perform the code in the Cookie_Rejected subroutine.
######################################################

######################################################
# Set $Seconds to the number of seconds until the cookie expires.
# Set $Seconds to 0 to remove the cookie.
#
# 1 minute = 1 * 60 = 60 seconds
# 1 hour = 1 * 60 * 60 = 3600 seconds
# 1 day = 1 * 60 * 60 * 24 = 86400 seconds
# 1 week = 1 * 60 * 60 * 24 * 7 = 604800 seconds
# 1 month = 1 * 60 * 60 * 24 * 30 = 2592000 seconds
# 1 year = 1 * 60 * 60 * 24 * 352 = 30412800 seconds
######################################################

$Seconds = 30;

######################################################
# Set $Cookie_Name to a unique name to identify this cookie.
######################################################

$Cookie_Name = "$ENV{SCRIPT_NAME}"; # unix script pathname

######################################################
# Pre-processing.
######################################################

# Insert any optional & additional initialization here.
# Initialize variables, parse forms, perform calculations, etc.

######################################################
# Check cookie.
######################################################

&Check_Cookie;

######################################################
# Post-processing.
######################################################

# Insert any optional & additional finalization here.
# Send emails, delete temporary files, spawn process, etc.

######################################################
# Done.
######################################################

exit;

######################################################
# Get, check, set, or remove cookie and display current status.
######################################################

sub Check_Cookie {
if ( $Seconds eq 0 ) {
$cookie=&Remove_Cookie( $Cookie_Name );
print "$cookie\n";
&Cookie_Status('REMOVED', "Expires in $Seconds seconds");
} else {
$Cookie_Value = &Get_Cookie( $Cookie_Name );
if ( $Cookie_Value > time ) {
&Cookie_Rejected;
} else {
$cookie = &Set_Cookie( $Cookie_Name, time + $Seconds, $Seconds );
print "$cookie\n";
&Cookie_Accepted;
}
}
}

######################################################
# Takes (name,value,hours) as arguments to set a cookie.
# 0 hours means a current browser session cookie life.
######################################################

sub Set_Cookie {
my ( $name, $value, $expires ) = @_;
$name = &Cookie_Scrub( $name );
$value = &Cookie_Scrub( $value );

# $expires=$expires * 60;
# $expires=int($expires);

my $expire_at = &Cookie_Date( $expires );
my $namevalue = "$name=$value";

my $COOKIE = "";

if ( $expires!= 0 ) {
$COOKIE = "Set-Cookie: $namevalue; expires=$expire_at; ";
}
else {
$COOKIE = "Set-Cookie: $namevalue; "; #current session cookie if 0
}
return $COOKIE;
}

######################################################
# This routine removes cookie of (name) by setting the expiration to a
# date/time GMT of (now - 24hours)
######################################################

sub Remove_Cookie {
my ( $name ) = @_;
$name = &Cookie_Scrub( $name );
my $value = "";
my $cookie = "";
my $expires = &Cookie_Date( -86400 );
my $namevalue = "$name=$value";
my $COOKIE = "Set-Cookie: $namevalue; expires=$expires; ";
return $COOKIE;
}

######################################################
# given a cookie name, this routine returns the value component of the
# name=value pair. A returned value of 0 means no cookie.
######################################################

sub Get_Cookie {
my ( $name ) = @_;
$name = &Cookie_Scrub( $name );
my $temp = $ENV{'HTTP_COOKIE'};
@pairs = split(/\; /,$temp);
foreach my $sets ( @pairs ) {
my ( $key, $value ) = split( /=/, $sets );
$clist{$key} = $value;
}
if ( $clist{$name} eq "" ) { $clist{$name}="0"; }
my $retval = $clist{$name};
return $retval;
}

######################################################
# Number of seconds added to the server time to calculate expiration.
# Cookie time is ALWAYS GMT.
######################################################

sub Cookie_Date {
my ( $seconds ) = @_;
my %mn = ( 'Jan','01', 'Feb','02', 'Mar','03', 'Apr','04', 'May','05', 'Jun','06', 'Jul','07', 'Aug','08', 'Sep','09', 'Oct','10', 'Nov','11', 'Dec','12' );
my $sydate = gmtime( time+$seconds );
my ( $day, $month, $num, $time, $year ) = split( /\s+/, $sydate );
my $zl = length( $num );
if ( $zl == 1 ) {
$num = "0$num";
}
my $retdate = "$day $num-$month-$year $time GMT";
return $retdate;
}

######################################################
# Don't allow = or ; as valid elements of name or data
######################################################

sub Cookie_Scrub {
my ( $retval ) = @_;
$retval=~s/\;//g;
$retval=~s/\=//g;
return $retval;
}

######################################################
# Display Cookie Status Message
######################################################

sub Cookie_Status {
my ( $action, $detail ) = @_;
print "Content-type: text/html\n\n";
print <<__END_MESSAGE__;
<H2 ALIGN=Center>$Cookie_Name COOKIE $action</H2>
<H3 ALIGN=Center>$detail</H3>
__END_MESSAGE__
}

######################################################
# Stop. Cookie has not yet expired.
######################################################

sub Cookie_Rejected {
&Cookie_Status('REJECTED', ( $Cookie_Value - time ) . " of $Seconds seconds remaining");
}

######################################################
# OK to continue processing.
######################################################

sub Cookie_Accepted {
&Cookie_Status('ACCEPTED', "Expires in $Seconds seconds");
}

helle2005

11:45 am on Aug 14, 2005 (gmt 0)

10+ Year Member



I got the same problem, with your script/functions. The script is working fine, when you start it directly in the browser, but it cause problems when you start it in SSI. I can read cookies, but for some reason it isn't writen back the cookies to the users browser. Here is what I try to do: START perlscript from SSI in index.shtml <!--#include virtual="/cgi-bin/counter/counter.pl?countername=index&display=counter"--> this is working fine. In Counter.pl I would like to check, if the user was in the last xx minutes already on the page. I thought the easiest way is to create a cookie. The Counter.pl I try to read and write back a cookie with a.)
# === Cookie ====================================================================

# === read Cookie ===============================================================

my $temp = $ENV{'HTTP_COOKIE'};

# === update Cookie ===============================================================

my ( $name, $value, $expires ) = @_;
$name = "last_visit";
$value = "XXX";
my $COOKIE = "Set-Cookie: $name=$value; expires=+3M; ";
print "$COOKIE\n";

or b.)

use CGI;
my $cgi = new CGI;
use CGI::Carp qw(fatalsToBrowser);

my $CTIME_String = localtime(time);
my $altCookie = $cgi->cookie(-name=>'letzter_Besuch');
my $neuCookie = $cgi->cookie(-name=>'letzter_Besuch',
-value=>$CTIME_String,
-expires=>'+3M',
-path=>'/');

print $cgi->header(-cookie=>$neuCookie);

both methods are not writing back the Cookie from SSI. Any ideas?
Or maybe the is a other method to do it. Everything is welcome.

WWMike

1:19 pm on Aug 14, 2005 (gmt 0)

10+ Year Member



I tried calling my script from an SSI in both the BODY and HEAD sections and noticed that the cookie could not be set but could be read if I pre-set it manually.

Then I realized that there is probably no way for Apache to set a cookie based on SSI because by that time, the header has already been sent.

Then I searched for "cookie SSI" and found someone else that had the same problem:

[archive.apache.org...]

Here's one possible solution:

<META HTTP-EQUIV="Set-Cookie" CONTENT="$newcookie">

Here's how to read a cookie with SSI:

<!--#cookie get="cookie-name" alt="alt" -->
<!--#cookie if="cookie-name" then="then" alt="alt" -->

And here's another way:

<!--#if expr="$HTTP_COOKIE" -->
<FONT SIZE="4">You have a cookie set: </FONT><!--#echo var="HTTP_COOKIE" -->
<!--#elif -->
<FONT SIZE="4">You are cookieless!</FONT>
<!--#endif -->

It appears that if you absolutely need to set the cookie with PERL you'll need to call the script directly so that it can generate the cookie header.

If that's the case and you don't want to link directly to the cgi you might try calling a script from SSI that writes a new page and then does print "Location: [mydomain.com...]

Good luck!

volatilegx

5:57 pm on Aug 15, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You're right that a server-side script must set the cookie before the headers are finished. I've never done it in perl, but in PHP, the solution is simple:

<?php
# code to set cookie here
$value = 'something from somewhere';
setcookie("TestCookie", $value);
?>
HTML CODE HERE

Note that the <?php would be on the first line of the file. The PHP interpreter doesn't send the mime type header (the last header) until you begin outputing HTML code, meaning that you can set headers, cookies, etc. at the beginning of the file.

All that being said, you could try doing something similar with perl. Maybe if your SSI was at the first line of the page it might work.