in reply to Pass a hash as parameter to a CGI?

A perl reference is just a fancy pointer. Even if you could recreate the pointer when the .cgi is called again, that to which it was pointing is no longer in memory. What you can do is serialize the hash. There are modules to do that, or here's a simple way to do a hash of strings or an array of strings:

$s = join('|', map { local $_=$_; s/\^/^1/g; s/\|/^2/g; $_ } %test_hash );

And to deserialize:

%test_hash = map { local $_=$_; s/\^1/^/g; s/\^2/|/g; $_ } split(/\|/, $s);

I didn't use a slashed escape mechanism since it's makes deserialization hard. (i.e. "Should I split on this pipe, or is that an escaped pipe?") Trivia: IP over Serial Line (SLIP) and maybe Point to Point Protocol (PPP) use a similar escaping mechanism to escape packet delimiters since the delimiters cannot appear inside a packet.


Update: I had typos originally. Fixed. here's some test code:

use Data::Dumper (); %test_hash = ( 'apple' => 'red', 'lime' => 'green', 'junk' => 'foo^bar', 'junk2' => 'bla|bla', ); print(Data::Dumper->Dump([ \%test_hash ],[qw( $test_hash_ref )])); print("\n"); $s = join('|', map { local $_=$_; s/\^/^1/g; s/\|/^2/g; $_ } %test_hash ); print($s, "\n"); print("\n"); %test_hash = map { local $_=$_; s/\^1/^/g; s/\^2/|/g; $_ } split(/\|/, $s); print(Data::Dumper->Dump([ \%test_hash ],[qw( $test_hash_ref )])); __END__ output ====== $test_hash_ref = { 'apple' => 'red', 'junk' => 'foo^bar', 'junk2' => 'bla|bla', 'lime' => 'green' }; apple|red|junk|foo^1bar|junk2|bla^2bla|lime|green $test_hash_ref = { 'apple' => 'red', 'junk' => 'foo^bar', 'lime' => 'green', 'junk2' => 'bla|bla' };

Replies are listed 'Best First'.
Re^2: Pass a hash as parameter to a CGI?
by C_T (Scribe) on Sep 16, 2004 at 18:05 UTC
    Very cool! What would happen in this example code if the hash was like this?:

    $var = undef; $hash{'param1'} = 1; $hash{'param2'} = $var;

    CT

    Charles Thomas
    Madison, WI

      The code above only covers array and hashes of strings, and undef is not a string. Below is a variation that supports undef. Anything more complicated should definitely use FreezeThaw.

      sub serialize_string_list { return join('|', map { (defined($_) ? do { local $_=$_; s/\^/^1/g; s/\|/^2/g; $_ } : '^0' ) } @_ ); } sub deserialize_string_list { return map { ($_ eq '^0' ? undef : do { local $_=$_; s/\^1/^/g; s/\^2/|/g; $_ } ) } split(/\|/, $_[0]); } $s = serialize_string_list(%test_hash); %test_hash = deserialize_string_list($s);
      I answered my own question. It works, but throws warnings if you have them turned on.

      $test_hash_ref = { 'apple' => 'red', 'junk' => 'foo^bar', 'junk2' => undef, 'lime' => 'green' }; Use of uninitialized value in substitution (s///) at ./serialize.pl li +ne 19. Use of uninitialized value in join or string at ./serialize.pl line 19 +. apple|red|junk|foo^1bar|junk2||lime|green $test_hash_ref = { 'apple' => 'red', 'junk' => 'foo^bar', 'lime' => 'green', 'junk2' => '' };

      CT

      Charles Thomas
      Madison, WI