Loading

Wolf01 log parser

  1. <?php
  2.  
  3. class Parser
  4. {
  5.     private $filename;
  6.     private $temp_filename;
  7.     private $contents;
  8.     private $parsed_log = array();
  9.  
  10.     private $rule_map = array(
  11.         'Crash reason'                => '_parseKVP',
  12.         'OpenTTD version'             => '_parseKVP',
  13.         'Registers'                   => '_parseBlob',
  14.         'Stack trace'                 => '_parseBlob',
  15.         'Operating system'            => '_parseKVP',
  16.         'Configuration'               => '_parseKVP',
  17.         'Fonts'                       => '_parseKVP',
  18.         'AI Configuration (local: 0)' => '_parseKVP',
  19.         'Libraries'                   => '_parseKVP',
  20.         'Module information'          => '_parseBlob',
  21.         'Decoded stack trace'         => '_parseBlob',
  22.     );
  23.  
  24.     public function __construct($file)
  25.     {
  26.         $this->filename = $file['name'];
  27.         $this->temp_filename = $file['tmp_name'];
  28.     }
  29.  
  30.     public function validate()
  31.     {
  32.         $ext = pathinfo($this->filename, PATHINFO_EXTENSION);
  33.  
  34.         if ($ext !== 'log') {
  35.             throw new Exception('The uploaded file is not a log file, got ' . $ext);
  36.         }
  37.  
  38.         $file = fopen($this->temp_filename, 'r');
  39.  
  40.         if (!feof($file)) {
  41.             if (trim(fgets($file), "\n\r") !== '*** OpenTTD Crash Report ***') {
  42.                 throw new Exception('The uploaded file is not a valid crash log');
  43.             }
  44.         } else {
  45.             throw new Exception('The uploaded file is empty');
  46.         }
  47.  
  48.         fclose($file);
  49.     }
  50.  
  51.     private function prepare()
  52.     {
  53.         $this->contents = file($this->temp_filename, FILE_IGNORE_NEW_LINES);
  54.     }
  55.  
  56.     public function parse()
  57.     {
  58.         $this->prepare();
  59.  
  60.         $section = '';
  61.  
  62.         foreach ($this->contents as $line) {
  63.             if ($this->isSection($line)) {
  64.                 $section = trim($line, ":");
  65.                 continue;
  66.             }
  67.  
  68.             if ($section !== '') {
  69.                 if (array_key_exists($section, $this->rule_map)) {
  70.                     call_user_func(array($this, $this->rule_map[$section]), $line, $section);
  71.                 }
  72.             }
  73.         }
  74.     }
  75.  
  76.     public function getLog()
  77.     {
  78.         return $this->parsed_log;
  79.     }
  80.  
  81.     private function isSection($line)
  82.     {
  83.         if (strpos($line, " ") === 0) return false;
  84.  
  85.         $pos = strrpos($line, ':');
  86.         $len = strlen($line) - 1;
  87.         $check = $pos === $len;
  88.  
  89.         return $check;
  90.     }
  91.  
  92.     private function _parseKVP($line, $section)
  93.     {
  94.         if (strlen($line) === 0) {
  95.             return;
  96.         }
  97.  
  98.         $i = stripos($line, ": ");
  99.         $key = trim(substr($line, 0, $i));
  100.         $value = trim(substr($line, $i + 1, strlen($line)));
  101.  
  102.         $this->parsed_log[$section][$key] = $value;
  103.     }
  104.  
  105.     private function _parseBlob($line, $section)
  106.     {
  107.         if (strlen($line) === 0) {
  108.             return;
  109.         }
  110.  
  111.         $this->parsed_log[$section][] = $line;
  112.     }
  113. }
  114.  
  115. if (isset($_POST["submit"])) {
  116.     $parser = new Parser($_FILES["logfile"]);
  117.     $parser->validate(); // handle exceptions
  118.     $parser->parse();
  119.     var_dump($parser->getLog());
  120. }
  121.  
  122. ?>
  123. <html>
  124. <title>OpenTTD Log Analyzer</title>
  125. <body>
  126. <form action="index.php" method="post" enctype="multipart/form-data">
  127.     <input type="file" name="logfile"/>
  128.     <button name="submit">Analyze</button>
  129. </form>
  130. </body>
  131. </html>

Comments