123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- <?php
- use dokuwiki\Logger;
- /**
- * DokuWiki Plugin logviewer (Admin Component)
- *
- * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
- * @author Andreas Gohr <andi@splitbrain.org>
- */
- class admin_plugin_logviewer extends DokuWiki_Admin_Plugin
- {
- const MAX_READ_SIZE = 1048576; // 1 MB
- protected $facilities;
- protected $facility;
- protected $date;
- /** @inheritDoc */
- public function forAdminOnly()
- {
- return true;
- }
- /** @inheritDoc */
- public function handle()
- {
- global $INPUT;
- $this->facilities = $this->getFacilities();
- $this->facility = $INPUT->str('facility');
- if (!in_array($this->facility, $this->facilities)) {
- $this->facility = $this->facilities[0];
- }
- $this->date = $INPUT->str('date');
- if (!preg_match('/^\d\d\d\d-\d\d-\d\d$/', $this->date)) {
- $this->date = gmdate('Y-m-d');
- }
- }
- /** @inheritDoc */
- public function html()
- {
- echo '<div id="plugin__logviewer">';
- echo $this->locale_xhtml('intro');
- $this->displayTabs();
- $this->displayLog();
- echo '</div>';
- }
- /**
- * Show the navigational tabs and date picker
- */
- protected function displayTabs()
- {
- global $ID;
- $form = new dokuwiki\Form\Form(['method' => 'GET']);
- $form->setHiddenField('do', 'admin');
- $form->setHiddenField('page', 'logviewer');
- $form->setHiddenField('facility', $this->facility);
- $form->addTextInput('date', $this->getLang('date'))
- ->attr('type', 'date')->val($this->date)->addClass('quickselect');
- $form->addButton('submit', '>')->attr('type', 'submit');
- echo $form->toHTML();
- echo '<ul class="tabs">';
- foreach ($this->facilities as $facility) {
- echo '<li>';
- if ($facility == $this->facility) {
- echo '<strong>' . hsc($facility) . '</strong>';
- } else {
- $link = wl($ID,
- ['do' => 'admin', 'page' => 'logviewer', 'date' => $this->date, 'facility' => $facility]);
- echo '<a href="' . $link . '">' . hsc($facility) . '</a>';
- }
- echo '</li>';
- }
- echo '</ul>';
- }
- /**
- * Read and output the logfile contents
- */
- protected function displayLog()
- {
- $logfile = Logger::getInstance($this->facility)->getLogfile($this->date);
- if (!file_exists($logfile)) {
- echo $this->locale_xhtml('nolog');
- return;
- }
- try {
- $lines = $this->getLogLines($logfile);
- $this->printLogLines($lines);
- } catch (Exception $e) {
- msg($e->getMessage(), -1);
- }
- }
- /**
- * Get the available logging facilities
- *
- * @return array
- */
- protected function getFacilities()
- {
- global $conf;
- // default facilities first
- $facilities = [
- Logger::LOG_ERROR,
- Logger::LOG_DEPRECATED,
- Logger::LOG_DEBUG,
- ];
- // add all other dirs
- $dirs = glob($conf['logdir'] . '/*', GLOB_ONLYDIR);
- foreach ($dirs as $dir) {
- $facilities[] = basename($dir);
- }
- $facilities = array_unique($facilities);
- return $facilities;
- }
- /**
- * Read the lines of the logfile and return them as array
- *
- * @param string $logfilePath
- * @return array
- * @throws Exception when reading fails
- */
- protected function getLogLines($logfilePath)
- {
- global $lang;
- $size = filesize($logfilePath);
- $fp = fopen($logfilePath, 'r');
- if (!$fp) throw new Exception($lang['log_file_failed_to_open']);
- try {
- if ($size < self::MAX_READ_SIZE) {
- $toread = $size;
- } else {
- $toread = self::MAX_READ_SIZE;
- fseek($fp, -$toread, SEEK_END);
- }
- $logData = fread($fp, $toread);
- if (!$logData) throw new Exception($lang['log_file_failed_to_read']);
- $lines = explode("\n", $logData);
- unset($logData); // free memory early
- if ($size >= self::MAX_READ_SIZE) {
- array_shift($lines); // Discard the first line
- while (!empty($lines) && (substr($lines[0], 0, 2) === ' ')) {
- array_shift($lines); // Discard indented lines
- }
- // A message to inform users that previous lines are skipped
- array_unshift($lines, "******\t" . "\t" . '[' . $lang['log_file_too_large'] . ']');
- }
- } finally {
- fclose($fp);
- }
- return $lines;
- }
- /**
- * Get an array of log lines and print them using appropriate styles
- *
- * @param array $lines
- */
- protected function printLogLines($lines)
- {
- $numberOfLines = count($lines);
- echo "<dl>";
- for ($i = 0; $i < $numberOfLines; $i++) {
- $line = $lines[$i];
- if (substr($line, 0, 2) === ' ') {
- // lines indented by two spaces are details, aggregate them
- echo '<dd>';
- while (substr($line, 0, 2) === ' ') {
- echo hsc(substr($line, 2)) . '<br />';
- $i++;
- $line = $lines[$i] ?? '';
- }
- echo '</dd>';
- $i -= 1; // rewind the counter
- } else {
- // other lines are actual log lines in three parts
- list($dt, $file, $msg) = sexplode("\t", $line, 3, '');
- echo '<dt>';
- echo '<span class="datetime">' . hsc($dt) . '</span>';
- echo '<span class="log">';
- echo '<span class="msg">' . hsc($msg) . '</span>';
- echo '<span class="file">' . hsc($file) . '</span>';
- echo '</span>';
- echo '</dt>';
- }
- }
- echo "</dl>";
- }
- }
|