diff --git a/config.ini b/config.ini index dcd60ff6..037af0f9 100644 --- a/config.ini +++ b/config.ini @@ -114,3 +114,6 @@ listTags=anonymous mergeTags=moderator renameTags=moderator massTag=moderator + +listLogs=moderator +viewLog=moderator diff --git a/public_html/media/css/logs.css b/public_html/media/css/logs.css new file mode 100644 index 00000000..91bd95a9 --- /dev/null +++ b/public_html/media/css/logs.css @@ -0,0 +1,9 @@ +#content input { + margin: 0 1em; + height: 25px; + vertical-align: middle; +} + +pre { + font-size: 11pt; +} diff --git a/public_html/media/js/logs.js b/public_html/media/js/logs.js new file mode 100644 index 00000000..7a5aa3b5 --- /dev/null +++ b/public_html/media/js/logs.js @@ -0,0 +1,4 @@ +$(function() +{ + $('#content form input').eq(0).focus().select(); +}); diff --git a/src/Controllers/LogController.php b/src/Controllers/LogController.php new file mode 100644 index 00000000..8891f6a4 --- /dev/null +++ b/src/Controllers/LogController.php @@ -0,0 +1,59 @@ +context->subTitle = 'latest logs'; + PrivilegesHelper::confirmWithException(Privilege::ListLogs); + + $path = $this->context->rootDir . DS . $this->config->main->logsPath; + $path = TextHelper::cleanPath($path); + + $logs = []; + foreach (glob($path . DS . '*.log') as $log) + $logs []= basename($log); + + usort($logs, function($a, $b) + { + return strnatcasecmp($b, $a); //reverse natcasesort + }); + + $this->context->transport->logs = $logs; + } + + /** + * @route /log/{name} + * @validate name [0-9a-zA-Z._-]+ + */ + public function viewAction($name) + { + $this->context->subTitle = 'logs (' . $name . ')'; + $this->context->stylesheets []= 'logs.css'; + $this->context->scripts []= 'logs.js'; + PrivilegesHelper::confirmWithException(Privilege::ViewLog); + + $name = str_replace(['/', '\\'], '', $name); //paranoia mode + $path = $this->context->rootDir . DS . $this->config->main->logsPath . DS . $name; + $path = TextHelper::cleanPath($path); + if (!file_exists($path)) + throw new SimpleException('Specified log doesn\'t exist'); + + $filter = InputHelper::get('filter'); + + $lines = file_get_contents($path); + $lines = explode(PHP_EOL, str_replace(["\r", "\n"], PHP_EOL, $lines)); + $lines = array_reverse($lines); + if (!empty($filter)) + $lines = array_filter($lines, function($line) use ($filter) { return stripos($line, $filter) !== false; }); + $lines = join(PHP_EOL, $lines); + $lines = TextHelper::parseMarkdown($lines); + $lines = trim($lines); + + $this->context->transport->filter = $filter; + $this->context->transport->name = $name; + $this->context->transport->log = $lines; + } +} diff --git a/src/CustomMarkdown.php b/src/CustomMarkdown.php index c147bec7..06100def 100644 --- a/src/CustomMarkdown.php +++ b/src/CustomMarkdown.php @@ -5,6 +5,7 @@ class CustomMarkdown extends \Michelf\Markdown { $this->no_markup = true; $this->span_gamut += ['doSpoilers' => 71]; + $this->span_gamut += ['doUsers' => 7]; $this->span_gamut += ['doPosts' => 8]; $this->span_gamut += ['doTags' => 9]; $this->span_gamut += ['doAutoLinks2' => 29]; @@ -66,4 +67,12 @@ class CustomMarkdown extends \Michelf\Markdown return $this->hashPart('') . $x[0] . $this->hashPart(''); }, $text); } + + protected function doUsers($text) + { + return preg_replace_callback('/(?:(?hashPart('') . $x[0] . $this->hashPart(''); + }, $text); + } } diff --git a/src/Helpers/TextHelper.php b/src/Helpers/TextHelper.php index 9fc3777d..7c9d1c2e 100644 --- a/src/Helpers/TextHelper.php +++ b/src/Helpers/TextHelper.php @@ -197,4 +197,14 @@ class TextHelper $iv = mcrypt_create_iv(mcrypt_get_iv_size($alg, $mode), MCRYPT_RAND); return trim(mcrypt_decrypt($alg, $salt, base64_decode($text), $mode, $iv)); } + + public static function cleanPath($path) + { + $path = str_replace(['/', '\\'], DS, $path); + $path = preg_replace('{[^' . DS . ']+' . DS . '\.\.(' . DS . '|$)}', '', $path); + $path = preg_replace('{(' . DS . '|^)\.' . DS . '}', '\1', $path); + $path = preg_replace('{' . DS . '{2,}}', DS, $path); + $path = rtrim($path, DS); + return $path; + } } diff --git a/src/Models/Privilege.php b/src/Models/Privilege.php index 5ebf5461..2c4ae348 100644 --- a/src/Models/Privilege.php +++ b/src/Models/Privilege.php @@ -36,4 +36,7 @@ class Privilege extends Enum const MergeTags = 27; const RenameTags = 27; const MassTag = 29; + + const ListLogs = 32; + const ViewLog = 33; } diff --git a/src/Views/layout-normal.phtml b/src/Views/layout-normal.phtml index 92b5478f..55349003 100644 --- a/src/Views/layout-normal.phtml +++ b/src/Views/layout-normal.phtml @@ -102,6 +102,9 @@
', array_map(function($x) { return preg_replace('/\s+/', ' ', $x); }, queryLogger()->getLogs())) ?>szurubooru v + + Logs +