<?php
class Parser
{
private $filename;
private $temp_filename;
private $contents;
private $parsed_log = array();
private $rule_map = array(
'Crash reason' => '_parseKVP',
'OpenTTD version' => '_parseKVP',
'Registers' => '_parseBlob',
'Stack trace' => '_parseBlob',
'Operating system' => '_parseKVP',
'Configuration' => '_parseKVP',
'Fonts' => '_parseKVP',
'AI Configuration (local: 0)' => '_parseKVP',
'Libraries' => '_parseKVP',
'Module information' => '_parseBlob',
'Decoded stack trace' => '_parseBlob',
);
public function __construct($file)
{
$this->filename = $file['name'];
$this->temp_filename = $file['tmp_name'];
}
public function validate()
{
$ext = pathinfo($this->filename, PATHINFO_EXTENSION);
if ($ext !== 'log') {
throw new Exception('The uploaded file is not a log file, got ' . $ext);
}
$file = fopen($this->temp_filename, 'r');
if (!feof($file)) {
if (trim(fgets($file), "\n\r") !== '*** OpenTTD Crash Report ***') {
throw new Exception('The uploaded file is not a valid crash log');
}
} else {
throw new Exception('The uploaded file is empty');
}
fclose($file);
}
private function prepare()
{
$this->contents = file($this->temp_filename, FILE_IGNORE_NEW_LINES);
}
public function parse()
{
$this->prepare();
$section = '';
foreach ($this->contents as $line) {
if ($this->isSection($line)) {
$section = trim($line, ":");
continue;
}
if ($section !== '') {
if (array_key_exists($section, $this->rule_map)) {
call_user_func(array($this, $this->rule_map[$section]), $line, $section);
}
}
}
}
public function getLog()
{
return $this->parsed_log;
}
private function isSection($line)
{
if (strpos($line, " ") === 0) return false;
$pos = strrpos($line, ':');
$len = strlen($line) - 1;
$check = $pos === $len;
return $check;
}
private function _parseKVP($line, $section)
{
if (strlen($line) === 0) {
return;
}
$i = stripos($line, ": ");
$key = trim(substr($line, 0, $i));
$value = trim(substr($line, $i + 1, strlen($line)));
$this->parsed_log[$section][$key] = $value;
}
private function _parseBlob($line, $section)
{
if (strlen($line) === 0) {
return;
}
$this->parsed_log[$section][] = $line;
}
}
if (isset($_POST["submit"])) {
$parser = new Parser($_FILES["logfile"]);
$parser->validate(); // handle exceptions
$parser->parse();
var_dump($parser->getLog());
}
?>
<html>
<title>OpenTTD Log Analyzer</title>
<body>
<form action="index.php" method="post" enctype="multipart/form-data">
<input type="file" name="logfile"/>
<button name="submit">Analyze</button>
</form>
</body>
</html>