note 80878 added to function.php-check-syntax
| From: | matt dot nospam at pryor dot org dot uk | Date: | Tue, 05 Feb 2008 13:35:55 +0000 |
| Subject: | note 80878 added to function.php-check-syntax | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-135789@lists.php.net to get a copy of this message | ||
While developing an app where I have to include PHP files written by a user, I came across the
following problem:
I used "php -l somefile.php" to check the syntax of the file I was about to include and if
it passed, I would include it - so far so good. But in some test cases, the file I was including
would have other includes/requires inside it. If one of these was invalid, then I would still get
the parse error that I was trying to avoid.
I got round it using this:
<?php
function CheckSyntax($fileName, $checkIncludes = true)
{
// If it is not a file or we can't read it throw an exception
if(!is_file($fileName) || !is_readable($fileName))
throw new Exception("Cannot read file ".$fileName);
// Sort out the formatting of the filename
$fileName = realpath($fileName);
// Get the shell output from the syntax check command
$output = shell_exec('php -l "'.$fileName.'"');
// Try to find the parse error text and chop it off
$syntaxError = preg_replace("/Errors parsing.*$/", "", $output, -1,
$count);
// If the error text above was matched, throw an exception containing the syntax error
if($count > 0)
throw new Exception(trim($syntaxError));
// If we are going to check the files includes
if($checkIncludes)
{
foreach(GetIncludes($fileName) as $include)
{
// Check the syntax for each include
CheckSyntax($include);
}
}
}
function GetIncludes($fileName)
{
// NOTE that any file coming into this function has already passed the syntax check, so
// we can assume things like proper line terminations
$includes = array();
// Get the directory name of the file so we can prepend it to relative paths
$dir = dirname($fileName);
// Split the contents of $fileName about requires and includes
// We need to slice off the first element since that is the text up to the first
include/require
$requireSplit = array_slice(preg_split('/require|include/i',
file_get_contents($fileName)), 1);
// For each match
foreach($requireSplit as $string)
{
// Substring up to the end of the first line, i.e. the line that the require is on
$string = substr($string, 0, strpos($string, ";"));
// If the line contains a reference to a variable, then we cannot analyse it
// so skip this iteration
if(strpos($string, "$") !== false)
continue;
// Split the string about single and double quotes
$quoteSplit = preg_split('/[\'"]/', $string);
// The value of the include is the second element of the array
// Putting this in an if statement enforces the presence of '' or ""
somewhere in the include
// includes with any kind of run-time variable in have been excluded earlier
// this just leaves includes with constants in, which we can't do much about
if($include = $quoteSplit[1])
{
// If the path is not absolute, add the dir and separator
// Then call realpath to chop out extra separators
if(strpos($include, ':') === FALSE)
$include = realpath($dir.DIRECTORY_SEPARATOR.$include);
array_push($includes, $include);
}
}
return $includes;
}
?>
This checks as many of the includes inside the file as it possibly can without executing anything.
----
Server IP: 87.124.64.96
Probable Submitter: 138.38.249.188
----
Manual Page -- http://www.php.net/manual/en/function.php-check-syntax.php
Edit -- https://master.php.net/note/edit/80878
Del: integrated -- https://master.php.net/note/delete/80878/integrated
Del: useless -- https://master.php.net/note/delete/80878/useless
Del: bad code -- https://master.php.net/note/delete/80878/bad+code
Del: spam -- https://master.php.net/note/delete/80878/spam
Del: non-english -- https://master.php.net/note/delete/80878/non-english
Del: in docs -- https://master.php.net/note/delete/80878/in+docs
Del: other reasons-- https://master.php.net/note/delete/80878
Reject -- https://master.php.net/note/reject/80878
Search -- https://master.php.net/manage/user-notes.php