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

Since I have learned the ways of CGI.pm, the world has been a better place. But there are still some servers I have to write scripts for that don't have any CPAN modules installed.

When this happens, I normally use the following subroutine:

sub parsedata { ($ENV{'REQUEST_METHOD'} eq "GET") ? $in = $ENV{'QUERY_STRING'} : read(STDIN,$in,$ENV{'CONTENT_LENGTH'}); @in = split(/&/,$in); foreach $i (0 .. $#in) { $in[$i] =~ s/\+/ /g; $in[$i] =~ s/%(..)/pack("c",hex($1))/ge; $in[$i] =~ s/\n/ /g; $in[$i] =~ s/\r/ /g; ($key, $val) = split(/=/,$in[$i],2); $in{$key} .= '\0' if (defined($in{$key})); $in{$key} .= $val; } }

This then makes a variable $in{'foo'} for the HTML form element named foo.

Great.

But I've also started writing use strict in all my code, and it's not real clear to me how I can get my scoping correct using the above function.

Any ideas?

Replies are listed 'Best First'.
Re: A strict CGI parser?
by chromatic (Archbishop) on Jul 26, 2000 at 00:58 UTC
    Well, the following lines at the start and end of your subroutine would do:
    my ($in, @in, %in); # stuff here return \%in; # or %in, as you prefer
    You'll get back either a reference to a hash of keys and values or a copied list made from the hash, depending on if you return a reference or the hash.

    You could also declare %in as a global variable at the top of this script with use vars qw( %in );. You can keep the internal my declaration of $in and @in, as they don't appear to be used outside your subroutine.

    Of course, CGI.pm has been included in the standard distribution of Perl since 5.004. If you're regularly working on servers with older installations than that, it's time for their owners to upgrade. The current release is two minor versions higher, with lots of bug and security and feature fixes I'm sure you already know about. :)

Re: A strict CGI parser?
by athomason (Curate) on Jul 26, 2000 at 01:13 UTC
    Are you really sure CGI isn't installed? It's included by default with most recent Perl distros, past 5.004 as chromatic pointed out. But if you're really stuck, take a look at the code in CGI.pm itself: it's better to build off of the right way to do it than reinvent the wheel incorrectly. Specifically, the code you need is in the init and parse_params subs.

    The reason I'd suggest you modify existing code for your needs (or use it straight out if you can) is that it's difficult to handle all the possible query strings and a lot of people get it wrong (even many CGI books have flawed parameter parsers). For instance, what will your routine do when a user selects multiple items in a list box? Only the last will be saved, which is incorrect behavior. You may not have any such forms, and your code may work with your application, but look around for existing battle-tested implementations; turnstep posted one here in response to a Q&A post.

Re: A strict CGI parser?
by davorg (Chancellor) on Jul 26, 2000 at 02:08 UTC

    You know, CGI.pm really isn't very difficult to install. It's a single file and there's no XS component to deal with. If you really are having to deal with versions of Perl earlier than 5.004_04 you could just copy the CGI.pm file into your cgi-bin directory and everything will work fine.

    Of course if people are using a version of Perl that old then they have security issues far more serious than just having buggy CGI scripts.

    --
    <http://www.dave.org.uk>

    European Perl Conference - Sept 22/24 2000, ICA, London
    <http://www.yapc.org/Europe/>