Curtis,
    Of course I'm not going to take this personally, this is the very reason I 
submitted the code.
I appreciate your feedback.  The reason I was frustrated with Todd is because it was 
strictly
criticism.  Basically the tone was "Your wrong, and you shouldn't be making your own 
lib anyway".
    Ok, I'm going to reply to your comments, then I have attached the full lib so you 
can see how
the whole thing works.  Granted the web site for the lib is blank because I lost that 
page and
didn't have a back up for it.  So, I have to rebuild the home page for it.

>    my @variables = split(/\&/, $input);
> First, we know that the split is incorrect.  A semi-colon is the new, preferred
> delimiter for form data, beginning with the HTML 4.0 specification.

Any suggestions on how to do this?  Should I check to see if there are &'s and if not 
attempt to
split on ;'s?

> my $form_hash = parse_form_input( $ENV{QUERY_STRING} );
> Now, if I have 20 programs, I have 20 places to mistype that.

If you will look at the full lib attached, you simply use:
use Form.pm
my %vars = Form();
Sorry for the confusion, I thought I had cleared up that those two functions were only 
the guts of
the lib.

> next if ($variable !~ /\=/);
> Oh, and you don't need to escape the equals sign.

I know, but I usually escape all special characters so that I don't have to worry 
about which ones I
do and don't have to escape.  I know, dirty habit from when I first began learning 
perl.

> if ($value ne ""){
> Not sure if I like that last line.

Yes, I know.  I have earlier in on this group suggested that I would probably give the 
option of
receiving empty value pairs. (or maybe it was in a different perl group, hmm, not sure)

> if (!defined $form_vars{$name}) { # if this is the first of this form input name.
> You want "exists", not defined.

Ok, any reasons why?  They both seem to accomplish exactly the same result.

> if (!defined $form_vars{$name}) { # if this is the first of this form input name.
>   $var_count{$name} = 0; # set the count of the array to 0 incase there is more than 
>one
>   $form_vars{$name} = $value; # setting the variable the hash with the name to the 
>value
> } else { # for repeated times in with the same form input name
>   $form_vars{$name} = [($form_vars{$name})] if ($var_count{$name} == 0); # set the 
>first element
to the first input if this is only the second input with this name
>   $var_count{$name}++; # increase the count of the array for this form input name
>   push(@{$form_vars{$name}}, $value); # adding the next element to the list
> }
> First, there's no reason to track the var count since you just throw it away.
> Second, you can skip the entire if/else structure and just give people a array 
>references for the
values

Your right, beyond the first I don't need to track the count.  I could have said
$var_count{$name}=1; instead of $var_count{$name}++; and I would have accomplished the 
same thing.
I do need to track it that far to accomplish my desired result.  That is that single 
value pairs
only have hash element name = value.  But multiple value same name sets would be name 
= array_ref.
Actually, come to think of it, instead of keeping a count, I could simply say:
$form_vars{$name} = [($form_vars{$name})] if (ref($var_count{$name}) ne "ARRAY");
and that would accomplish what I wanted.  Hmm, that's a line of code I haven't touched 
for a good
year or two (I began programming in Commodore basic back in 1983 or 1984, some habits 
never die,
counters for example).

Ok, let me finish up here.
    Yes, my lines of code are long.  For this I apologize.  I work on 1600x1200 with 
Homesite which
doesn't wrap lines unless I ask it to.  You know, if you have the same circumstances 
as I do, it
sure makes for easy reading (less vertical lines, and all same command on the same 
line and so on).
    I do handle POST, I guess I didn't make that clear before.  Read through the 
attached lib and
you will see that is true.  That is what parse_mform_input is about.
    Yes, everybody does need to print the header and other such things.  CGI.pm does 
provide
functions for this, but that is not what this lib was intended for.  I wrote this to 
accomplish one
specific task quickly, efficiently, and the way I wanted it done, and that task was to 
receive data
and put it into a very useable format.  I didn't intend to write a CGI.pm replacement, 
that makes no
sense at all (there are way too many functions there that I for one will never use, 
and am not
interested in, though I understand others are).  Most scripts that I have seen do 
their own print
headers and cookies without regard to CGI.pm as stands.  Infact, most that I have seen 
only use
CGI.pm for the retrieval of data.  You know, I didn't even write this lib with intent 
to give CGI.pm
competition.  I simply wanted a lib that did as I described above, and once I had 
created it,
wondered if I was the only one who would be interested in such a library.  I don't 
believe that I
am, so I figured I would share it with the rest of the world as well.

I appreciate the feedback, and hope with the full lib in hand I will get more.

Also remember that I have a few options I already plan to add to it that are currently 
not there.
- Option to disable upload
- Option to limit upload file size
- Option to receive all name value sets regardless of if the values are empty
- Option to receive get along with post

I think there is one more that keeps eluding me, but anyway, that's the jist of it.

Thanks,
David



----- Original Message -----
From: "Ovid" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>; <[EMAIL PROTECTED]>
Sent: Wednesday, July 03, 2002 9:35 AM
Subject: Re: Form.pm


Hi David,

I hope you don't take this stuff personally.  A code critique is a critique, after all 
:)

I'll skip the lines of code that I'm not commenting on.

    my $input = shift;
    my @variables = split(/\&/, $input);

First, we know that the split is incorrect.  A semi-colon is the new, preferred
delimiter for form data, beginning with the HTML 4.0 specification.  See
http://www.w3.org/TR/REC-html40/appendix/notes.html#ampersands-in-uris for more
information.  And yes, I *have* seen user agents using semicolons.

However, that's not my biggest concern.  You're forcing the use to do something
like this:

  my $form_hash = parse_form_input( $ENV{QUERY_STRING} );

Now, if I have 20 programs, I have 20 places to mistype that.   This will
increase the chance of bugs and is a serious problem.  The user needs to be
shielded from such implementation details.

Further, while you acknowledge that you don't currently handle POST requests, I
consider this to be a bug, not a limitation.  GET and POST requests are only
similar on the surface.  Their actual behavior is different enough that leaving
off POST cripples this code.

    foreach $variable (@variables) {

Hmm... you didn't predeclare $variable.  It looks like you're not using strict.
Tsk, tsk.  If someone else using this code has a global named $variable in the
same namespace, you've just clobbered it.

      next if ($variable !~ /\=/);

Skip if no '='?  I guess this code doesn't handle ISINDEX, either, but I won't
cry over that.  Who uses it anyway?  (I'm sure I'm going to hear from two of
the three people who still do :)  Oh, and you don't need to escape the equals
sign.

      if ($value ne ""){

Not sure if I like that last line.  If the value evaluates as false, you throw
away the name.  I'm not sure the end-user is going to appreciate the data loss.
This could become a problem is they're doing something with the names and they
have them hard-coded into their code.

        if (!defined $form_vars{$name}) { # if this is the first of this form input 
name.

You want "exists", not defined.

          $var_count{$name} = 0; # set the count of the array to 0 incase there is 
more than one
          $form_vars{$name} = $value; # seting the variable the hash with the name to 
the value
        } else { # for repeated times in with the same form input name
          $form_vars{$name} = [($form_vars{$name})] if ($var_count{$name} == 0); # set 
the first
element to the first input if this is only the second input with this name

First, there's no reason to track the var count since you just throw it away.
Second, you can skip the entire if/else structure and just give people a array
references for the values.  Some people aren't familiar with them, so you could
provide nice, transparent accessors to them.  Then, you have plenty of control
over access to your data structure.

This is one of the nice benefits of CGI.pm's param() method.  All of the form
values are stored internally as array refs, but param() uses 'wantarray' to see
if you just want a scalar value or all of them.  This means that internally
there is only one data structure type for these values and less change of bugs.

Okay, that's my general comments on the first subroutine.  I'll tackle
parse_mform_input() later.  However, I'll go ahead and make some general
comments on the code.

First, your lines are waaaaaaaaaaaaaay too long.  Different editors and
different resolutions allow for different lines lengths to be comfortably
displayed.  In every single editor that I have, your lines of code wrap around
the screen.  This makes it very difficult for me to trace the execution of your
program.  By limiting your line lengths to, say, 80 characters or so, you can
ensure that others can easily read through your code.  Further, if you need to
work on your code on someone else's computer (which can be common in a
workplace), then you are less likely to be cursing wrapping lines.

If you added POST handling to your code, you might think it complete.  I would
disagree because of the limitations in your code.  For example, how many times
do we see stuff like the following:

  print "Content-type:text/html\n\n";

  print "ContentType: text/plain\n\n";

  print "Set-Cookie: name=Ovid; expires=Friday,31-Dec-02 23:59:59 GMT; 
domain=ovidinexile.com;\n";

Every one of those three lines has an error.  Some of them, the browser (or
perhaps the Web server) will correct for.  Others will not be corrected.
Further, many programmers, even experienced Web programmers, will not spot the
errors right away.  Now, if most Web programs only parsed form input, your code
would be fine, but that's not the case.  These programs print headers and
generate cookies.  They *have* to.  As a result, any module that is going to
handle form data will have to handle headers and cookies for the user rather
than allow users to keep making typos like I did in the above code.

Naturally, not all of the errors that a user can make will be eliminated by
code that handles this for them, but anything that reduces their error rate for
known repetitive actions (headers and cookies) is pretty much mandatory for
code that is to benefit Web programming.

Cheers,
Curtis "Ovid" Poe


=====
"Ovid" on http://www.perlmonks.org/
Someone asked me how to count to 10 in Perl:
push@A,$_ for reverse q.e...q.n.;for(@A){$_=unpack(q|c|,$_);@a=split//;
shift@a;shift@a if $a[$[]eq$[;$_=join q||,@a};print $_,$/for reverse @A

__________________________________________________
Do You Yahoo!?
Sign up for SBC Yahoo! Dial - First Month Free
http://sbc.yahoo.com

--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Attachment: Form.pm
Description: Binary data

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to