0, 'file' => $object['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 ); foreach( $include_files as $file ) { $counter++; scan_progress( $counter, $total, 'Scanning Function Libraries [%d/%d]' ); $parser->parseFile( $file ); } $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']}'", true ); } 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", true ); } elseif( $warning === true ) { $this->fault( $object, FAULT_MEDIUM, "Potentially undefined function '{$object['name']}' $info", true ); } } 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 ); ?>