Perl CGI::param Overloaded Method?

Nov 30, 2009 / By John Scoles

Tags: , ,

This is a little story of a little bug. This gremlin suddenly appeared in a CGI.PM web-based application I work with. To make a long story short, an email was coming out something like this . . .

389939
Subject:Update to Report #389939 by B. bloggins Description:389939 #389939: TPDD Now Deploying to monitoring for the MySQL servers.

. . . when it should have been some thing like this:

Subject: TPDD Update to Report #389939 by B. bloggins

TPDD Now Deploying to monitoring for the MySQL servers.

After about an hour tracking things back, my team and I narrowed it down to this line of code:

$self->send_TXT_email(CGI::param("rep_no"),$rep_object,
                     $subject,$user_ref);

We scratched our respective heads on this for a while, because for user type ‘A’, it worked fine; but for user type ‘B’, it did not. And they were both using the same web page to send the email.

But before we went and reinstalled our mail server, I remembered that this is how CGI::param is intended to work:

@values = $query->param('foo');
# or
$value = $query->param('foo');

Arghhh! A wretched, two-faced overloaded method! So, depending on how you call the method, the returned results may differ.

Looking deeper, I discovered that the page was in fact receiving three values for CGT::param(“rep_no”) when user was of type ‘B’, and thus sending that as an array to the send_TXT_email method, and as a result, buggering up the email content.

Even more digging I found out the root cause was a web page that was three pages back from the one that was sending the email. Seems some-one made a change to fix one bug and as a result caused this one.

This quick fix for this (as we could not change the root page) was

my $rep_no=CGT::param("rep_no");
$self->send_TXT_email($rep_no,$rep_object,$subject,$user_ref);

Lesson learned: never trust a wretched, two-faced overloaded method.

3 Responses to “Perl CGI::param Overloaded Method?”

  • Richard Quintin says:

    Perl – a million solutions for every problem.

    Would this also do it?
    $self->send_TXT_email(scalar($rep_no=CGT::param(“rep_no”)),$rep_object,$subject,$user_ref);

  • $self->send_TXT_email(scalar($rep_no=CGT::param(”rep_no”)),$rep_object,$subject,$user_ref);

    Actually, the scalar( $x = param() ) is overkill. Assigning ‘param()’ to a scalar already forces a scalar context. So

    $self->send_TXT_email(scalar(CGI::param(”rep_no”)),$rep_object,$subject,$user_ref);

    or

    $self->send_TXT_email(($rep_no=CGI::param(”rep_no”)),$rep_object,$subject,$user_ref);

    or even

    $self->send_TXT_email(''.CGI::param(”rep_no”),$rep_object,$subject,$user_ref);

    would work just fine. Although splitting it in two statements, like John did, is a more readable way of doing it.

  • Daniel Fisher says:

    I could be wrong here, but you could also embrace the overloading:

    ($value) = $query->param(‘foo’);

    You’ll get the param output as an array, where it will put the first value in the list into $value.

Leave a Reply

  • (will not be published)

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>