diff --git a/Globye.php b/Globye.php index bb16017..cb6ad0d 100644 --- a/Globye.php +++ b/Globye.php @@ -5,6 +5,8 @@ * @package tools * @copyright 2013 René-Gilles Deberdt, wedge.org * @license MIT + * + * Modifications 2015 by Feline, portamx.com */ /* @@ -13,9 +15,32 @@ - Remove quotes from tests, so we don't find false positives in commented-out code. */ +/* + Modifications by Feline + - if no additional option is given, only the help screen is shown. + - added option ?scan to scan all files in the current folder and his subfolder. + - added option ?file=filename to scan only the given file. + - added option ?path=path_to_scan to scan all files in the given folder and his subfolder. + - added option ?fixme to allow the script to fix all found problems exept false-positives. + In this case a backup (filename.php.timestamp) is created if any changed. + - added option ?nobackup .. uhm .. I think, you don't use this until you love high risk *g* + - added a function to stripout inline Javascript functions +*/ + $script_name = basename(__FILE__); -$root = dirname(__FILE__); +$root = $dir = $_SERVER['DOCUMENT_ROOT']; +if (isset($_GET['path'])) +{ + if (substr($_GET['path'], 0, 1) == '/') + $dir = $root . substr($_GET['path'], 1); + else + $dir = $_GET['path']; +} +$dir = $basedir = str_replace('\\', '/', $dir); +$file = (isset($_GET['file']) ? $_GET['file'] : ''); $problems = 0; +$fixes = 0; + @ini_set('xdebug.max_nesting_level', 300); if (function_exists('set_time_limit') && is_callable('set_time_limit')) // Can't be too careful with this one... @set_time_limit(300); @@ -42,6 +67,14 @@ '$scripturl', '$board_info', '$action_list', + '$language', // for SMF (forks or mainline) + '$sourcedir', // for SMF (forks or mainline) + '$themedir', // for SMF (forks or mainline) + '$themeurl', // for SMF (forks or mainline) + '$user_info', // for SMF (forks or mainline) + '$smcFunc', // for SMF (forks or mainline) + '$cachedir', // for SMF (forks or mainline) + '$maintenance', // for SMF (forks or mainline) ); echo ' @@ -55,49 +88,79 @@ .new { margin-top: 8px; } em { color: #c30; } li { padding: 3px 0 3px 8px; } - - .duplicates { background: linear-gradient(to right, #fcc, #fff 30px); } - .undeclared { background: linear-gradient(to right, #ccf, #fff 30px); } - .unused { background: linear-gradient(to right, #bea, #fff 30px); } + kbd { font-size: 17px; font-weight: bold; } + samp { font-size: 17px; font-weight: bold; } + h1 { font-size: 18px; font-weight: bold; } + .duplicates { background: linear-gradient(to right, #fcc, #fff 80px); } + .undeclared { background: linear-gradient(to right, #ccf, #fff 90px); } + .unused { background: linear-gradient(to right, #bea, #fff 65px); }

Globye.php

-
By Nao (Wedge.org)
-
+
By Nao (Wedge.org), modifications by Feline (PortaMx.com)
+
'; +if (empty($_GET)) +{ + echo '

This script will list all PHP files in the ', $root, ' folder that have duplicate, unneeded global declarations or undeclared globals. +

-

- Add ?noclean to view a quick, dirty list of results that may generate more false positives. -
- Add ?ignorefp to list only strong suspects; potential false positives will be ignored. + Add ?path=/relative or ?path=absolute to scan only the given path and his subfolder. + (Base path for relative: ' . $_SERVER['DOCUMENT_ROOT'] . ').
+ Add ?file=your_phpfile.php to allow the script to scan only the given file.
+ Add ?noclean to view a quick, dirty list of results that may generate more false positives. + (Ignored, if the fixme option is used).
+ Add ?ignorefp to list only strong suspects; potential false positives will be ignored.
+ Add ?fixme to allow the script to fix all files, except for potential false-positives. A backup (*.php.timestamp) is created if a file is modified.
+ Add ?nobackup if you don\'t make a backup if any changed during "fixme". Use this at your own risk !!!
+ If you use more then one option, use the ampersand (&) for the additional option, like path=/Sources&file=Subs.php

+ If you don\'t use any option, add ?scan to allow the script to scan all files in the current folder and all subfolder.


+ +'; + exit; +} +echo ' +

Searching: ', $dir , (isset($_GET['file']) ? '/'. $_GET['file'] : ''), '

    '; // We're just going to provide a list of global variables commonly used in Wedge. Feel free to edit to your taste... -find_global_problems($known_globals, $ignored_folders); +find_global_problems($known_globals, $ignored_folders, $dir, $file); echo '
'; if (!$problems) echo '

No problems found, congratulations!

'; else - echo '

', $problems, ' problems found, including potential false positives.

'; +{ + if(!isset($_GET['ignorefp'])) + echo '

', $problems, ' problems found, including potential false positives.
'; + else + echo '

', $problems, ' problems found.
'; + if($fixes > 0) + echo $fixes, ' problems fixed.'; + echo '

'; +} echo ' '; -function find_global_problems($real_globals = array(), $ignored_folders = array(), $dir = '') +function find_global_problems($real_globals = array(), $ignored_folders = array(), $dir = '', $file = '') { - global $root, $problems; + global $root, $problems, $fixes, $basedir; $old_file = ''; - $dir = $dir ? $dir : $root; - $files = scandir($dir); + if (empty($file)) + $files = scandir($dir); + else + $files[0] = $file; + + $modifyTime = time(); foreach ($files as $file) { @@ -105,32 +168,34 @@ function find_global_problems($real_globals = array(), $ignored_folders = array( continue; if (is_dir($dir . '/' . $file)) { - find_global_problems($real_globals, $ignored_folders, $dir . '/' . $file); + find_global_problems($real_globals, $ignored_folders, $dir . '/' . $file, ''); continue; } if (substr($file, -4) != '.php') continue; $php = $real_php = file_get_contents($dir . '/' . $file); - - // Remove comments, quotes and double quotes from the string. - // This makes the script about 5x to 10x slower, so if you just need a quick check, add the ?noclean parameter. - // A few alternative ways to remove these through regexes, but they won't work together: - // http://ideone.com/rLP1nq - // http://blog.stevenlevithan.com/archives/match-quoted-string - if (!isset($_GET['noclean'])) - $php = clean_me_up($php); + $fixes = 0; // Detect functions and class methods. $matches = get_function_list($php); foreach ($matches as $match) { + // Remove comments, quotes and double quotes from the string. + // This makes the script about 5x to 10x slower, so if you just need a quick check, add the ?noclean parameter. + if (!isset($_GET['noclean']) || isset($_GET['fixme'])) + $match['clean'] = clean_me_up($match['clean']); + preg_match_all('~(\$[a-zA-Z_][a-zA-Z0-9_]*)~', $match[2], $params); $params = isset($params[1]) ? $params[1] : array(); preg_match_all('~\sglobal (\$[^;]+);~', $match['clean'], $globs); $globs[1] = isset($globs[1]) ? $globs[1] : array(); + $curdir = str_replace($basedir, '', $dir); + if(!empty($curdir)) + $curdir = substr($curdir . '/', 1); + foreach ($globs[1] as $find_dupes) { $dupes = array_map('trim', explode(',', $find_dupes)); @@ -139,7 +204,22 @@ function find_global_problems($real_globals = array(), $ignored_folders = array( $problems++; $is_new = $file != $old_file; $old_file = $file; - echo '
  • Found duplicate globals in ', str_replace($root, '', $dir), '/', $file, ' (', $match[1] ?: 'anonymous function', ') -- ', $find_dupes, '
  • '; + $func_line = substr_count(substr($php, 0, $match['pos']), "\n"); + $glob_line = substr_count(substr($match['pristine'], 0, strpos($match['pristine'], $test_me)), "\n"); + echo '
  • Duplicate globals in ', $curdir, '', $file, ':', $func_line + $glob_line, ' (', $match[1] ?: 'anonymous function', ') -- ', $find_dupes, '
  • '; + + if (isset($_GET['fixme']) && strpos($match['clean'], 'global') !== false) + { + $funcglobs = implode(', ', array_unique($dupes)); + $globs[2] = explode(', ', $funcglobs); + $tmp = $match['pristine']; + if(strpos($match['clean'], 'global') !== false) + { + $match['pristine'] = preg_replace('~global[^\;]*\;~', 'global '. $funcglobs .';', $match['pristine']); + $php = str_replace($tmp, $match['pristine'], $php); + $fixes++; + } + } } } @@ -168,12 +248,30 @@ function find_global_problems($real_globals = array(), $ignored_folders = array( $old_file = $file; $func_line = substr_count(substr($php, 0, $match['pos']), "\n"); $glob_line = substr_count(substr($match['pristine'], 0, strpos($match['pristine'], $test_me)), "\n"); - echo '
  • Unused global in ', str_replace($root, '', $dir), '/', $file, ':', $func_line + $glob_line + 3, ' (', $match[1] ?: 'anonymous function', ') -- ', $test_me, ''; + echo '
  • Unused global in ', $curdir , '', $file, ':', $func_line + $glob_line, ' (', $match[1] ?: 'anonymous function', ') -- ', $test_me, ''; if ($probably_false_positive) { echo '
    The line above might be a false positive (', $r, ').
  • '; continue; } + else + { + if (isset($_GET['fixme']) && strpos($match['clean'], 'global') !== false) + { + $tmp = $match['pristine']; + $match['pristine'] = preg_replace( + '~[\t\s]*global \\' . $test_me . ';[\r\n]~', + '', + preg_replace( + '~(, ?\\' . $test_me . '(?![a-zA-Z_])|\\' . $test_me . ', ?)~', + '', + $match['pristine'] + ) + ); + $php = str_replace($tmp, $match['pristine'], $php); + $fixes++; + } + } echo ''; } } @@ -196,9 +294,9 @@ function find_global_problems($real_globals = array(), $ignored_folders = array( { $is_new = $file != $old_file; $old_file = $file; - $func_line = substr_count(substr($php, 0, $match['pos']), "\n"); - $glob_line = substr_count(substr($match['pristine'], 0, strpos($match['pristine'], reset($there_we_are[0]))), "\n"); - echo '
  • Undeclared global in ', str_replace($root, '', $dir), '/', $file, ':', $func_line + $glob_line + 3, ' (', $match[1] ?: 'anonymous function', ') -- ', $real_global, ''; + $func_line = substr_count(substr($php, 0, strpos($php, $match[0])), "\n"); + $glob_line = substr_count(substr($match['pristine'], 0, strpos($match['pristine'], $real_global)), "\n"); + echo '
  • Undeclared global in ', $curdir, '', $file, ':', $func_line + $glob_line +1, ' (', $match[1] ?: 'anonymous function', ') -- ', $real_global, ''; if ($probably_false_positive) { echo '
    The line above might be a false positive (', @@ -208,10 +306,48 @@ function find_global_problems($real_globals = array(), $ignored_folders = array( ($in_list ? 'initialized in a list() within function' : ''))), ').
  • '; continue; } + else + { + if (isset($_GET['fixme'])) + { + $tmp = $match['pristine']; + $func = substr($match['pristine'], strpos($match['pristine'], 'function'), strpos($match['pristine'], '{') +1); + + // any global in the clean area? + if(strpos($match['clean'], 'global') === false) + { + // no, remove commented globals + $match['pristine'] = preg_replace('~[^\/]\/\*[^g]*global[^\;]*;[^\*].?\*\/[\r\n]+~', '', $match['pristine']); + $match['pristine'] = preg_replace('~[\n\t\s\/]+global[^\;]*;[\r\n]+~', '', $match['pristine']); + + // add one to the clean area + $func = substr($match['clean'], strpos($match['clean'], 'function'), strpos($match['clean'], '{') +1); + $match['clean'] = preg_replace('~'. preg_quote($func) .'~', $func. "\n\t" .'global '. $real_global .";\n", $match['clean']); + + // insert missing globals + $func = substr($match['pristine'], strpos($match['pristine'], 'function'), strpos($match['pristine'], '{') +1); + $match['pristine'] = preg_replace('~'. preg_quote($func) .'~', $func. "\n\t" .'global '. $real_global .";\n", $match['pristine']); + } + else + $match['pristine'] = preg_replace('~global~', 'global '. $real_global .',', $match['pristine']); + + $php = str_replace($tmp, $match['pristine'], $php); + $fixes++; + } + } echo ''; } } } + + // if we have fixes .. + if (isset($_GET['fixme']) && !empty($fixes)) + { + file_put_contents($dir . '/' . $file, $php); + if (!isset($_GET['nobackup'])) + file_put_contents($dir . '/' . $file . '.' . $modifyTime, $real_php); + } + flush(); } } @@ -301,7 +437,7 @@ function find_next(&$php, $pos, $search_for) function get_function_list($php) { - $matches = find_functions($php); + $matches = find_functions($php, 0); for ($i = 0, $c = count($matches); $i < $c; $i++) for ($j = $i - 1; $j >= 0; $j--) if (strpos($matches[$i]['clean'], $matches[$j]['pristine']) !== false) @@ -309,14 +445,84 @@ function get_function_list($php) return $matches; } +function find_javascript($php) +{ + $script = array(); + $pos = 0; + + // find script start + $scriptstart = stripos($php, '', $scriptstart); + + // used by PortaMx for compressed inline javascript + if($scriptend === false) + $scriptend = stripos($php, 'array(), true)', $scriptstart); + + // used by PortaMx for inline javascript + if($scriptend === false) + $scriptend = stripos($php, ';\');', $scriptstart); + + if($scriptend === false) + break; + + $pos = $scriptstart; + while ($pos !== false && $pos < $scriptend) + { + $pos = stripos($php, 'function', $pos); + if ($pos !== false && $pos < $scriptend) + { + $func = $pos; + $pos = stripos($php, '{', $func) +1; + $script[] = array('start' => $func, 'end' => $pos); + } + } + + // find next start + $scriptstart = stripos($php, '= $scriptpos['start'] && $next < $scriptpos['end']) + { + $pos = $scriptpos['end']; + $next = stripos($php, 'function', $pos); + break; + } + } + // Did we reach the end of the block, or maybe we're in a nested function and we've reached its end? if ($next === false || (substr_count($count_brackets = substr($php, $pos, $next - $pos), '{') < substr_count($count_brackets, '}'))) return $matches; @@ -364,3 +570,4 @@ function find_functions($php, $offset = 0) $pos = $next_bracket; } } +?> \ No newline at end of file diff --git a/LICENSE b/LICENSE index dfe550d..2a8d1a6 100644 --- a/LICENSE +++ b/LICENSE @@ -2,6 +2,8 @@ The MIT License (MIT) Copyright (c) 2013 RenĂ©-Gilles Deberdt +Modification by Feline portamx.com + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to diff --git a/README.md b/README.md index 6dee5ec..e2d6ee0 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,4 @@ Tools ===== Scripts written for the Wedge platform. Might be usable in any other software, though. +Modifications by Feline for the SMF 2.1 and the PortaMx Virgo software