Correl Roush
fc258c4230
git-svn-id: file:///srv/svn/scanner/trunk@7 a0501263-5b7a-4423-a8ba-1edf086583e7
157 lines
5.6 KiB
PHP
157 lines
5.6 KiB
PHP
<?php
|
|
$FunctionsModule_functions = array();
|
|
$FunctionsModule_local_functions = array();
|
|
$FunctionsModule_file = '';
|
|
$FunctionsModule_instance = new FunctionsModule();
|
|
|
|
function FunctionsModule_callback_global( $object ) {
|
|
global $FunctionsModule_functions, $FunctionsModule_file;
|
|
$FunctionsModule_functions[$object['name']] = array(
|
|
'used' => 0,
|
|
'file' => $FunctionsModule_file
|
|
);
|
|
}
|
|
function FunctionsModule_callback_local( $object ) {
|
|
global $FunctionsModule_local_functions, $FunctionsModule_file;
|
|
$file = $FunctionsModule_file;
|
|
if( !isset( $FunctionsModule_local_functions[$file] ) ) {
|
|
$FunctionsModule_local_functions[$file] = array();
|
|
}
|
|
$FunctionsModule_local_functions[$file][strtolower( $object['name'] )] = array(
|
|
'used' => 0,
|
|
'file' => $object['file']
|
|
);
|
|
}
|
|
|
|
class FunctionsModule extends ScannerModule {
|
|
var $include_paths;
|
|
var $internal_functions;
|
|
var $included_files;
|
|
|
|
function FunctionsModule() {
|
|
$this->ScannerModule();
|
|
// Preload library function declarations
|
|
$library_folders = array(
|
|
'libs',
|
|
'inc',
|
|
'incs',
|
|
'includes'
|
|
);
|
|
global $base_path;
|
|
$parser = new PHPParser( PHPPARSER_FETCH_FUNCTIONS );
|
|
$parser->registerCallback( 'FunctionsModule_callback_global' );
|
|
//$parser->registerCallback( 'FunctionsModule_callback_local' );
|
|
$this->include_paths = array();
|
|
$paths = array();
|
|
$path = realpath( $base_path );
|
|
if( !in_array( $path, $paths ) ) {
|
|
$paths[] = $path;
|
|
$contents = scandir( $path );
|
|
foreach( $contents as $node ) {
|
|
if(
|
|
is_dir( "$path/$node" )
|
|
&& in_array( strtolower( $node ), $library_folders )
|
|
&& !in_array( "$path/$node", $this->include_paths )
|
|
) {
|
|
$this->include_paths[] = "$path/$node";
|
|
}
|
|
}
|
|
}
|
|
$include_files = array();
|
|
$functions = array();
|
|
foreach( $this->include_paths as $path ) {
|
|
exec( "find $path -iname '*.php' 2>/dev/null", $output, $result );
|
|
$include_files = array_merge( $include_files, $output );
|
|
}
|
|
err( "Parsing function libraries...\n" );
|
|
$counter = 0; $total = count( $include_files ); $lastpct = 0;
|
|
foreach( $include_files as $file ) {
|
|
$counter++;
|
|
if( $counter == 1 ) { err( 0 ); }
|
|
else {
|
|
$pct = intval( $counter / $total * 100 );
|
|
if( $pct != $lastpct && $pct % 2 == 0 ) {
|
|
err( $pct % 10 == 0 ? $pct : '.' );
|
|
$lastpct = $pct;
|
|
}
|
|
}
|
|
$parser->parseFile( $file );
|
|
}
|
|
err( "\n" );
|
|
$this->internal_functions = get_defined_functions();
|
|
$this->internal_functions = $this->internal_functions['internal'];
|
|
}
|
|
function parserCallback( $object ) {
|
|
global $FunctionsModule_functions;
|
|
global $FunctionsModule_local_functions;
|
|
global $FunctionsModule_file;
|
|
|
|
$FunctionsModule_file = filename( $object['file'] );
|
|
switch( $object['type'] ) {
|
|
case PHPPARSER_INCLUDE:
|
|
$this->included_files[] = $object;
|
|
if( $object['name'] == 'global.php' ) {
|
|
$object['name'] = 'libs/security/lib_security_input.php';
|
|
$this->included_files[] = $object;
|
|
$object['name'] = 'libs/get/lib_get_portal.php';
|
|
$this->included_files[] = $object;
|
|
$object['name'] = 'libs/logging/lib_logging_errors.php';
|
|
$this->included_files[] = $object;
|
|
}
|
|
break;
|
|
case PHPPARSER_FUNCTION_CALL:
|
|
if( !in_array( $object['name'], array_keys( $FunctionsModule_functions ) ) ) {
|
|
if(
|
|
!in_array( $object['name'], $this->internal_functions )
|
|
&& !in_array( $object['name'], array_keys( $FunctionsModule_local_functions[filename( $object['file'] )] ) )
|
|
) {
|
|
$this->fault( $object, FAULT_MAJOR, "Undefined function '{$object['name']}'" );
|
|
}
|
|
continue;
|
|
}
|
|
|
|
$include = filename( $FunctionsModule_functions[$object['name']]['file'] );
|
|
if( $include != filename( $object['file'] ) ) {
|
|
//$functions[$object['name']]['used']++;
|
|
//if( !isset( $file_requires[$file]['libs'][$include] ) ) { $file_requires[$file]['libs'][$include] = array( 'lines' => array(), 'calls' => array() ); }
|
|
//$lib =& $file_requires[$file]['libs'][$include];
|
|
|
|
$bad = $warning = true;
|
|
foreach( $this->included_files as $libinc ) {
|
|
if( $libinc['name'] != $include || !in_array( $libinc['in_function'], array( '', $object['in_function'] ) ) ) { continue; }
|
|
$inc = $libinc;
|
|
$bad = false;
|
|
$warning = !$bad && !in_array( $libinc['block'], $object['open_blocks'] );
|
|
if( !$bad && !$warning ) { break; }
|
|
}
|
|
$open_blocks = is_array( $object['open_blocks'] ) ? implode( ',', $object['open_blocks'] ) : '';
|
|
$info = "called[l={$object['line']};b={$object['block']};d={$object['depth']}]" . ( !$bad ? ", required[l={$inc['line']};b={$inc['block']};d={$inc['depth']}] open[{$open_blocks}]" : '' );
|
|
if( $bad === true ) {
|
|
$this->fault( $object, FAULT_MAJOR, "Undefined function '{$object['name']}' $info" );
|
|
} elseif( $warning === true ) {
|
|
$this->fault( $object, FAULT_MEDIUM, "Potentially undefined function '{$object['name']}' $info" );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
function preScan( $file ) {
|
|
parent::preScan( $file );
|
|
global $FunctionsModule_local_functions, $FunctionsModule_file;
|
|
$FunctionsModule_file = filename( $file['filename'] );
|
|
$FunctionsModule_local_functions = array();
|
|
$FunctionsModule_local_functions[filename( $file['filename'] )] = array();
|
|
$parser = new PHPParser( PHPPARSER_FETCH_FUNCTIONS );
|
|
$parser->registerCallback( 'FunctionsModule_callback_local' );
|
|
if( $file['revision'] > 0 ) {
|
|
$file_contents = isset( $file['contents'] ) ? $file['contents'] : shell_exec( "svn cat -r {$file['revision']} {$svn_root}{$svn_base}/{$file['filename']} 2>/dev/null" );
|
|
$parser->parse( $file_contents );
|
|
} else {
|
|
$parser->parseFile( $file['filename'] );
|
|
}
|
|
$this->included_files = array();
|
|
}
|
|
}
|
|
|
|
addModule( $FunctionsModule_instance );
|
|
?>
|