upload file and run bash application on file

awesomefennis
awesomefennis used Ask the Experts™
on
Hello,

I have an apache web server (on Ubuntu) that is running perl, and i would like to do the following. I would like an upload file functionality on the site, which once a user has uploaded a file to the webserver, an bash shell application is launched once the file is uploaded and the bash shell responses are displayed in the browser.

So I have the upload functionality upload.cgi, at the end of which I have put a command:
`progname -f /var/www/$filename -t /path to other folder/`;

Is it ok to run the bash command simply using ` `, or do i need to use the system() command?
I am assuming this will run progname in the background using the newly uploaded $filename, as if i had typed it in as bash shell .

I would like to display the responses of the bash shell in the browser.

Is this possible? How would it be done?

I have included the full code of upload.cgi below.
#!/usr/bin/perl -w
 
use strict;
use CGI;
use CGI::Carp qw ( fatalsToBrowser );
use File::Basename;
 
$CGI::POST_MAX = 1024 * 5000;
my $safe_filename_characters = "a-zA-Z0-9_.-";
my $upload_dir = "/var/www/";
 
my $query = new CGI;
my $filename = $query->param("photo");
 
if ( !$filename )
{
 print $query->header ( );
 print "There was a problem uploading your photo (try a smaller file).";
 exit;
}
 
my ( $name, $path, $extension ) = fileparse ( $filename, '\..*' );
$filename = $name . $extension;
$filename =~ tr/ /_/;
$filename =~ s/[^$safe_filename_characters]//g;
 
if ( $filename =~ /^([$safe_filename_characters]+)$/ )
{
 $filename = $1;
}
else
{
 die "Filename contains invalid characters";
}
 
my $upload_filehandle = $query->upload("photo");
 
open ( UPLOADFILE, ">$upload_dir/$filename" ) or die "$!";
binmode UPLOADFILE;
 
while ( <$upload_filehandle> )
{
 print UPLOADFILE;
}
 
close UPLOADFILE;
 
 
`progname -f /var/www/$filename -t /path to other folder/`;
 
 
print $query->header ( );
print <<END_HTML;
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   <title>Thanks!</title>
   <style type="text/css">
     img {border: none;}
   </style>
 </head>
 <body>
   <p>Thanks for uploading your file!</p>
 </body>
</html>
END_HTML

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

You have options with regard to calling your bash script.  A good page to bookmark as a reference is the 'perlipc' man page.  

Below, I show an example of using a pipe and the perl builtin 'open'.

Although, you could alternatively use just the back ticks and capture everything in an array, like this:

my @bash_output = `progname -f /var/www/$filename -t /path to other folder/`;
foreach my $line (@bash_output) {    #Process output here...}

However, if the bash script returns a huge amount of stuff, you might wind up with a huge array.  


Using the pipe approach gives you the opportunity to deal with the bash commands output 1 line at a time, and bail out, if you decide that is the thing to do...


David



#!/usr/bin/perl -w
 
use strict;
use CGI;
use CGI::Carp qw ( fatalsToBrowser );
use File::Basename;
 
$CGI::POST_MAX = 1024 * 5000;
my $safe_filename_characters = "a-zA-Z0-9_.-";
my $upload_dir = "/var/www/";
 
my $query = new CGI;
my $filename = $query->param("photo");
 
if ( !$filename ) {
    print $query->header ( );
    print "There was a problem uploading your photo (try a smaller file).";
    exit;
}
 
my ( $name, $path, $extension ) = fileparse ( $filename, '\..*' );
$filename = $name . $extension;
$filename =~ tr/ /_/;
$filename =~ s/[^$safe_filename_characters]//g;
 
if ( $filename =~ /^([$safe_filename_characters]+)$/ ) {
    $filename = $1;
}
else {
    die "Filename contains invalid characters";
}
 
my $upload_filehandle = $query->upload("photo");
 
open ( UPLOADFILE, ">$upload_dir/$filename" ) or die "$!";
binmode UPLOADFILE;
 
while ( <$upload_filehandle> ) {
    print UPLOADFILE;
}
 
close UPLOADFILE;
 
 
my $bash_command = "progname -f /var/www/$filename -t /path to other folder/";
 
open my $bash_command_output_pipe_fh, "$bash_command |"
    or croak "Could not execute DNSCMD Command: '$bash_command'";
 
my $bash_output;
LINE: while (my $line = <$bash_command_output_pipe_fh>) {
    chomp $line;
    
    # Process / convert / play with line of output here...
    # Perhaps we add back a newline to the end, or <br>'s or format it for HTML
    # Tables, etc...
    
    my $processed_line = '<p>' . $line . '<p>';
    
    
    # And when ready, tack place it in a var to print later
    $bash_output .= $processed_line;
}
 
 
print $query->header ( );
 
print <<END_HTML;
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   <title>Thanks!</title>
   <style type="text/css">
     img {border: none;}
   </style>
 </head>
 <body>
   <p>Thanks for uploading your file!</p>
   
   <p>The Unix Bash Shell Returned:</p>
   $bash_output
   
   
 </body>
</html>
END_HTML

Open in new window

And, yes, there was a copy/paste typo in my code...

david

# This:
open my $bash_command_output_pipe_fh, "$bash_command |"
    or croak "Could not execute DNSCMD Command: '$bash_command'";
 
# Should have been:
open my $bash_command_output_pipe_fh, "$bash_command |"
    or croak "Could not execute Bash Command: '$bash_command'";

Open in new window

Author

Commented:
Great and quick response....thanks very much.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial