Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

calling functions in cgi

Status
Not open for further replies.

JackTheRussel

Programmer
Aug 22, 2006
110
FI
Hi.

How can I call different functions (in different buttons) ?

I have form where is upload-image button and execute button and textarea column.

Upload-image button let users to browse filesystem and select picture and then script saves picture to the folder /tmp.

execute-button writes textarea content to the file which are located in folder /tmp.

Now I don't know how can I make script which would call save_image function when user pushes upload-Image button.

and when user pushes execute-button it would go to the write_text function?

Now I have this kind of function call
Code:
    if ($q->param()) {
        save_file($q);
    }

So how can I make that If user pushes buttonX it goes to function X. If user pushes button Y it goes to function Y ?
 
Hi Jack,

I'm not 100% sure if this is what you require...

Okay, so you have your HTML form...

Code:
<form action=script.cgi method=post>
<input type="submit" name="upload_image" value="Upload Image">
<input type="submit" name="write_text" value="Write Text">
</form>

The above forms action (script.cgi) links to your CGI form when one of the two submit buttons is pressed. So obviously you connect to this form in your CGI script like this...

Code:
$upload_image = param('upload_image');
$write_text = param('write_text');

if ($upload_image) {
#UPLOAD IMAGE FUNCTION
}

if ($write_text) {
#WRITE TEXT FUNCTION
}

As you see to check which submit button has been pressed its as simple as that. Where I have written i.e. #UPLOAD IMAGE FUNCTION, this is where you include the code which uploads the image.

Chris

 
Ok. Thanks Chris.

So the conclusion is that, I should make html-page where the form locates and script.cgi which makes something to the values.

Now I only have script.cgi where I have form and the functions.

 
I always put my forms and my data in the same script.

Usually some logic like
print headers
if $q->params, process data, and either redirect or print output message
else print form

now if I don't mind the form being on every page (search functions normallY) I just print it on the top of every page. I like to make my scripts as few files as possible so I don't like having the seperate html file.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those who say it cannot be done are usually interrupted by someone else doing it; Give the wrong symptoms, get the wrong solutions;
 
Yeah thats right. I used to use a separate HTML file however I often need to print the html form again once the script has performed its tasks. So going back to the previous example, I would possibly change it to this...

Code:
$upload_image = param('upload_image');
$write_text = param('write_text');

if ($upload_image) {
#UPLOAD IMAGE FUNCTION
}

if ($write_text) {
#WRITE TEXT FUNCTION
}

print "Content-type: text/html\n\n";
print <<"HTML code";
<HTML>

<HEAD>
<title>HTML Form</title>
</HEAD>

<BODY>
<form action=script.cgi method=post>
<input type="submit" name="upload_image" value="Upload Image">
<input type="submit" name="write_text" value="Write Text">
</form>
</BODY>

</HTML>
HTML code

##### Blank print statement
print "";
 
Note that when the script runs for the first time, because no button has been pressed then the if statements are ignored and just the form is printed.
 
Only thing I would suggest is moving your headers to the top of the script so that if anything errors out you see the errors and not get a 500 error code.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those who say it cannot be done are usually interrupted by someone else doing it; Give the wrong symptoms, get the wrong solutions;
 
How can I call different functions (in different buttons) ?

This is the basis of all CGI scripts unless they do only one thing. The best practice is to make a dispatch table (a hash) that uses the various form widgets to know which function to call:

Code:
my %functions = (
   'Upload Image' => \&upload_function,
   'Write Text' => \&text_function,
);

my $command = param('commad');
$functions{$command}->() or die "Invalid command\n";

sub upload_function {
   ....
}
sub text_function {
   ...
}

in your form all your "command" buttons have the same name but a different value:

Code:
<input type="submt" name="command" value="Upload Image">
<input type="submt" name="command" value="Write Text">

The value is the name of the hash key that tells the script what to do. The form field could be any form widget named "command", it does not have to be a submit button. Often there is a hidden form field that tells the script what to do with the data sent to it. I do that myself and give the form widget a simple numbering system:

Code:
<form input type="hidden" name="command" value="1">

the form is sent and the scripts gets the value of the "command" widgt and uses the dispatch table to call a function.

Code:
my %functions = (
   1 => \&foo,
   2 => \&foobar,
   3 => \&bar,
   etc
   etc
   etc
);

my $command = param('command');
$functions{$command}->() or die "Invalid command\n";

this way you use generic submit buttons that have no real purpose in the script, they just send the data.






------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Kevin,

Thats a real neat way to call a function. I will also bare that in mind for future scripts.

Chris
 
Ok. I'm little bit lost now.

Let me describe exactly what I am trying to do.

I have form where I have 3 buttons and one textarea and one filefield

I'll try to draw the form:
Code:
Choose filename or write it |--filefield--| [browse-button]
[savePicture-button]

|              |
|---textarea---|
|              |

[execute-button]


So when user has browse the picture and then user push the savePicture button will do next:

1. We save the picture to the folder /tmp
2. We add filename to the @table.

So, now the user has add (example 3) pictures.
Now user writes some text to the textarea.
and then user push execute button, which cause next:

1. We write @table content to the file which locates in /tmp folder.

OR if user dont add any pictures but only text that would do fine.

So now my code looks like this, and I cant get this working.
I get error text: Undefined subroutine &main::param called at / line 53.

Code:
#!/usr/bin/perl -wT
#   use strict;
    use warnings;
    use CGI;
    use CGI::Carp qw(fatalsToBrowser);    

$CGI::POST_MAX = 1024 * 100;  # maximum upload filesize is 100K

my $query = new CGI;

print $query->header;
print $query->hr;
print $query->start_html(
			 -title => "File upload web page",
			 );

print $query->h3('Upload a local file to the web server'),
    $query->start_multipart_form(
				 -name => 'main_form'
				 );

print 'Enter a filename, or click on the browse button to choos one: ',
    $query->filefield(
		      -name => 'filename',
		      -size => 50,
		      -maxlength => 80
		      );
print "<br /><br />";
print $query->submit(-value => 'Upload the file');
print $query->hr;

print "<br /><br />";
print $query->hr;
print 'Enter text message: ',
    $query->textarea(
		      -name => 'text',
		      -size => 400,
		      -maxlength => 1024
		      );

print $query->submit(-value => 'Write text');
print $query->hr;
print $query->end_form;

# Code Below causes the error message:

my %functions = (
   'Upload Image' => \&upload_file,
   'Write Text' => \&write_text,
);

$query = param('Upload the file');
$functions{$query}->() or die "Invalid command\n";

 sub upload_file($) {


       my ($q) = @_;
        my ($bytesread, $buffer);
        my $num_bytes = 1024;
        my $totalbytes;
        my $filename = $q->upload('filename');
        my $untainted_filename;



   my $file = "/tmp/$untainted_filename";

        print "Uploading $filename to $file<BR>";

        open (OUTFILE, ">", "$file") or die "Couldn't open $file for writing: $!";

        while ($bytesread = read($filename, $buffer, $num_bytes)) {
            $totalbytes += $bytesread;
            print OUTFILE $buffer;
        }
        die "Read failure" unless defined($bytesread);
        unless (defined($totalbytes)) {
            print "<p>Error: Could not read file ${untainted_filename}, ";
            print "or the file was zero length.";
        } else {
            print "<p>Done. File $filename uploaded to $file ($totalbytes bytes)";
        }
        close OUTFILE or die "Couldn't close $file: $!";

}


 sub write_text($) {

         #Here we will write content of @table to the file 

}


I know my code is poor, but I would like to hear some advices, how you would do this kind of script ?

I haven't code cgi ever before.
 
There is no hash key named "Upload the file":

Code:
my %functions = (
   'Upload Image' => \&upload_file,
   'Write Text' => \&write_text,
);

$query = param('Upload the file');

You need to add that to the hash and point it to the function it is a reference to.

Also, stop doing this:

Code:
sub upload_file($) {

that is called a prototype when you add parenthesis after the function name. Call the functions without any parenthesis:

Code:
sub upload_file {

there is no need to use prototypes and it may cause problems down the road.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top