Skip to content

Instantly share code, notes, and snippets.

@SukkaW
Created December 6, 2018 14:32
Show Gist options
  • Save SukkaW/45f85999903d8fd743b68d3e0141f47b to your computer and use it in GitHub Desktop.
Save SukkaW/45f85999903d8fd743b68d3e0141f47b to your computer and use it in GitHub Desktop.
#!/usr/bin/env php
<?php
// FIXME: Make this a proper app with unit-tests
require_once 'simple_html_dom.php';
exit(main($argv));
/**
* Scan a series of files for suspicious code
*
* example: find templates -name '*.tpl' | xargs php tools/scripts/tpl-lint
*
* @param array $argv
* @return int
*/
function main($argv) {
$files = $argv;
array_shift($files); // skip program name
foreach ($files as $file) {
check_tpl($file, function($code, $message) use ($file) {
printf("[%s] %s\n", $file, $message);
});
}
return 0;
}
/**
* Scan a file for suspicious code
*
* @param string $file
* @param callable $reporter
* @return void
*/
function check_tpl($file, $reporter) {
$html = file_get_html($file);
foreach ($html->find('a') as $a) {
check_a($a, $reporter);
}
}
/**
* Scan an <A> tag
*
* @param object $a
* @param callable $reporter
* @return void
*/
function check_a($a, $reporter) {
if (!$a->hasAttribute('href')) {
// anchor, don't care
return;
}
$href = trim($a->getAttribute('href'));
if (preg_match('/javascript:/', $href)) {
$reporter('javascript-url', "<a> has javascript url: $href");
return;
}
if ($href == '#' && $a->hasAttribute('onclick')) {
$onclick = $a->getAttribute('onclick');
if (!js_returns_false($onclick) && !js_returns_func($onclick)) {
$reporter('a-no-return', "<a> has href=# but handler fails to return false: $onclick");
return;
}
}
if ($href != '#' && $a->hasAttribute('onclick')) {
$onclick = $a->getAttribute('onclick');
$reporter('a-double-action', "<a> has both URL ($href) and onclick ($onclick)");
return;
}
}
/**
* Determine if snippet of JS returns strictly false
* @param $js
* @return bool
*/
function js_returns_false($js) {
return
// last in a series of statements
preg_match('/; *return +false *; *$/', $js)
||
// only statement
preg_match('/^ *return +false *;? *$/', $js);
}
/**
* Determine if snippet of JS returns a function call
* @param $js
* @return int
*/
function js_returns_func($js) {
return preg_match('/^ *return +[a-zA-Z0-9\._$]+\(/', $js);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment