Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

accessing CGI object from a subroutine in another package.

by kingman (Scribe)
on Aug 30, 2001 at 17:48 UTC ( [id://109076]=perlquestion: print w/replies, xml ) Need Help??

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

Hi, I'm trying to put some subroutines into a module so I can easily re-use them. But I'm not really clear on the syntax. I'm trying to access a CGI object in package main from a subroutine declared in a module. Is this sub-classing? Here's the script:
#!/usr/bin/perl -wT use strict; use Shortcuts qw(debug print_at_form create_at_job); BEGIN {&debug} use CGI; my $q = new CGI; print $q->header(); print "<center>\n"; print_at_form($q); &create_at_job("touch /home/foo/some_file\n") if $q->param('Submit');
This creates the form but when I try to submit it, I get this error: Can't call method "param" on an undefined value at /usr/lib/perl5/site_perl/5.6.0/Shortcuts.pm line 50 I think this is happening because I'm putting a COPY of the cgi object ($q) into &print_at_form so the &create_at_job doesn't know what I'm talking about. I was also wondering if I should be using this function-oriented code with an object; it doesn't seem right somehow. I tried changing $q->startform() in print_at_form to $main::q->startform() (throughout the sub) but that didn't work either. Here's the module:
package Shortcuts; # See the bottom of this file for the POD documentation. Search for t +he # string '=head'. use strict; use diagnostics; use vars qw($q @ISA @EXPORT_OK $VERSION); use subs qw(debug); use Exporter; $VERSION = 1.00; @ISA = qw(Exporter); @EXPORT_OK = qw(debug print_at_form create_at_job); ### subroutines ### sub debug { use CGI::Carp qw(carpout fatalsToBrowser); &carpout (\*STDOUT); } sub print_at_form { my $q = $_[0]; print $q->startform(); print "Hour"; print $q->popup_menu(-name=>'hour', -values=>[1..12]); print "Minutes"; print $q->popup_menu(-name=>'minute', -values=>[qw/00 05 10 15 20 +25 30 35 40 45 50 55/]); print "Day"; print $q->popup_menu(-name=>'day', -values=>[qw/Today Mon Tue Wed +Thu Fri Sat Sun/]); print $q->radio_group(-name=>'meridiem', -values=>[qw/am pm/]); print $q->submit(-name=>'Submit'); print $q->endform(); return $q; } sub create_at_job { my %time = &_untaint; my $string = "/usr/bin/at $time{hour}:$time{minute} $time{meridiem +} $time{day}"; my $pid = open(ATJOB, "| $string") or die "Couldn't fork: $!\n"; print ATJOB $at_command; close(ATJOB); print "Your job has been scheduled for <b>$time{hour}:$time{minute +} $time{meridiem} $time{day}</b>"; } sub _untaint { my %time; $ENV{"PATH"} = ""; if ($q->param('hour') =~ /^(1|2|3|4|5|6|7|8|9|10|11|12)$/) { $time +{hour} = $1; } else { die "Can't untaint 'hour'"} if ($q->param('minute') =~ /^(00|05|10|15|20|25|30|35|40|45|50|55) +$/) { $time{minute} = $1; } else { die "Can't untaint 'minute'"} if ($q->param('day') =~ /^(Today|Mon|Tue|Wed|Thu|Fri|Sat|Sun|)$/) +{ $time{day} = $1; } else { die "Can't untaint 'day'"} if ($q->param('meridiem') =~ /^(am|pm)$/) { $time{meridiem} = $1; +} else { die "Can't untaint 'meridiem'"} return %time; } 1;

Replies are listed 'Best First'.
Re: accessing CGI object from a subroutine in another package.
by wog (Curate) on Aug 30, 2001 at 18:13 UTC
    The reason your CGI object isn't getting into the package global $q variable is because print_at_form has it's own private lexical (my-created) $q variable, seperate from the package. You can fix this problem by removing the my from the my $q = $_[0];.

    That said, you have very bad design here. Subroutines should be independent and reusable whenever possible. You are requiring another, unreleated subroutine to have been used for this to work. For example, what if you wanted to modify your program in the future so it would not always print_at_form when it got the info to make an at job? It would be better to have create_at_job take $q as an argument, and pass it to _untaint as an argument (it would also be nice to rename _untaint into a more informative name like _get_untainted_time, so you can get an idea what it does just be looking at it's name.) It's not going to be much more code to do this, and it makes your code much easier to maintain.

    Another note, I don't think letting people start at jobs like this is a good idea -- it opens you up to mean people who would overload your webserver with at started programs.

Re: accessing CGI object from a subroutine in another package.
by jryan (Vicar) on Aug 30, 2001 at 18:13 UTC

    You can't create an object in one pge and then expect to be able to use it in others. You can still do what you want by a few different ways:

    1. Creating a new CGI object in the module, and then accessing the params from there. Don't forget to use CGI.
    2. Passing the CGI object in main to the function. You will still need to use CGIin the module so that it knows what to expect.
Re: accessing CGI object from a subroutine in another package.
by clintp (Curate) on Aug 30, 2001 at 18:16 UTC
    If you just need to share the query object everywhere, it might be easier to just make it accessable from everywhere. Instead of:
    my $q=new CGI;
    Use 'use vars qw($q)' or the 5.6 construct our:
    our $q=new CGI;

    Then in the module, refer to the variable by its fully-qualified package name:

    $main::q

    Purists will maintain, however, that you should just pass it around. Pass $q to create_at_job as well as to print_at_job. (_untaint seems to have the same problem.)

Log In?
Username:
Password:

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

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

    No recent polls found