views:

402

answers:

5

I have a PHP script that creates other PHP files based on user input. Basically, there are files containing language specific constants (define) that can be translated by the user. In order to avoid runtime errors, I want to test newly written files for parse errors (due to "unusual" character sequences). I have read several posts here on SO (like http://stackoverflow.com/questions/1255230/php-include-files-with-parse-errors) and tried a function that uses

$output = exec("php -l $filename");

to determine whether a file parses correctly. This works perfectly on my local machine, but at on the provider's machine, the output of calls to exec("php ...") seems to be always empty. I tried a call to ls and it gives me output, leading me to the assumption that PHP is somehow configured to not react to command line invocations or so. Does anyone know a way around this?

EDIT: I forgot to mention, I had already tried shell_exec and it gives no result, either. In response to sganesh's answer: I had tried that too, sorry I forgot to mention. However, the output (second argument) will always be an empty array, and the return value will always be 127, no matter if the PHP file to test has syntax errors or not.

+2  A: 

You can try with exec second and third arguments. second argument will have the output of the command. third argument will have the return value.

And exec will return only last line of the command.

$filename = "a.php";
$output = exec("php -l $filename",$op,$ret_val);
print $output."\n";
print $ret_val."\n";
var_dump($op);
sganesh
What is `$p`, did you mean `$op`?
Anthony Forloney
Yeah. I missed 'o' in that.It is $op only.
sganesh
+1  A: 

By executing shell_exec(), you can see the output as if you executed that file via command line. You can just see if there is an error right here.

<?php
if (strpos(shell_exec('php -l file.php'), 'Syntax Error')) {
    die('An error!');
}

There may also be a possibility that shell_exec() or exec() may be disable by your host.

Sean Fisher
If `shell_exec()` or `exec()` were disabled, I would not be able to perform `exec("ls /")` successfully.
Tom Bartel
+1  A: 

Hi Tom,

Nice idea to check the file validity :-)!

Now, from the PHP manual for exec():

Note: When safe mode is enabled, you can only execute files within the safe_mode_exec_dir. For practical reasons, it is currently not allowed to have components in the path to the executable.

Can you check if this is not the case for you?

Also, can you check by providing the full path of the PHP interpreter in the exec() instead of only php. Let me know how you fare.

Pinaki

pinaki
Hi pinaki, thanks for your answer. `phpinfo()` for the site in question gives me `safe_mode = Off` (both local and master value) and `safe_mode_exec_dir = no value` (again, both local and master). That's strange. Good idea to check that, though, I should have read the manual more carefully. As for the full path of PHP, I tried to find that out wich `exec("which php")`, but that returned nothing.
Tom Bartel
Hi Tom,Just have a doubt that the filename might be relative here causing the issue. Can you try a static filename (for e.g. /var/www/index.php) with the complete system path and check the output?--Pinaki
pinaki
You mean the PHP file to be checked? Oh yeah, I tried that. In fact, I'm running it with absolute pathnames right now, and it doesn't make any difference. Thanks.
Tom Bartel
Hi pinaki, I found a different way for accomplishing the parse test, in case you are interested.
Tom Bartel
Hi Tom, saw your solution. cant say i like it as much (security concerns). if the file format is fixed (only for defining constants), then i would suggest using a red-ex to validate. Let me know if you need help on this.
pinaki
Yeah I know, neither do I. What exactly do you mean by "red-ex"?
Tom Bartel
A: 

I worked around my original problem by using a different method. Here is what I do now:

  1. Write a temporary file with contents <?php include "< File to test >"; echo "OK"; ?>
  2. Generate the correct URL for the temporary file
  3. Perform HTTP request with this URL
  4. Check if result equals "OK". If yes, the file to test parses without errors.
  5. Delete temporary file

Maybe this could be done without the temporary file by issuing an HTTP request to the file to test directly. However, if there is a parse error and errors are suppressed, the output will be empty and not discernible from the output in the case of a file that gives no parse errors. This method is risky because the file is actually executed instead of just checked. In my case, there is only a limited number of users who have access to this functionality in the first place. Still, I'm naturally not entirely happy with it.

Why the exec() approach did not work, I still do not know exactly. pinaki might be right by suggesting to provide the full path to the PHP executable, but I cannot find out the full path.

Thank you everyone for answering, I upvoted you all. However, I cannot accept any of your answers as none of your suggestions really solved my problem.

Tom Bartel
A: 

@Bartel have u checked whether u have installed php-cli (php command line module) on server. This may be one reason of not able to run php from command line. hence exec() call.

Kamlesh Bhure