tags:

views:

295

answers:

5

I have a scriptA.cgi which calls scriptB.cgi.

scriptB.cgi requires a param.

I have tried both inside scriptA.cgi I have tried:

`perl -l scriptB.cgi foo="toast is good" `;

as well as

@args = ("perl", "-l", "scriptB.cgi", "foo=\"toast is good\"");
system(@args);

When I call scriptA.cgi from the command line it works as expected. However when I call scriptA.cgi through the browser scriptB.cgi is executed but it fails to read the incoming param and prints foo as empty.

Is there a less ugly way to call one cgi from another and pass in params?

scriptB does not have to be a cgi, if it's easier to do this with a straight .pl and args, I'm happy to do that too... but the arg has to be a quoted string with spaces.

All thoughts welcome.

A: 

A:

#!/usr/bin/perl
print "Content-type: text/html\n\n";
{
    local $foo = "toas is bad";
    do 'b.cgi';
}

B:

#!/usr/bin/perl
print "$foo";
Why down? this accomplishes what you asked?
I wasn't the one who down graded it... I would never down grade if someone took the time to try and help me, even if their info wasn't useful (not saying yours isn't). Could you explain what is happening in your code? I don't understand why $foo would be utilized as the param to the cgi call here
Dr.Dredel
If using `do FILE` seems like a good solution, you really should be using modules.
daotoad
You don't know what havoc that do will bring into the calling program. It could change all sorts of state, destroy data, and what not. At least with a module you usually don't actually run code until you call one of its subroutines.
brian d foy
A: 

Here's a snippet from some code I wrote that has a _*.cgi_ script calling a Perl script:

$note = "toast is good";
$cmd = "addAccTrans.pl $priAcc $date $priGrp \"$note\" $amt";<br />
open($f, "perl $cmd|");<br />
while(<$f>) { print "$_\n" };<br />
close($f);<br />

The CGI script captures the output of the Perl script and prints it out again.

Cecil
Ouch. What if $priAcc has something like foo; rm -rf /*? Or more realistically, a variable like that could be used to upload a bootstrapping script for future pwnage.
daotoad
thats why you sanitize $cmd first.
@unk, That's why you don't pass user input through the shell--sanitized or not.
daotoad
+4  A: 

If there is common functionality shared between many scripts, put it in a module

Modules may seem intimidating, but they are really very simple.

File SMSTools.pm:

package SMSTools;
use strict;
use warnings;
use Exporter qw(import);

# Name subs (and variables, but don't do that) to export to calling code:
our @EXPORT_OK = qw( send_sms_message );

our @EXPORT = @EXPORT_OK;  
# Generally you should export nothing by default.
# However, for simple cases where there is only one key function
# provided by a module, I believe it is reasonable to export it by default.


sub send_sms_message {
    my $phone_number = shift;
    my $message      = shift;

    # Do stuff.

    return; # Return true on successful send.
}

# Various supporting subroutines as needed.

1;  # Any true value.

Now, to use your module in foo.cgi:

use strict;
use warnings;
use CGI;

use SMSTools;

my $q = CGI->new;

my $number = $q->param_fetch( 'number');
my $message = $q->param_fetch( 'msg');

print 
    $q->header,
    $q->start_html,
    (    send_sms_message($number, $message) 
         ? $q->h1("Sent SMS Message") 
         : $q->h1("Message Failed")
    ),
    q->end_html; 

See perlmod, and the docs for Exporter for more information.

daotoad
that's an excellent answer, and I'm upvoting it, but I'd still like to figure out the answer to my initial question. However, thanks very much.
Dr.Dredel
+2  A: 

I suspect that the CGI environment is getting in your way. Are you using CGI.pm?

When you run your CGI script from the command line, you probably haven't set any of the CGI environment variables, such as QUERY_STRING. The CGI script starts up, notices its missing those environment variables, and thinks it must have been run from the command line. If it thinks it has been run from the command line, it looks in other places, such as @ARGV, for the data. That would be my first guess.

There are various things that might be going on in the CGI program case. Mostly likely, scriptB.cgi is using the same environment set-up for scriptA.cgi and it doesn't have the parameters or data it expects. Since the CGI environment is set up and there isa QUERY_STRING variable, it never thinks to look in @ARGV.

However, you have many options depending on what you want to do (and this goes a bit beyond your situation):

  • If you only need scriptB.cgi to support other scripts (i.e. browsers should never call it directly), make it a library or a module. You should always try to do this. Make every script at least a modulino.

  • If scriptB.cgi is a standalone CGI script and should stay that way, make a sub request in scriptA.cgi so all the normal CGI stuff gets set up through the server.

  • If you don't want to make a subrequest, localize %ENV, which child processes will share, and fake the CGI environment yourself. That's a bit of work, but not too hard.

brian d foy
Brian! It's so good to hear your voice. You and I worked together about 12 years ago for Smith Renaud. I hope you're doing as well in life as you are in your SO point count! I like your answer a lot and I'm sure it accounts for what my problem is. If you have a public email addy you can post here, I'll send you mine. Happy New Year, -Gene
Dr.Dredel
Oh hey Gene, I was just talking about you to someone. We were talking about how Russian jokes never translate to English and how you'd always have to say "It's funny is Russian" :)
brian d foy
A: 

See "Decoding Form Output" here:

http://www.cgi101.com/class/ch4/text.html

(Her post.cgi script was invaluable to me in diagnosing this issue.)

And another thing to be aware of for those of you using CGI.pm--it uses "multipart/form-data" for its default encoding type, which "is suitable for forms that ... are intended for transferring binary data." Interestingly, changing the encoding type to the other option made everything work as one would expect:

-enctype=>"application/x-www-form-urlencoded"

(Tested with Windows XP, Perl 5.10, CGI.pm 3.43, and Apache 2)

Jim