Created
February 3, 2017 20:53
-
-
Save apokalyptik/53ffa152ad5a9f9b1730ab849c5d2413 to your computer and use it in GitHub Desktop.
Revisions
-
apokalyptik created this gist
Feb 3, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,169 @@ #!/usr/bin/env php <?php define( 'DEBUG_RECURSION', false ); if ( $_SERVER['argc'] > 1 ) { if ( substr( $_SERVER['argv'][1], 0, 1 ) !== "/" ) { define( 'FUNCTION_MATCH', "/" . preg_quote( $_SERVER['argv'][1] ) . "/" ); } else { define( 'FUNCTION_MATCH', $_SERVER['argv'][1] ); } } else { die( "Usage: " . $_SERVER['argv'][0] . " function_pattern [scan_path]\n" ); } if ( $_SERVER['argc'] > 2 ) { define( 'SCAN_BASE', get_real_path_to( $_SERVER['argv'][2] ) ); if ( !SCAN_BASE ) { die( $_SERVER['argv'][2] . " does not appear to be a directory...\n" ); } } else { define( 'SCAN_BASE', get_real_path_to( getcwd() ) ); } function get_real_path_to( $path ) { $path = realpath( $path ); while( is_link( $path ) ) { $path = realpath( readlink( $path ) ); } return $path; } define( 'SCAN_BASE_STRIP', strlen( SCAN_BASE ) + 1 ); function resurse_find_ext_callback( $ext, $dir, $callback ) { $base = get_real_path_to( $dir ); $d = opendir( $base ); if ( $d !== false ) { while( false !== ( $entry = readdir( $d ) ) ) { if ( in_array( $entry, array( ".", "..", ".svn", ".git" ) ) ) { if ( DEBUG_RECURSION ) fwrite( STDERR, "!valid\t$base/$entry\n" ); continue; } $new = get_real_path_to( "$base/$entry" ); if ( $new === $base ) { // Don't scan if the entry is a link to the self if ( DEBUG_RECURSION ) fwrite( STDERR, "!loop\t$new\n" ); continue; } if ( is_dir( $new ) ) { if ( strpos( $new, $base ) === 0 ) { resurse_find_ext_callback( $ext, $new, $callback ); } else { // Don't scan if we've been linked out of the current directory (eg: an nfs share of user uploads) if ( DEBUG_RECURSION ) fwrite( STDERR, "!subdir\t$base/$entry -> $new\n" ); } continue; } if ( substr( $new, strrpos( $new, "." ) ) === $ext ) { $callback( $new ); } } } else { if ( DEBUG_RECURSION ) fwrite( STDERR, "!opendir\t$d\n" ); } } function find_prev( $tokens, $from_idx ) { for( $i = $from_idx - 1; $i >= 0; $i-- ) { if ( is_string( $tokens[$i] ) ) { return $i; } else { switch( token_name( $tokens[$i][0] ) ) { case 'T_WHITESPACE': break; default: return $i; } } } return false; } function find_entire_function_call( $tokens ) { $p_depth = 0; foreach( $tokens as $idx => $token ) { if ( !is_string( $token ) ) { continue; } switch( $token ) { case '(': $p_depth++; break; case ')': $p_depth--; break; } if ( $p_depth === 0 ) { return $idx+1; } } return false; } function reconstruct( $tokens ) { $parts = array(); foreach( $tokens as $token ) { if ( is_string( $token ) ) { $parts[] = $token; } else { $parts[] = $token[1]; } } return implode( "", $parts ); } resurse_find_ext_callback( ".php", SCAN_BASE, function( $file ) { $tokens = token_get_all( file_get_contents( $file ) ); foreach( $tokens as $token_idx => $token ) { if ( is_string( $token ) ) { continue; } else { switch( token_name( $token[0] ) ) { case 'T_STRING': if ( !preg_match( FUNCTION_MATCH, $token[1] ) ) { continue; } if ( !is_string( $tokens[$token_idx+1] ) ) { continue; } if ( $tokens[$token_idx+1] !== "(" ) { continue; } $prev = find_prev( $tokens, $token_idx ); if ( $prev !== false ) { $prev = $tokens[$prev]; if ( !is_string( $prev ) && token_name( $prev[0] ) === "T_FUNCTION" ) { break; } } $len = find_entire_function_call( array_slice( $tokens, $token_idx ) ); if ( $len === false ) { printf( "Unable to determine function call end for %s in %s on line %d\n", $token[1], $file, $token[2] ); break; } printf( "%s:%d %s\n", substr( $file, SCAN_BASE_STRIP ), $token[2], str_replace( array( "\n", "\t" ), array( "\\n", "\\t" ), reconstruct( array_slice( $tokens, $token_idx, $len ) ) ) ); break; default: //printf( "%s: %s\n", token_name($token[0]), $token[1] ); } } } });