FeraliX has asked for the wisdom of the Perl Monks concerning the following question:

Is there anyway to send a basic perl cookie without using modules? I haven't been able to find a tutorial for one. Thanks in advance.

2006-05-01 Retitled by g0n, as per Monastery guidelines
Original title: 'Cookies'

Replies are listed 'Best First'.
Re: Sending cookies without module
by dynamo (Chaplain) on May 01, 2006 at 04:56 UTC
    Sure.

    First off, I need to mention that I'm assuming that you mean you want to send an HTTP cookie, you're using Apache as your web server, and you are writing a CGI script (as opposed to using mod_perl, which would require modules to work).

    Second, you should consider using a module, or at least using some code from inside of them, just to avoid typo trouble. At least, write a function to send the cookie and get it tested before you use it much.

    Having said that, all you have to do is decide on what your cookie will say (key and value), and in the CGI script, before the "Content-type: text/html\n" line, you will want to print a "Set-Cookie: $Key=$Value\n".

    I was able to find an example here.

    Have fun!

Re: Sending cookies without module
by jZed (Prior) on May 01, 2006 at 04:54 UTC
    Just look at the code for CGI, that will show you how. But it would be a lot easier to just use that module instead of reading it and recreating it. Is there a reason for your "without using modules" caveat?
Re: Sending cookies without module
by Zaxo (Archbishop) on May 01, 2006 at 04:58 UTC
    . . . without using modules?

    Why? If you want deep understanding of cookies, that's ok, but Perl without CPAN modules? That's like C without libc.

    After Compline,
    Zaxo

      Yes, I've figured out I kinda have to use modules, which is ok, but I've encountered another problem. Im attempting a very simple login screen, It's all written and works, It just doesn't remember that they are logged in. I have a login form that on submit reloads the page and loads a subroutine to check if the username/password are correct. I've tried putting the following code in if the login data is correct, but it just prints it to the screen, I've tried several other ways but can't get it to print the cookie. I hope this makes sense :P
      my $c = new CGI::Cookie(-name=>'Something'); print "Set-Cookie: LOGGEDIN=$c\n";
        There are two sections to what you are sending back to the HTTP server. First, you (or the module you use) need to print a list of header data (ex line: "Content-Type: text/html\n"). Then you want to send a blank line, then your content.

        However, if it's printing your headers to the screen, your problem is apparently that your code (/module) has already sent the HTTP headers section _and_the_blank_line_ when it gets to the code above.

        So you can either stop using the module:

        #/usr/bin/perl print <<END Content-Type: text/html Set-Cookie: this=that <html> html content here </html> END
        or you can tell CGI::Cookie to go ahead and send that header after creating the CGI::Cookie object (see the docs for CGI::Cookie):
        use CGI qw/:standard/; use CGI::Cookie; # Create new cookies and send them $cookie1 = new CGI::Cookie(-name=>'ID',-value=>123456); $cookie2 = new CGI::Cookie(-name=>'preferences', -value=>{ font => Helvetica, size => 12 } ); print header(-cookie=>[$cookie1,$cookie2]);
        I didn't use your code in this last example because I'm not sure if you are trying to print the header stuff before all the content, and that's necessary. So make sure this is at the beginning. Then, in CGI::Cookie parlance, you need to bake the cookie:
        my $c = new CGI::Cookie(-name=>'Something'); $c->bake;
        There are many was to write this, check the docs from the link here for more info.
        Im attempting a very simple login screen, It's all written and works, It just doesn't remember that they are logged in. I have a login form that on submit reloads the page and loads a subroutine to check if the username/password are correct.

        Right, there are a couple of number of ways to handle the details, but it boils down to this: you have to remember somewhere not only that the user is logged in, but _who_ they're logged in as. If you put this information in a cookie, and then _trust_ the cookie, anyone will be able to fake being logged in as any user, just by creating a fake cookie (which is easy to do with most browsers), so you don't want to do it that way. You could cryptographically sign the cookie, but that starts to get complicated, and you'd have to verify the signature on every page load. You could put the password into the cookie, but then the password gets passed, in cleartext, with each and every page load, which is not ideal. So the best solution is to store the session information on the _server_ someplace, and just put a unique session-ID number in the cookie that can be used to look up the session information (such as which user is logged in).

        I usually store the session info in a database, but if you aren't prepared to set up a database you could store it in flat files easily enough, and use the session-ID number as the filename. Then to verify that the user is logged in, you take the session ID number from the cookie that the browser sends you, and you open that file and read the session information (such as the logged-in username) out of it.

        To create the cookie, you can just do something like this:

        # Create a random session ID number: my $sessionid = join "", map { int rand 100 } 1..20; # Send the session id to the browser: print "Content-type: text/html\nSet-Cookie: session=$sessionid\n\n" +; # And remember on the server which session that is: storesessioninfo($sessionid, $username, %other_session_info);

        However, any script that wants to "remember" later whether the user is logged in or not will need to check the cookie:

        if ($ENV{HTTP_COOKIE} =~ /sessionid=(\w+)/) { # Call the routine that reads the server-side session info: ($username, %other_session_info) = getsessioninfo($1); }

        Once you get it working, you can decide how long you want to keep the things before expiring them, and create a cron job to clean up the old leftover ones.

        The storesessioninfo and getsessioninfo routines just need to store and retrieve (respectively) the session information, either in the filesystem, or a database, or in some other way.


        Sanity? Oh, yeah, I've got all kinds of sanity. In fact, I've developed whole new kinds of sanity. Why, I've got so much sanity it's driving me crazy.