0, 'file' => $object['file'] ); } function FunctionsModule_callback_local( $object ) { global $FunctionsModule_local_functions; $file = filename( $object['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; 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( $filename ) { parent::preScan( $filename ); global $FunctionsModule_local_functions; $FunctionsModule_local_functions = array(); $FunctionsModule_local_functions[filename( $filename)] = array(); $parser = new PHPParser( PHPPARSER_FETCH_FUNCTIONS ); $parser->registerCallback( 'FunctionsModule_callback_local' ); $parser->parseFile( $filename ); $this->included_files = array(); } } $modules[] = $FunctionsModule_instance; ?>