Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:
Hello fellow monks,
I'm learning CGI, and have a questions (Probably an easy one). I have a cgi script, and wish to call a subroutine via 'a href', what is the correct syntax? I am trying this code, but unfortunately it doesn't work!
print "<a href=\&toggle_on>ON</a>";
&toggle_on is my sub-routine
Thanks guys (and gals)
Re: Calling a sub-routine in CGI
by DamnDirtyApe (Curate) on Aug 09, 2002 at 03:10 UTC
|
I think you're blurring the line between HTML and Perl more than is possible here. As I understand it, an HTML anchor is simply a way of requesting a certain page from the web browser. It's not directly a way of executing code. What you may be able to do instead is something like:
print qq[<a href="my_script.pl?sub=toggle_on">ON</a>] ;
Then, have my_script.pl test the value of param( 'sub' ), and execute the appropriate subroutine.
If you choose to do something like this, take precautions against malicious posts, and do not execute user input directly.
_______________
DamnDirtyApe
Those who know that they are profound strive for clarity. Those who
would like to seem profound to the crowd strive for obscurity.
--Friedrich Nietzsche
| [reply] [d/l] [select] |
Re: Calling a sub-routine in CGI
by fuzzyping (Chaplain) on Aug 09, 2002 at 04:58 UTC
|
As DamnDirtyApe has started to allude to, you cannot use a hyperlink to call a subroutine. A perl subroutine is encapsulated within the CGI process. An HTML hyperlink is simply another way of requesting a web "object", where an object can be any manner of hosted files... text/html, images, cgi scripts, etc. However, the execution of said scripts does NOT happen within Apache's process... a separate perl process is started to handle the cgi task; only the output of the script is returned to Apache for output to the requestor (browser).
Assuming you want the script to perform some function as defined by a subroutine, I suggest you create a URL with custom or hidden parameters, which, when read in by the cgi, understands to run the appropriate subroutine. Example:
#/usr/bin/perl -w
use strict;
use CGI qw(:standard);
my $cgi = CGI->new;
if ($cgi->param()) {
if ($cgi->param('toggle_on')) {
&toggle_on;
} elsif ($cgi->param('toggle_off')) {
&toggle_off;
} else {
&default;
}
} else {
# print form
print $cgi->a({href => "/cgi-bin/script.cgi?toggle_on=1"}, "Toggle
+ On");
# print more stuff
}
Hope this helps!
-fp
| [reply] [d/l] |
Re: Calling a sub-routine in CGI
by Massyn (Hermit) on Aug 09, 2002 at 05:53 UTC
|
Hi Anonymous Monk,
Hmmm... Yes, it easy, depending on what you want to do. Are you
a) Trying to execute what ever is in &toggle_on and put the output of that text in your A HREF command, or are you
b) Trying to get &toggle_on to execute when you click the ON hyperlink? It almost looks like this is what you're trying to do. If so, you're going the wrong way.
Solution A
print "<a href=" . &toggle_on . ">ON</a>";
Solution B
#get the UNWEB procedure in here
$FORM=&unweb;
if($FORM{action} eq "toggleon")
{
&toggle_on;
}
else
{
print "<a href=\"?action=toggleon\">ON</a>\n";
}
This is a very simplified way of going. | [reply] [d/l] [select] |
|
I'm sorry, but I'm still learning...Where can I learn more about UNWEB?
Thanks
| [reply] |
|
sub unweb
{
if($ENV{QUERY_STRING} eq "")
{
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}
else
{
$buffer = $ENV{QUERY_STRING};
}
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ s/~!/ ~!/g;
$FORM{$name} = $value;
}
return %FORM;
}
Have a look at cgi101. That's where I started with CGIs.
| [reply] [d/l] |
Re: Calling a sub-routine in CGI
by physgreg (Scribe) on Aug 09, 2002 at 03:08 UTC
|
print "<a href='".toggle_on()"'>ON</a>";
Without knowing what toggle_on does. Are you trying to access the subroutine via the web page link? If so, it is not so straightforward, as you have to get the name from a form submission. Then you could have a hash of subroutine references, and if the form submission is in your list, then run it. In which case a bit of code like:
print "<a href='$BASE_URL?action=toggle_on'>ON</a>";
will be what you want in your HTML, where $BASE_URL is set to the appropriate link for your script. I would suggest having a look at CGI.pm for an easy way to deal with form submissions. Hope that helps! | [reply] [d/l] [select] |
Re: Calling a sub-routine in CGI
by Anonymous Monk on Aug 09, 2002 at 03:34 UTC
|
This is the source I'm using, the sub routines work if I call them explicitly, but I wan't to call them from a link on the same page
#!perl.exe -wT
use Strict;
use CGI;
my $q = new CGI;
print $q->header("text/html");
print <<WEB_PAGE;
<HTML>
<HEAD>
<TITLE>Help ME</TITLE>
</HEAD>
<H1> Just a simple page for now </H1>
WEB_PAGE
my ($device, $port, $house, $unit, $interface);
# Use BEGIN so we can conditionally eval modules
BEGIN {
# Set the parameters
$interface = 'CM11';
$port = 'COM1';
$house = 'A';
$unit = '2';
use Win32::SerialPort 0.17;
die "$@\n" if ($@);
$device = Win32::SerialPort->new ($port) or die "Can't start $port
+\n";
eval "use ControlX10::CM11 qw( :FUNC 2.06 )";
die "$@\n" if ($@);
}
$BASE_URL = '/cgi-bin/lights.cgi';
print "Turn light <a href='$BASE_URL?action=toggle_on'>ON</a>";
# &toggle_on;
# &toggle_off;
sub toggle_on{
my $cmd = 'J';
print"<h2>Turning Lights ON</H2>";
print "---> Toggle light $house$unit to on \($cmd\)\n";
send_cm11($device, $house . $unit);
send_cm11($device, $house . $cmd);
}
sub toggle_off{
my $cmd = 'K';
print"<h2>Turning Lights OFF</H2>";
print "---> Toggle light $house$unit to on \($cmd\)\n";
send_cm11($device, $house . $unit);
send_cm11($device, $house . $cmd);
}
| [reply] [d/l] |
Re: Calling a sub-routine in CGI
by Anonymous Monk on Aug 09, 2002 at 11:23 UTC
|
Thanks everyone,
I guess I'm going about this the wrong way! (see my code mid way down the page) As I said I'm still learning CGI, and this is my first undertaking. Is there a better way to execute the toggle_on command? If so what are my options?
The toggle_on comand in using the ControlX10 module from CPAN to activate some X10 components. Would it be better and less complicated to just create some sort of form and exexcute the command based on text input, or is it possible (I know anything is possible with Perl) to activate the sub-routine graphically (ie pushing a button, or clicking a hyperlink)?
Thanks again
| [reply] |
|
So, you are wanting a web frontend to control some device connected through a serial port. This seems to imply that the machine with the serial port is the same one as running the webserver (it may be that all your software is running on one box).
I would suggest that you are biting off more in one go than you can chew.
I would suggest starting by writing a command line Perl program to drive the X10 stuff. Write this program in a modular fashion with subs for each of the functions.
Next think about your web interface. Design the front end forms and hyperlinks, and prototype how you want it to work.
Now knock up a small CGI app to call your existing program functionality using system or backticks. You should now have a working application!
Finally, rewrite the CGI application to call the code directly.
Hope this helps,
--rW
| [reply] [d/l] |
|
| [reply] |
|
|