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

I have created a cookie using CGI:Cookie.

I want to create more than one cookie and am succesfully using the following line of code:

print $query->header(-cookie=>[$cookie1, $cookie2]);

-- The problem is that i am writing all instances of a hash to a cookie and want so want to write the print header query at the end of each $key loop. eg.

$cookie = 1; my $key; foreach $key (keys %$inputs) { $cookie = new CGI::Cookie(-name=>'ID',-value=>$key, -expires=>$inputs->{$key}, -path=>'/', -domain=>'', -secure=>0); $cookie++; print $query->header(-cookie=>[$cookie]); }


THis does not seem to work and only prints out the last instance of the loop to the cookie.

Can anyone help THanks Costas

Replies are listed 'Best First'.
Re: CGI::cookie query
by suaveant (Parson) on Apr 02, 2001 at 19:25 UTC
    Something you may want to think about... there is a limit to something like 20 cookies per site in browsers, after that they delete them. Each cookie can be like, 1 or 4k not sure which, you may just want to encode your hash into a single string and write it into a single cookie.

    something like:

    $cookie = join "\0", %hash; $cookie =~ s/(\W)/'%'.sprintf("%02lx",ord($1))/ge; #... print cookie ... #read cookie back to hash... $cookie =~ s/%([a-fA-F\d][a-fA-F\d])/chr(hex($1))/ge; %hash = split "\0", $cookie;
    as long as you don't have a really large hash, or one that contains \0 in it, that oughtta work fine and solve your problem
                    - Ant
Re: CGI::cookie query
by wardk (Deacon) on Apr 02, 2001 at 20:12 UTC

    Appears you are looking for a solution like this (from the CGI::Cookie perldoc)

    Within a CGI script you can send a cookie to the browser by creating one or more Set-Cookie: fields in the HTTP header. Here is a typical sequence: my $c = new CGI::Cookie(-name => 'foo', -value => ['bar','baz'], -expires => '+3M'); print "Set-Cookie: $c\n"; print "Content-Type: text/html\n\n"; To send more than one cookie, create several Set-Cookie: fields. Alternatively, you may concatenate the cookies together with "; " and send them in one field.

    Just do the Set-Cookie in your loop and the header after...

      The problem is is that the cookie values must not be concatenated, they have to be sent as seperate cookies (project rules). ..I also have to use the CGI::cookie module (hence no use of set-cookie)
Re: CGI::cookie query
by Masem (Monsignor) on Apr 02, 2001 at 20:37 UTC
    Another way that isn't mentioned already: You can only send the CGI header *once*, so that call to header() will be weird. But all you need to do is create an array of cookies and then call header once after the loop; eg replace that last line of the loop with push @cookies, $cookie;, then call print $query->header(-cookie=>@cookies); (note: untested, may have to use a reference to @cookies).

    But as other have send, there's a practical limit to cookies. It's better to only send one piece of data across and use a server at your end to extract all the data that you are trying to send now. So you'd create a unique key, write to some database all the info you're trying to save, then send off the cookie with just that key value. Upon getting back that key value by a cookie, it's a lot easier to get that data.


    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
      THis seems like the best idea!!! I have tried it however with no success. What did you actually mean by 'may have to use a reference to @cookies' Does anybody know if it is possible to writea cookie with an array $query->header(-cookie=>@cookies);
        Use $query->header( -cookie=> \@cookies ); (note the '\', that makes the call use a reference to @cookies as opposed to the variable @cookies itself), instead of what I had initially. Again, it's untested, so it might not work, though I doubt that it won't work this way.
        Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
Re: CGI::cookie query
by wardk (Deacon) on Apr 02, 2001 at 21:44 UTC

    so how about this...

    #!/bin/perl use CGI qw/:standard/; use CGI::Cookie; use strict; my @cookie; # do this in a loop.... $cookie[0] = new CGI::Cookie(-name=>'ID',-value=>123456); $cookie[1] = new CGI::Cookie(-name=>'preferences', -value=>{ font => 'Helvetica', size => '12' }); print header(-cookie=>\@cookie);
    which produces....
    Set-Cookie: ID=123456 Set-Cookie: preferences=size&12&font&Helvetica Date: Mon, 02 Apr 2001 17:42:01 GMT Content-Type: text/html
      Ive tried your script aswell. This is what im doing but it just wont put them all in the cookie. $inputs is a hash which contains only 9 instances (not over 4k).
      sub set_cookie_value { my ($inputs) = @_; my @cookies = (); my $key; foreach $key (keys %$inputs) { $cookie = new CGI::Cookie(-name=>$key, -value=>$inputs->{$key} +, -expires=>$inputs->{$key}, -path=>'/', -domain=>'', -secure=>0); push (@cookies, $cookie); } print header( -cookie=>\@cookies ); print "--$inputs->{'postcode'}--" }
      Any further ideas?

        what is the programs output?

        you can determine this by running it from a command line, CGI.pm will prompt you for some input variables (you can also pass them on the command line), like so: (line 1 is executing the script, 2 is the script prompting me for input, 3 is my input. between lines 3 and 4 I hit Ctrl-D, lines 4-7 is the output. in this case 2 cookies.

        1 xdev$ perl cook.pl 2 (offline mode: enter name=value pairs on standard input) 3 foo=bar 4 Set-Cookie: ID=123456 5 Set-Cookie: preferences=size&12&font&Helvetica 6 Date: Tue, 03 Apr 2001 21:01:04 GMT 7 Content-Type: text/html xdev$

        note the code executed above is the same code posted in the previous node

Re: CGI::cookie query
by suaveant (Parson) on Apr 02, 2001 at 19:38 UTC
    I also just realized... now, I don't really use CGI.pm, but it seems to me writing the cookie with the same name over and over again could be overwriting your old one in CGI::Cookie? I may be wrong.
                    - Ant