Wrapping Perl with PHP

Wednesday, 9 October 2008 - Jochen Lüll
perlwrapper
PHP Perl Wrapper
A lot of low cost hosting solutions have only PHP support and don't support Perl CGI scripts.
Although PHP is good for creating web pages it might be sometimes desirable to use Perl scripts.
This articles shows how to write an PHP to Perl wrapper to supper Per CGI scripts for web hosting solutions on which only PHP is supported.



A
lthough Perl CGI scripts are not officially supported, most ISPs using Unix based servers will have Perl installed on there systems.
If this is the case and PHP is support for creating web pages, the wrapper which we will develop can be used.

One thing first. I'm not a PHP developer and this is one of the first PHP scripts I've written so far. So the script is far from being perfect and has some limitations (see box on the right). But for simple Perl scripts it should be sufficient.

 

The Script

Limitations
Wrapper Limitations
The wrapper script performs the following tasks:

The script is called in the following way: perlwrapper.php?cgi=<name of script>[&debug=1]

The debug parameter is optional and prints the content of the stderr output instead of a "500 Internal Server Error" message.


<?php
/* PERL CGI WRAPPER PHP SCRIPT */
/* Note: Does not handle "multipart/form-data" */

/* Populate $HTTP_RAW_POST_DATA if not available */
if (!isset($HTTP_RAW_POST_DATA)){
    
$HTTP_RAW_POST_DATA file_get_contents('php://input');
}


/* A little bit of security */
$cgi str_replace(".."""$cgi);

$command "perl ./" $cgi;
$io = array();
$p proc_open($command,
               array(
               
=> array('pipe''r'),
               
=> array('pipe''w'),
               
=> array('pipe''w')),
               
$io);

/* Write the raw POST data to the pipe */
fwrite($io[0], $HTTP_RAW_POST_DATA);
fclose($io[0]);


/* Read output sent to stdout. */
while (!feof($io[1])) {
    
$stdout .= fgets($io[1]);  
}

/* Extract header section */
preg_match('/^(.*?)[\n]{2}(.*)$/s'$stdout$regs);
        
/* Set HTTP headers */
$headers preg_split("/[\n]/"$regs[1]);
foreach (
$headers as $header) {
    
header($header);
}
    
$stdout $regs[2];

echo 
$stdout;
/* Read output sent to stderr. */
while (!feof($io[2])) {
    
$stderr .= fgets($io[2]);
}


/* Close handles */            
fclose($io[1]);
fclose($io[2]);
$exit proc_close($p);


/* Set HTTP status code to 500 if an error occured */
if($exit != && !isset($debug)) {
    
header(getenv("HOME") . " 500 Internal Server Error");
}
else if(
$exit != 0) {
    print 
$stderr;
}

?> 


Source Code of perlwrapper.php



Adjusting Perl Scripts

Normally the Perl scripts should run out of the box.
In some cases the bellow errors might occur.

Insecure $ENV{PATH} while running with ...

Sometimes the following error might occur: "Insecure $ENV{PATH} while running with ..."
To avoid this error message add the following lines to the start of your script:

# To prevent: "Insecure $ENV{PATH} while running with ..."
$ENV{'PATH'} =~ /(.*)/; $ENV{'PATH'} = $1;

Perl Script adjustment (1)

Insecure dependency in require while running setgid at ...

If you get the error message "Insecure dependency in require while running setgid at ...", add the parameters -wU to the Perl call in perlwrapper.php.

$command "perl -wU ./" $cgi;
Perl Script adjustment (2)


Demos

Visit the demo page, if you would like to see the wrapper in action.



Hope this article is useful ... have fun! Face smile
(joschi)

Version: 0.1
Author's e-Mail address: jochen [at] fun2code.de

 
Valid HTML 4.01 Transitional  Creative Commons License
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.