mirror of
https://github.com/OPSnet/Logchecker.git
synced 2026-11-08 17:35:54 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7be957b343 | ||
|
|
09bfa6a98b | ||
|
|
ddbc042897 | ||
|
|
3f81c3a91d | ||
|
|
04d6d9cbef | ||
|
|
752ec6af0a | ||
|
|
594add313f | ||
|
|
fb05ef7b26 | ||
|
|
e462fdef45 | ||
|
|
b38c25a13d | ||
|
|
bd168e98b1 | ||
|
|
ec4d49f690 | ||
|
|
5a6a22cfbe | ||
|
|
d4664f02e7 | ||
|
|
a3643dadbb | ||
|
|
4529ca18d6 | ||
|
|
51e4545a60 | ||
|
|
aacc02cb61 | ||
|
|
fa9ef1b3bb | ||
|
|
b85fb622cb | ||
|
|
b7b7b59579 | ||
|
|
d37dd0283f | ||
|
|
55c61f5d3f |
No files matched your search
+2
-1
@@ -1,2 +1,3 @@
|
||||
.idea/
|
||||
vendor/
|
||||
vendor/
|
||||
logchecker.phar
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
language: php
|
||||
sudo: true
|
||||
dist: xenial
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.cache/pip
|
||||
- $HOME/.composer/cache
|
||||
|
||||
php:
|
||||
- 7.0
|
||||
- 7.1
|
||||
- 7.2
|
||||
- 7.3
|
||||
- nightly
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- php: nightly
|
||||
|
||||
before_install:
|
||||
- sudo apt-get install python3
|
||||
- wget https://bootstrap.pypa.io/get-pip.py
|
||||
- sudo python3 get-pip.py
|
||||
|
||||
install:
|
||||
- composer install --ansi --prefer-dist --no-interaction --optimize-autoloader --no-suggest --no-progress
|
||||
- pip3 install --user chardet xld_logchecker eac_logchecker
|
||||
|
||||
script:
|
||||
- bin/logchecker --version
|
||||
- bin/logchecker --help
|
||||
- bin/logchecker tests/logs/wgdbcm.log
|
||||
- bin/logchecker tests/logs/xld_perfect.log
|
||||
|
||||
before_deploy:
|
||||
- php -d phar.readonly=0 bin/compile
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: jlvbD7nzOz/8vssSI75loBMJE9OosAofTu1IDMc3bfxfRaPT6c2duebJF7Bm0VCTGYWK3Wc+19wwyLpCMoueUUEtKqi6RGIUQyboQvbSEe/cje7/9PgqmFstV8LdBLNOwRVj01YcmGw/iMVc+GxPTtDZtcwVU9bzlMCwXFAlggeId0Qw6KgxN+wTbm+oS3zrIh+TnWhgeWhmMYn0/UAEUEQCsYDI+UJjGWStWdpdJqdMhidg5GQyVtomFg82ZjIw+ywYGMGgq38S4PMRBLoqbxuWs++9LPblWboxtktb4+U0xUMdHfrv/r94b8+nI2SJ1xzzUKTXS/glkk0lJAovSYew6jJiu+gsejiNyR89WNgRGwnWAUA8ZBptrM2b3sxLuZ6RuxQXP3TMpxhQQE/3aodOrACPOHa8uuct0JAj/a2p0WCIj4r76McHrXTjFzDPsbdxD1GwOQmFJGqY5EV7Vez6q++Erp/64JEZJk9/jieTv0arLe76VZPQcZ6TB488tH699MvK7Gg1cc4114FbKIEZrOKF2FOrMAZJ3husjELN0zJYeRPZUy6Y7A2PAWsqfdswlxjP9IxuDFVE/3TW8O1sVItWo4+SSkKTILzsC0qgxVL2lW9WDmyka8U5T2SAa8ye/RRZ3FJYugep49wjUsfLraRdA+Lj7KQXSaMlFa8=
|
||||
file: logchecker.phar
|
||||
skip_cleanup: true
|
||||
on:
|
||||
tags: true
|
||||
repo: OPSnet/Logchecker
|
||||
php: '7.2'
|
||||
@@ -15,39 +15,32 @@ setting up the necessary programs to validate the checksum, see below for the gi
|
||||
|
||||
## Requirements
|
||||
* PHP 7.0+
|
||||
* Python3.4+
|
||||
|
||||
## Optional Requirements
|
||||
* Python 3.5+
|
||||
* [chardet](https://github.com/chardet/chardet)
|
||||
* [eac_logchecker.py](https://github.com/OPSnet/eac_logchecker.py)
|
||||
* [xld_logchecker.py](https://github.com/OPSnet/xld_logchecker.py)
|
||||
|
||||
## Installation
|
||||
```
|
||||
$ composer require orpheusnet/logchecker
|
||||
$ pip3 install chardet eac-logchecker xld-logchecker
|
||||
```
|
||||
|
||||
## Usage
|
||||
### CLI
|
||||
## Standalone
|
||||
### Installation
|
||||
Go to our [releases](https://github.com/OPSnet/Logchecker/releases) and grab the logchecker.phar
|
||||
file. Download this file, and then it can executed via CLI by running `php logchecker.phar`.
|
||||
Alternatively, if you `chmod +x logchecker.phar`, it can be executed directly by doing `./logchecker.phar`.
|
||||
|
||||
To install it globally, run:
|
||||
```bash
|
||||
mv logchecker.phar /usr/local/bin/logchecker
|
||||
chmod +x /usr/local/bin/logchecker
|
||||
```
|
||||
$ logchecker list
|
||||
Logchecker by Orpheus 0.5.0
|
||||
|
||||
Usage:
|
||||
command [options] [arguments]
|
||||
|
||||
Options:
|
||||
-h, --help Display this help message
|
||||
-V, --version Display this application version
|
||||
|
||||
Available commands:
|
||||
analyze analyze log file
|
||||
help Displays help for a command
|
||||
list Lists commands
|
||||
|
||||
$ logchecker analyze --help
|
||||
Description:
|
||||
analyze log file
|
||||
|
||||
### Usage
|
||||
```
|
||||
$ logchecker --help
|
||||
Usage:
|
||||
analyze [options] [--] <file>
|
||||
|
||||
@@ -57,11 +50,18 @@ Arguments:
|
||||
Options:
|
||||
--output Print the HTML log text
|
||||
-h, --help Display this help message
|
||||
-q, --quiet Do not output any message
|
||||
-V, --version Display this application version
|
||||
--ansi Force ANSI output
|
||||
--no-ansi Disable ANSI output
|
||||
-n, --no-interaction Do not ask any interactive question
|
||||
-file, --out=OUT File to write HTML log text to
|
||||
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
|
||||
|
||||
Help:
|
||||
This command analyzes a log file
|
||||
|
||||
$ logchecker analyze tests/logs/wgdbcm.log
|
||||
$ logchecker tests/logs/wgdbcm.log
|
||||
Score : 57
|
||||
Checksum: false
|
||||
Details :
|
||||
@@ -75,10 +75,47 @@ Details :
|
||||
```
|
||||
|
||||
### Code
|
||||
```
|
||||
```php
|
||||
<?php
|
||||
|
||||
$logchecker = new OrpheusNET\Logchecker\Logchecker();
|
||||
$logchecker->add_file('path/to/file.log');
|
||||
list($score, $details, $checksum, $log_text) = $logchecker->parse();
|
||||
```
|
||||
|
||||
## Library Usage
|
||||
### Installation
|
||||
```
|
||||
$ composer require orpheusnet/logchecker
|
||||
```
|
||||
|
||||
### Usage
|
||||
```php
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use OrpheusNET\Logchecker\Logchecker;
|
||||
|
||||
$logchecker = new Logchecker();
|
||||
$logchecker->new_file('/path/to/log/file');
|
||||
list($score, $details, $checksum, $log_text) = $logchecker->parse();
|
||||
print('Score: ' . $score . "\n");
|
||||
print('Checksum: ' . ($checksum ? 'true' : 'false') . "\n");
|
||||
print("\nDetails:\n");
|
||||
foreach ($details as $detail) {
|
||||
print(" {$detail}\n");
|
||||
}
|
||||
print("\nLog Text:\n{$log_text}");
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
To build your own phar, you can checkout this repository, and then
|
||||
run the `bin/compile` script. To do this, run the following commands:
|
||||
```bash
|
||||
git clone https://github.com/OPSnet/Logchecker
|
||||
cd Logchecker
|
||||
composer install
|
||||
php -d phar.readonly=0 bin/compile
|
||||
```
|
||||
Executable
+60
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
$phar_file = 'logchecker.phar';
|
||||
|
||||
if (file_exists($phar_file)) {
|
||||
unlink($phar_file);
|
||||
}
|
||||
|
||||
$phar = new Phar(__DIR__.'/../'.$phar_file, FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::KEY_AS_FILENAME, $phar_file);
|
||||
$phar->startBuffering();
|
||||
|
||||
$base_dir = realpath(__DIR__.'/../');
|
||||
|
||||
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(realpath(__DIR__.'/../src'), RecursiveDirectoryIterator::SKIP_DOTS));
|
||||
foreach ($it as $entry) {
|
||||
$phar->addFile($entry->getPathName(), str_replace($base_dir, '', $entry->getPathName()));
|
||||
}
|
||||
|
||||
$vendor = [
|
||||
'composer',
|
||||
'psr',
|
||||
'symfony'
|
||||
];
|
||||
|
||||
foreach ($vendor as $dir) {
|
||||
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(realpath(__DIR__.'/../vendor/'.$dir), RecursiveDirectoryIterator::SKIP_DOTS));
|
||||
foreach ($it as $entry) {
|
||||
$phar->addFile($entry->getPathName(), str_replace($base_dir, '', $entry->getPathName()));
|
||||
}
|
||||
}
|
||||
|
||||
$phar->addFile(realpath(__DIR__.'/../vendor/autoload.php'), 'vendor/autoload.php');
|
||||
|
||||
|
||||
$phar->addFile(realpath(__DIR__.'/../composer.json'), 'composer.json');
|
||||
$phar->addFile(realpath(__DIR__.'/../LICENSE.md'), 'LICENSE.md');
|
||||
$phar->addFile(realpath(__DIR__.'/../README.md'), 'README.md');
|
||||
|
||||
$bin_file = file_get_contents(__DIR__.'/logchecker');
|
||||
$bin_file = preg_replace('{^#!/usr/bin/env php\s*}', '', $bin_file);
|
||||
$phar->addFromString('bin/logchecker', $bin_file);
|
||||
|
||||
$stub = <<<PHP
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
Phar::mapPhar('{$phar_file}');
|
||||
require 'phar://{$phar_file}/bin/logchecker';
|
||||
|
||||
__HALT_COMPILER();
|
||||
PHP;
|
||||
|
||||
$phar->setStub($stub);
|
||||
|
||||
|
||||
$phar->stopBuffering();
|
||||
|
||||
//$phar->compress(Phar::GZ);
|
||||
|
||||
echo "{$phar_file} generated...";
|
||||
+4
-6
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "orpheusnet/logchecker",
|
||||
"description": "Logchecker for validating logs generated from supported ripping programs (like EAC and XLD)",
|
||||
"version": "0.7.0",
|
||||
"version": "0.8.3",
|
||||
"license": "Unlicense",
|
||||
"type": "library",
|
||||
"authors": [
|
||||
@@ -18,11 +18,9 @@
|
||||
"require": {
|
||||
"php": ">=7",
|
||||
"ext-mbstring": "*",
|
||||
"ext-yaml": "*",
|
||||
"symfony/console": "^4.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^6|^7"
|
||||
"symfony/console": "^3.4",
|
||||
"symfony/debug": "^3.4",
|
||||
"symfony/yaml": "^3.4"
|
||||
},
|
||||
"bin": ["bin/logchecker"]
|
||||
}
|
||||
Generated
+215
-1401
File diff suppressed because it is too large.
Load diff
@@ -44,4 +44,4 @@ for ($i = 1; $i < $rows->length; $i++) {
|
||||
|
||||
file_put_contents(__DIR__.'/../src/offsets.txt', implode("\n", $offsets));
|
||||
|
||||
print("Updating ".count($offsets)." drives\n");
|
||||
print("Updating ".count($offsets)." drives\n");
|
||||
+2
-1
@@ -15,11 +15,12 @@ class Chardet {
|
||||
foreach ($this->executables as $executable) {
|
||||
if (Util::commandExists($executable)) {
|
||||
$this->executable = $executable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->executable === null) {
|
||||
throw new \RuntimeException('Chardet not installed');
|
||||
throw new \RuntimeException('chardet not installed');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ class AnalyzeCommand extends Command {
|
||||
$logchecker = new Logchecker();
|
||||
$logchecker->new_file($filename);
|
||||
list($score, $details, $checksum, $log_text) = $logchecker->parse();
|
||||
$output->writeln('Ripper : ' . $logchecker->get_ripper());
|
||||
$output->writeln('Version : ' . $logchecker->get_version());
|
||||
$output->writeln('Score : ' . $score);
|
||||
$output->writeln('Checksum: ' . ($checksum ? 'true' : 'false'));
|
||||
|
||||
|
||||
+63
-22
@@ -2,6 +2,9 @@
|
||||
|
||||
namespace OrpheusNET\Logchecker;
|
||||
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Symfony\Component\Yaml\Exception\ParseException;
|
||||
|
||||
/*******************************************************************
|
||||
* Automated EAC/XLD log checker *
|
||||
********************************************************************/
|
||||
@@ -142,7 +145,6 @@ class Logchecker {
|
||||
$this->convert_encoding();
|
||||
}
|
||||
catch (\Exception $exc) {
|
||||
$this->Checksum = false;
|
||||
$this->Score = 0;
|
||||
$this->account('Could not detect log encoding, log is corrupt.');
|
||||
return $this->return_parse();
|
||||
@@ -157,17 +159,32 @@ class Logchecker {
|
||||
}
|
||||
|
||||
private function whipper_parse() {
|
||||
$Yaml = @yaml_parse($this->Log);
|
||||
if ($Yaml === false) {
|
||||
$this->Score = 0;
|
||||
$this->account('Could not parse whipper log.');
|
||||
try {
|
||||
$Yaml = Yaml::parse($this->Log);
|
||||
}
|
||||
catch (ParseException $exception) {
|
||||
$this->account('Could not parse whipper log.', 100);
|
||||
return $this->return_parse();
|
||||
}
|
||||
|
||||
$this->RIPPER = 'whipper';
|
||||
$this->Version = explode(" ", $Yaml['Log created by'])[1];
|
||||
|
||||
// Releases before this used octal numbers for tracks in the log which
|
||||
// gets messed up in parsing and we lose track data (e.g. tracks 08 and
|
||||
// 09 get merged into one entry).
|
||||
if (empty($this->Version) || version_compare('0.7.3', $this->Version) === 1) {
|
||||
$this->account('Logs must be produced by whipper 0.7.3+', 100);
|
||||
return $this->return_parse();
|
||||
}
|
||||
|
||||
if (!empty($Yaml['SHA-256 hash'])) {
|
||||
$Hash = $Yaml['SHA-256 hash'];
|
||||
$lines = explode("\n", trim($this->Log));
|
||||
$Slice = array_slice($lines, 0, count($lines)-1);
|
||||
$Lines = explode("\n", trim($this->Log));
|
||||
$Slice = array_slice($Lines, 0, count($Lines)-1);
|
||||
$this->Checksum = strtolower(hash('sha256', implode("\n", $Slice))) === strtolower($Hash);
|
||||
unset($Slice);
|
||||
unset($Lines);
|
||||
$Class = $this->Checksum ? 'good' : 'bad';
|
||||
$Yaml['SHA-256 hash'] = "<span class='{$Class}'>{$Hash}</span>";
|
||||
}
|
||||
@@ -211,18 +228,22 @@ class Logchecker {
|
||||
}
|
||||
|
||||
$DefeatCache = $Yaml['Ripping phase information']['Defeat audio cache'];
|
||||
if ($DefeatCache) {
|
||||
$Value = 'Yes';
|
||||
$Class = 'good';
|
||||
if (is_string($DefeatCache)) {
|
||||
$Value = (strtolower($DefeatCache) === 'yes') ? 'Yes' : 'No';
|
||||
$Class = (strtolower($DefeatCache) === 'yes') ? 'good' : 'bad';
|
||||
}
|
||||
else {
|
||||
$Value = 'No';
|
||||
$Class = 'bad';
|
||||
$this->account('"Defeat audio cache" should be yes', 10);
|
||||
$Value = ($DefeatCache === true) ? 'true' : 'false';
|
||||
$Class = ($DefeatCache === true) ? 'good' : 'bad';
|
||||
}
|
||||
if ($Class === 'bad') {
|
||||
$this->account('"Defeat audio cache" should be Yes/true', 10);
|
||||
}
|
||||
|
||||
$Yaml['Ripping phase information']['Defeat audio cache'] = "<span class='{$Class}'>{$Value}</span>";
|
||||
|
||||
foreach ($Yaml['Tracks'] as $Key => $Track) {
|
||||
$Yaml['Tracks'][$Key]['Peak level'] = sprintf('%.6f', $Track['Peak level']);
|
||||
$Class = 'good';
|
||||
if ($Track['Test CRC'] !== $Track['Copy CRC']) {
|
||||
$Class = 'bad';
|
||||
@@ -233,15 +254,22 @@ class Logchecker {
|
||||
$Yaml['Tracks'][$Key]['Copy CRC'] = "<span class='{$Class}'>{$Track['Copy CRC']}</span>";
|
||||
}
|
||||
|
||||
$this->Log = "Log created by: {$Yaml['Log created by']}\nLog creation date: {$Yaml['Log creation date']}\n\n";
|
||||
$CreationDate = gmdate("Y-m-d\TH:i:s\Z", $Yaml['Log creation date']);
|
||||
$this->Log = "Log created by: {$Yaml['Log created by']}\nLog creation date: {$CreationDate}\n\n";
|
||||
$this->Log .= "Ripping phase information:\n";
|
||||
foreach ($Yaml['Ripping phase information'] as $Key => $Value) {
|
||||
if (is_bool($Value)) {
|
||||
$Value = ($Value) ? 'true' : 'false';
|
||||
}
|
||||
$this->Log .= " {$Key}: {$Value}\n";
|
||||
}
|
||||
$this->Log .= "\n";
|
||||
|
||||
$this->Log .= "CD metadata:\n";
|
||||
foreach ($Yaml['CD metadata'] as $Key => $Value) {
|
||||
if (is_bool($Value)) {
|
||||
$Value = ($Value) ? 'true' : 'false';
|
||||
}
|
||||
$this->Log .= " {$Key}: {$Value}\n";
|
||||
}
|
||||
$this->Log .= "\n";
|
||||
@@ -254,7 +282,6 @@ class Logchecker {
|
||||
}
|
||||
$this->Log .= "\n";
|
||||
}
|
||||
$this->Log .= "\n";
|
||||
|
||||
$this->Log .= "Tracks:\n";
|
||||
foreach ($Yaml['Tracks'] as $Key => $Track) {
|
||||
@@ -267,16 +294,18 @@ class Logchecker {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (is_bool($Value)) {
|
||||
$Value = ($Value) ? 'Yes' : 'No';
|
||||
}
|
||||
$this->Log .= " {$KKey}: {$Value}\n";
|
||||
}
|
||||
}
|
||||
$this->Log .= "\n";
|
||||
}
|
||||
$this->Log .= "\n";
|
||||
|
||||
$this->Log .= "Conclusive status report:\n";
|
||||
foreach ($Yaml['Conclusive status report'] as $Key => $Value) {
|
||||
$this->Log .= "{$Key}: {$Value}\n";
|
||||
$this->Log .= " {$Key}: {$Value}\n";
|
||||
}
|
||||
$this->Log .= "\n";
|
||||
$this->Log .= "SHA-256 hash: {$Yaml['SHA-256 hash']}\n";
|
||||
@@ -424,10 +453,14 @@ class Logchecker {
|
||||
$GoodString = 'OK';
|
||||
}
|
||||
|
||||
$CommandExists = Util::commandExists($Command);
|
||||
$Out = shell_exec("{$Command} {$this->LogPath}");
|
||||
if (Util::strposArray($Out, $BadStrings) !== false || strpos($Out, $GoodString) === false) {
|
||||
$this->Checksum = false;
|
||||
if (Util::commandExists($Command)) {
|
||||
$Out = shell_exec("{$Command} ".escapeshellarg($this->LogPath));
|
||||
if ($Out == null || Util::strposArray($Out, $BadStrings) !== false || strpos($Out, $GoodString) === false) {
|
||||
$this->Checksum = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->account("Could not find {$Command}, checksum not validated.", false, false, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1005,7 +1038,7 @@ class Logchecker {
|
||||
$MatchedDrives[$i] = ['drives' => [], 'offsets' => []];
|
||||
}
|
||||
|
||||
foreach ($this->AllDrives as [$Drive, $Offset]) {
|
||||
foreach ($this->AllDrives as list($Drive, $Offset)) {
|
||||
$Distance = levenshtein($Drive, $DriveName);
|
||||
if ($Distance < 5) {
|
||||
$MatchedDrives[$Distance]['drives'][] = $Drive;
|
||||
@@ -1445,6 +1478,14 @@ class Logchecker {
|
||||
);
|
||||
}
|
||||
|
||||
function get_ripper() {
|
||||
return $this->RIPPER;
|
||||
}
|
||||
|
||||
function get_version() {
|
||||
return $this->Version;
|
||||
}
|
||||
|
||||
public static function get_accept_values() {
|
||||
return ".txt,.TXT,.log,.LOG";
|
||||
}
|
||||
|
||||
@@ -19,6 +19,6 @@ class LogcheckerConsole extends Application {
|
||||
$analyze_command
|
||||
]);
|
||||
|
||||
$this->setDefaultCommand($analyze_command->getName());
|
||||
$this->setDefaultCommand($analyze_command->getName(), true);
|
||||
}
|
||||
}
|
||||
+5
-3
@@ -3,9 +3,11 @@
|
||||
namespace OrpheusNET\Logchecker;
|
||||
|
||||
class Util {
|
||||
public static function commandExists($cmd) {
|
||||
$return = shell_exec(sprintf("which %s", escapeshellarg($cmd)));
|
||||
return !empty($return);
|
||||
public static function commandExists(string $cmd) {
|
||||
$where = substr(strtolower(PHP_OS), 0, 3) === 'win' ? 'where' : 'command -v';
|
||||
|
||||
exec("{$where} {$cmd} 2>/dev/null", $output, $return_var);
|
||||
return $return_var === 0;
|
||||
}
|
||||
|
||||
public static function strposArray(string $haystack, array $needles) {
|
||||
|
||||
Reference in new issue
Block a user