homepage Welcome to WebmasterWorld Guest from 54.227.89.236
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Pubcon Platinum Sponsor 2014
Visit PubCon.com
Home / Forums Index / Code, Content, and Presentation / Perl Server Side CGI Scripting
Forum Library, Charter, Moderators: coopster & jatar k & phranque

Perl Server Side CGI Scripting Forum

    
Getting results from Javascript back to Perl
For implementing cookie
nelmo




msg:4395574
 3:37 pm on Dec 8, 2011 (gmt 0)

Ok, newbie (to forum and PERL), so be kind...

I've got an app written in Perl that I want to use a cookie in. I've got lots of examples of cookie functions in JS but I'm confused about how to get data back from the JS function to the PERL script.

So I have this:

function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}

return null;


In my Perl script, do I just need to have:


print <<TheEnd

<script ....

rtn=readCookie("Fred");

TheEnd

print "Cookie is: $rtn";



Apologies for syntax etc, just want to get basic idea - will 'rtn' be visible to my Perl script?

 

Brett_Tabke




msg:4395582
 4:05 pm on Dec 8, 2011 (gmt 0)

Lets make sure we are on the same page.
  • JS is a browserside language. It runs in the browser only.
  • Perl is a server side lanaugage and runs only on the server.

JS can set and read cookies.
The only time those cookies are sent to the server is via a request as part of the HTTP header. Most often, that request is going to be a result of a pageview or downloading a graphic.

Somehow we have to get that cookie back to the perl program to work on. Most times, that is going to be directly calling that Perl program. Then the perl program can look at the server headers where the cookie data resides, and then do something with it.

So, the challenge is getting it into Perl - 3 options to pass the data to Perl via a HTTP header:
  1. a page view. You directly call the perl script.
  2. AJAX. quietly call your perl script from AJAX formated code to send the cookie.
  3. a transparent image graphic pull that actually calls the perl script.

How you go about each of those is a bit different.

I would say you first homework, is to study perl enough to figure out how to get the cookie from the http headers. Then move on to figuring out how you are going to get the cookie from the browser.

rocknbil




msg:4395599
 4:28 pm on Dec 8, 2011 (gmt 0)

Why don't you just set and read the cookie in Perl?

At any rate, if the cookie is set, even in Javascript, it's set **in the browser.** It shouldn't matter, as long as it's on the same domain. On the next page* after the cookie is set, you should be able to do something like

# note that fred and Fred are not the same
my $cookievalue = &readCookie('Fred');
if ($cookievalue ne '') { print "cookie value is $cookievalue"; }
else { print "cookie not found, try reloading this page.*"; }

sub readCookie {
my ($cname,@cookiegroups,$grp,$cookkey,$cookval);
$cname = shift(@_);
if ($ENV{'HTTP_COOKIE'}) {
$ENV{'HTTP_COOKIE'} =~ s/\s+//g;
(@cookiegroups) = split(/;/,$ENV{'HTTP_COOKIE'});
foreach $grp (@cookiegroups) {
($cookkey,$cookval) = split (/=/,$grp);
if ($cookkey eq $cname){ return $cookval; }
}
}
return ''; # means no matching cookie found
}


* Note that, as Mr. Tabke says, you set a cookie and it can't be "read" until the browser sends it's value back to the server - usually on the next pageview.

nelmo




msg:4395600
 4:31 pm on Dec 8, 2011 (gmt 0)

Thanks for the reply and good advice - however, I'm a support bloke in a big company who's been dumped on from above to write this app to fit in with an existing suite of webapps. Sadly, I don't have the time to go on a Perl course.

I wrote this app in Perl because that's what the others were written in and I have limited options as to what I can change and use (I doubt AJAX, whatever it is, is installed on our web servers).

I have a set of JS functions to manage cookies (read, erase, create) and I don't want to have to re-write my app in JS, which I guess is an option but will take a week.

I've tried a test program using my example in my first post and I'm not getting 'rtn' back to my Perl script (thought that would be too easy :-) ).

Any other suggestions?

nelmo




msg:4395603
 4:34 pm on Dec 8, 2011 (gmt 0)

Ah, sorry, Rocknbil, only saw your response after I typed mine...

OK, that looks a good option - many thanks, I'll give it a go...

EDIT: I'm fairly sure I've tried something similar to that already and the problem was that the environment variable is on the server side (if in Perl), no?

Which means I would have to differentiate the cookies for each user, which then brings up the problem of identifying the user from the browser without the user telling you directly.

Or is that total rubbish?

phranque




msg:4395818
 1:07 am on Dec 9, 2011 (gmt 0)

welcome to WebmasterWorld, nelmo!

if you need to uniquely identify a visitor so that you can maintain state throughout a session then you will have to assign a unique identity to the visitor through the cookie name or value.

rocknbil




msg:4396092
 6:10 pm on Dec 9, 2011 (gmt 0)

Not sure what you mean, but below is an example that works for you to grok the concepts. Name it "cookie-with-js.cgi" (or rename the link, otherwise the link won't work), upload it to your cgi-bin and set permissions to 755.

If you have any other cookies set for this domain (like analytics, etc) it will give you some unexpected results on the second page but you should still see "Cookie name is Fred, value is Wilma" on the second page. You're supposed to "cycle through" (loop) the cookies set for the domain and pull their values by the key name - this just sets and reads one cookie.

#!/usr/bin/perl
%qs=&readParse;
print "Content-type:text/html\n\n";
print qq|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Set with JS, read with Perl</title>
<script type="text/javascript">
function setCookie() {
document.cookie = 'Fred=Wilma';
document.getElementById('open-me').style.display='block';
return false;
}
</script>
</head>
<body>
|;
if ($qs{'readit'}) {
$cdata = $ENV{'HTTP_COOKIE'};
($name,$value) = split(/=/,$cdata);
print "Cookie name is $name, value is $value";
}
else {
print qq|
<p><a href="#" onclick="return setCookie();">click here to set the cookie</a></p>
<p id="open-me" style="display:none;">
<a href="cookie-with-js.cgi?readit=1">Cookie set. Click to read it with Perl</a>
<p>
|;
}
print '</body></html>';
## just meant for this script
sub readParse {
my (%query_hash,$query_string,$_qsname,$_qsvalue,$pair);
$query_string = $ENV{'QUERY_STRING'};
foreach $pair (split(/&/, $query_string)) {
($_qsname, $_qsvalue) = split(/=/, $pair);
$_qsname =~ s/[\+]/ /g;
$_qsname =~ s/%([\da-f]{2})/pack("C",hex($1))/ieg;
$_qsvalue =~ s/[\+]/ /g;
$_qsvalue =~ s/%([\da-f]{2})/pack("C",hex($1))/ieg;
$query_hash{$_qsname} = $_qsvalue;
}
return %query_hash;
}

nelmo




msg:4397052
 2:26 pm on Dec 12, 2011 (gmt 0)

Thanks Rocknbil, that works well...

Am I right in saying that, basically, the JS 'document.cookie' method is setting the HTTP_COOKIE environment variable for that Perl session?

nelmo




msg:4397067
 3:36 pm on Dec 12, 2011 (gmt 0)

OK, played around and, basically, you've got the HTTP_COOKIE environment variable set (as long as you also add an expiry date) to read from. Your example works because it takes the first cookie off the variable which I guess works because you've just created it so it's tagged on to the front.

Hallelujiah - I've spent a week on various different forums trying to get to this point - thanks Rocknbil...;-)

rocknbil




msg:4397124
 5:14 pm on Dec 12, 2011 (gmt 0)

you've got the HTTP_COOKIE environment variable set (as long as you also add an expiry date) to read from. Your example works because it takes the first cookie off the variable which I guess works because you've just created it so it's tagged on to the front.


Just to clarify, these are not exactly true. :-) when you set a cookie - doesn't matter where you set it, from a server side script or from the browser - it is set in the browser itself. It's the browser that sends that cookie information to the server. This is why you can't "read" it until the second page view after setting it.

As for the expiration date - there are two basic types of cookies, a session cookie and a persistent cookie. A session cookie is set, but since it has no valid expiration date, remains until the browser is closed. The above works not because of any tagging, but because it's set and the very next page view reads it. But yes - because it's the last cookie set, it's at the "top of the list." This is why you may or may not see other data added to "Wilma;...."

page 1: set cookie
page 2: browser SENDS the cookie value to the server and we can read it.

A persistent cookie is one with a valid expiration date and when you close the browser, it "lives" until the expiration date. This is a pretty big difference - when you set a persistent cookie in FireFox, you can go to Options and actually see the cookie, which I don't think you can with session cookies - they are still there though.

Like I said that was just for the JS/Perl puzzle, in actual use you'd always want to loop through cookies to access all keys and values, like


$cdata = $ENV{'HTTP_COOKIE'};
@pairs = split(/;/,$cdata);
foreach $pair (@pairs) {
($name,$value) = split(/=/,$pair);
print "Cookie name is $name, value is $value<br>";
}


There's more to it in practical applications, like cleansing data, etc., but that's the gist.

oops: was thinking PHP there for a sec

nelmo




msg:4397366
 11:27 am on Dec 13, 2011 (gmt 0)

I changed your code to display HTTP_COOKIE before setting the cookie, shutdown the browser window, restarted and I still see the cookie in there. I do have a seperate browser window also open - is that what is still holding the env variable?

I will be using a persistent cookie and expect to read it at the start of my app, so are you saying that when I start a clean session, HTTP_COOKIE will NOT be available?

mark_roach




msg:4397377
 12:12 pm on Dec 13, 2011 (gmt 0)

A session cookie will be kept until all instances of the browser are closed which explains why you are still seeing the cookie values.

If you use a persistant cookie it will be available across browser sessions so yes you will be able to read it (assuming it has not expired) when you start up a clean browser session, after a re-boot for example.

Note to use a persistant session you need to set and expires value when you create the cookie. Your initial code does not do this.

rocknbil




msg:4397475
 4:51 pm on Dec 13, 2011 (gmt 0)

^^ Right, and

is that what is still holding the env variable?


No . . .the browser it holding the cookie. :-) Environment variables are on the server, and an http_cookie envar is only present if the browser sends it to the server. Even if it's a persistent cookie, it still doesn't live on the server, it's in your browser (well, actually, stored in some file the browser uses.)

A thing about persistent cookies that it took me a long time to get right is the expiration date has to be in the correct format otherwise they won't "stick."

nelmo




msg:4397479
 5:04 pm on Dec 13, 2011 (gmt 0)

OK, so what actually does the sending? Just reloading the form/page? Part of QUERY_STRING?

So, if I have a persistent cookie and just load the page, it will have HTTP_COOKIE (with my cookie in it), without any call to, say, 'document.cookie'?

phranque




msg:4397614
 12:57 am on Dec 14, 2011 (gmt 0)

the user agent (browser) sends with each HTTP request all cookies it has stored that are within the scope of the requested resource.
the cookies are sent as HTTP Request headers.

the server may send a number of Set-Cookie HTTP Response headers as required by the application.
the user-agent may store or ignore these cookies.

you should probably read the IETF RFC on HTTP State Management Mechanism:
http://tools.ietf.org/html/rfc6265 [tools.ietf.org]

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / Perl Server Side CGI Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved