Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Pass a hash as parameter to a CGI?

by C_T (Scribe)
on Sep 16, 2004 at 17:23 UTC ( [id://391510]=perlquestion: print w/replies, xml ) Need Help??

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

Hello!

I'm curious if there is a way to pass a hash as parameters in a perl CGI script.

For example, I tried this, which doesn't seem to work:

$test_hash{$switch_name}{'port_desc'} = 'Whatever'; $test_hash{$switch_name}{'speed'} = 'auto'; $test_hash{$switch_name}{'duplex'} = 'auto'; $test_hash{$switch_name}{'reserve_status'} = 'active'; $test_hash{$switch_name}{'port_vlan'} = '999'; $test_hash_ref = \%test_hash; print qq~<input type=hidden name="test_ref" value="$test_hash_ref">\ +n~;
This just passes a string that says "HASH(0x3jshdf29)" or somesuch.

Beyond breaking the hash down into its component key=>value pairs and passing each individually, then reassembling them into a hash again, is there a more elegant way to pass a data structure to a CGI form? I'd like to pass a REALLY big data structure, and the idea of doing it as 400 key=>value pairs really doesn't appeal.

Thanks for any info.

CT

Charles Thomas
Madison, WI

Replies are listed 'Best First'.
Re: Pass a hash as parameter to a CGI?
by Random_Walk (Prior) on Sep 16, 2004 at 17:29 UTC

    how about using FreezeThaw to stringify it then pass the string and thaw at the other end.

    Cheers,
    R.

      Wow! FreezeThaw works very well!

      Thanks for the tip! This is exactly what I needed.

      CT

      Charles Thomas
      Madison, WI
Re: Pass a hash as parameter to a CGI?
by ikegami (Patriarch) on Sep 16, 2004 at 17:31 UTC

    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' };
      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
Please remember to be safe.
by tmoertel (Chaplain) on Sep 16, 2004 at 19:13 UTC
    Just a quick public service announcement: Be safe.

    Always:

    1. Be mindful of encoding mismatches. If you're stuffing your frozen hash into an HTML/XML attribute value (and it looks like you are), what you are stuffing must conform to SGML/XML CDATA encoding requirements. Is the character encoding that FreezeThaw returns guaranteed to satisfy those requirements? If not, it's your responsibility to encode the frozen data before stuffing it into the attribute value. And on the reverse trip "out" of the value, you must decode it before thawing.
    2. Be paranoid about data from the client. What you get back from the HTTP POST may not be what you placed into your form's hidden field. The data you receive may not be what you were expecting. An attacker may have crafted a value designed to cause you grief. If you want to be safe, sign or encrypt your data on the way out and verify the signature on the way in. Use a key that is only known to your server.

    Let's be careful out there.

    Cheers,
    Tom

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://391510]
Approved by Limbic~Region
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (5)
As of 2024-04-25 08:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found