The Problem:
I want to take some data that is generated within a PHP script (a simple string 'dirTemp' which holds an absolute directory path) and make it available to a separate Perl script.
I don't want to hard-code any paths in either of the scripts because (a) most data is generated on the fly, and (b) I want to make installation of these scripts as simple as possible (i.e. minimal configuration).
My development machine is WAMP and remote hosting server is LAMP.

Considered Solutions:
1. Setting 'dirTemp' in a Cookie
This works great, but with one major drawback - security! Apart from giving potential hackers an insight into my directory structure, cookies can be very easily spoofed so would cause some havoc within the target perl script.

2. Storing 'dirTemp' in the Session, then using "PHP::Session" Perl module to read it
This seems like a more secure solution, but the Perl scripts still needs to know the session 'save_path', so we get back to square one - needing to send a directory path to Perl! The system I'm developing also uses custom Session handlers (D😎 and PHP::Session currently only supports file-based sessions.

3. Setting an environment variable in PHP so Perl can read it
On my windows machine, PHP generates a "tmp" environment variable, but Perl doesn't. The languages don't seem to have any directory environment variable in common. If they did, this would be great as I could create a file based on a unique ID in that "tmp" directory, then simply pass the ID to perl via a cookie (this would be safe).
So I've tried using "putenv()" and "apache_setenv()" to set the environment variable in PHP, but they don't become available to the Perl script.

So, none of the solutions I've come up with so far cut the mustard. Of the three I think the environment variables would be the simplest and neatest way around it, and possibly the Apache "SetEnv" directive may help, but before I delve into Apache (with which I'm very clumsy) I'd like to exhaust other solutions.

Hopefully someone out there can point out what's missing and solve this little conundrum in one fell swoop! 🙂

    Why don't you just store the data in a database which both scripts can read/write? I know you wanted to keep things simple but you've already mentioned that you use a database for storing sessions.

      Yes, a good idea, but ...

      In order to access the database you need to specify a username/password/dbname/port - all of which are currently stored in an XML file in a sub-docroot folder that the PHP script can read and knows the location of, but Perl doesn't.

      To explain a bit better, here's the layout of my scripts:

      [FONT=Courier New]/public_html/init.php[/FONT] - a PHP script that is included by all other scripts to do some initializing
      [FONT=Courier New]/public_html/inc/config.xml[/FONT] - defines where to find the DB XML file amongst other things (hidden from browser using .htaccess controls)
      [FONT=Courier New]/cgi-bin/action.pl[/FONT] - The Perl script that is called in the browser separately.

      The "init.php" script can easily find the "config.xml" file because it will always be in the "/inc/" folder relative to "init.php"'s location (I use "dirname(FILE)" here).

      Now I could just as easily open "config.xml" from the Perl script "action.pl" by assuming that it's location is relative (i.e. "../public_html/inc/config.xml"), but as my wife keeps telling me, "never assume because it makes an ass out of u and me!".....I don't want to assume, because the server on which this system is installed may not have the "cgi-bin" folder in the same relative location, and the doc-root folder may not be called "public_html".

      Also, to make things a little harder, all the sites on the server use the very same Perl script (from the exact same location), but each have different document roots! So the relative path wouldn't work anyway.

      I suppose one way would be to create a "tmp" DB which has fixed access details (different to those set in the XML file) and I hard-code these details into the scripts. One main drawback to this is that all sites would have to use the same DB table, which could result in security breaches.

      Anyway, I'll investigate this route and see how it goes 🙂

      Thanks.

        Any possibility that action.pl can read config.xml from standard input? If yeah, then one option would appear to be to use a system call from PHP with config.xml as a commandline argument to the Perl script. Assuming that perl is in the usual search path you wouldn't need its absolute pathname.

          So you mean use PHP as a wrapper for the Perl script? Something like ...

          <?php
          $cmd = dirname(__FILE__).'/action.pl';
          exec("perl $cmd /path/to/config.xml");
          ?>

          ... and call this via "http://www.somedomain.net/cgi-bin/wrapper.php"?

          I'm using a kind of "virtual hosting via PHP" setup on the server, whereby all sites pull core scripts from the same directories, but have site-specific folders (determined by the "SERVER_NAME" environment variable) to deliver site content. So, the above script will need a little bit of system-specific code to determine where to find the "/path/to/config.xml", but this will be a lot easier to do in PHP than Perl.

          I think if I'd had a "normal" setup, then it would've been simple to use the "DOCUMENT_ROOT" environment variable in some manner as both PHP and Perl appear to define this by default.

          Thanks for the ideas! 🙂

            mmm, one major flaw with this wrapper approach...

            The Perl script is initiated via a form action submitted using the POST header. The Perl script needs access to the raw POST data so a wrapper cannot be used! I should've pointed this out in the first place.

            Any other suggestions?

              /Weedpacket smacks a palm to his forehead. "He said cgi-bin, didn't he?"

              Okay: this isn't the most elegant of solutions because it requires an extra http transaction - but if that's what the Perl script wants we might as well give it one 🙂

              Basically, your PHP script acts as a web client, builds a POST request and submits it to the Perl script. The URL you submit to would be the same one that some random somewhere would use to communicate to the Perl script directly ("http://www.example.com/yadayada"). The Perl script receives it, processes it, and sends its response back to your PHP script. The URL could be built from bits of the $_SERVER array to maintain portability and minimise hardwiring.

              Simple way would be to use the [man]cURL[/man] extension, because that will handle all the http protocol stuff, request formatting and so on. Or you could build the request yourself and use [man]fsockopen[/man] to create an http connection you can write to and read from.

                This would mean the PHP script would have to gather all the POST data (which contains file uploads) from the submitted form before it can begin to open a connection to the Perl script. If the form contains a few megs of data, then it will take a while for the PHP script to gather all that data into it's $_POST hash before then calling the Perl script.

                Whilst this solution would certainly work, the timing of the form submission is key to this Perl script (again, something I should perhaps have mentioned before 🙂 ) because it needs to immediately start reading the STDIN from the http request generated by the form submission.

                Basically, I'm using the "Mega Upload" Perls scripts as provided by http://www.raditha.com/php/progress.php - with a few minor modifications to work within my own system.

                This fancy little script reads the raw POST data via STDIN and as it does so, creates progress files that can be read from an external script that generates a progress bar from that info. If PHP could start reading from STDIN straight away before packing everything away into the $POST/$FILES hashes then I could've written a PHP equivalent, but as far I can find this just isn't supported (not via "php://stdin", "php://input" or "$HTTP_RAW_POST")

                So, at the moment I'm using Apache's "SetEnv" directive to ensure that an environment variable is created that both Perl and PHP can read. This is placed at the bottom of "httpd.conf", which means it sets this variable for every site ...

                ...
                SetEnv MY_TMP_DIR /tmp
                ...

                ... but I suppose you could just as easily place it in the "<VirtualHost ... />" blocks to create a variable that only exists for that host, or in an ".htaccess" file.

                This then makes $ENV{'MY_TMP_DIR'} available to Perl, and $_SERVER['MY_TMP_DIR'] available to PHP - perfect!

                In the end this is an Apache solution rather than a PHP one, and although the other solutions you've mentioned would work well in other circumstances, this is the only way I can currently think of for my (very exact) requirements!

                Thanks again 🙂

                  Write a Reply...