Passed
Pull Request — master (#3)
by Tim
03:47 queued 01:05
created

Logpeek   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 14
eloc 44
c 2
b 0
f 0
dl 0
loc 125
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A setAuthUtils() 0 3 1
B main() 0 32 6
A logFilter() 0 19 5
A setModuleConfig() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\Module\logpeek\Controller;
6
7
use Exception;
8
use SimpleSAML\Assert\Assert;
9
use SimpleSAML\Configuration;
10
use SimpleSAML\Module\logpeek\Config;
11
use SimpleSAML\Module\logpeek\File;
12
use SimpleSAML\Module\logpeek\Syslog;
13
use SimpleSAML\Session;
14
use SimpleSAML\Utils;
15
use SimpleSAML\XHTML\Template;
16
use Symfony\Component\HttpFoundation\Request;
17
18
use function array_reverse;
19
use function intval;
20
use function count;
21
use function date;
22
use function preg_match;
23
use function strstr;
24
25
/**
26
 * Controller class for the logpeek module.
27
 *
28
 * This class serves the different views available in the module.
29
 *
30
 * @package simplesamlphp/simplesamlphp-module-logpeek
31
 */
32
class Logpeek
33
{
34
    /** @var \SimpleSAML\Configuration */
35
    protected Configuration $config;
36
37
    /** @var \SimpleSAML\Module\logpeek\Config\Logpeek */
38
    protected Config\Logpeek $moduleConfig;
39
40
    /** @var \SimpleSAML\Session */
41
    protected Session $session;
42
43
    /** @var \SimpleSAML\Utils\Auth */
44
    protected $authUtils;
45
46
47
    /**
48
     * Controller constructor.
49
     *
50
     * It initializes the global configuration and session for the controllers implemented here.
51
     *
52
     * @param \SimpleSAML\Configuration $config The configuration to use by the controllers.
53
     * @param \SimpleSAML\Session $session The session to use by the controllers.
54
     *
55
     * @throws \Exception
56
     */
57
    public function __construct(
58
        Configuration $config,
59
        Session $session
60
    ) {
61
        $this->authUtils = new Utils\Auth();
62
        $this->config = $config;
63
        $this->moduleConfig = Config\Logpeek::fromYaml();
64
        $this->session = $session;
65
    }
66
67
68
    /**
69
     * Inject the \SimpleSAML\Utils\Auth dependency.
70
     *
71
     * @param \SimpleSAML\Utils\Auth $authUtils
72
     */
73
    public function setAuthUtils(Utils\Auth $authUtils): void
74
    {
75
        $this->authUtils = $authUtils;
76
    }
77
78
79
    /**
80
     * Inject the \SimpleSAML\Module\logpeek\Config\Logpeek dependency.
81
     *
82
     * @param \SimpleSAML\Module\logpeek\Config\Logpeek $moduleConfig
83
     */
84
    public function setModuleConfig(Config\Logpeek $moduleConfig): void
85
    {
86
        $this->moduleConfig = $moduleConfig;
87
    }
88
89
90
    /**
91
     * Main index controller.
92
     *
93
     * @param \Symfony\Component\HttpFoundation\Request $request The current request.
94
     *
95
     * @return \SimpleSAML\XHTML\Template
96
     */
97
    public function main(Request $request): Template
98
    {
99
        $this->authUtils->requireAdmin();
100
101
        $logFile = $this->moduleConfig->getLogFile();
102
        $blockSize = $this->moduleConfig->getBlockSize();
103
        $myLog = new File\ReverseRead($logFile, $blockSize);
104
105
        $results = [];
106
        if ($request->query->has('tag') === true) {
107
            /** @psalm-var string $tag */
108
            $tag = $request->query->get('tag');
109
            Assert::notNull($tag);
110
111
            $results = $this->logFilter($myLog, $tag, $this->moduleConfig->getLines());
112
        }
113
114
        $fileModYear = intval(date("Y", $myLog->getFileMtime()));
115
        $firstLine = $myLog->getFirstLine();
116
        $firstTimeEpoch = Syslog\ParseLine::getUnixTime($firstLine ?: '', $fileModYear);
117
        $lastLine = $myLog->getLastLine();
118
        $lastTimeEpoch = Syslog\ParseLine::getUnixTime($lastLine ?: '', $fileModYear);
119
        $fileSize = $myLog->getFileSize();
120
121
        $t = new Template($this->config, 'logpeek:logpeek.twig');
122
        $t->data['results'] = $results;
123
        $t->data['trackid'] = $this->session->getTrackID();
124
        $t->data['timestart'] = date(DATE_RFC822, $firstTimeEpoch ?: time());
125
        $t->data['endtime'] = date(DATE_RFC822, $lastTimeEpoch ?: time());
126
        $t->data['filesize'] = $fileSize;
127
128
        return $t;
129
    }
130
131
132
    /**
133
     * @param \SimpleSAML\Module\logpeek\File\ReverseRead $objFile
134
     * @param string $tag
135
     * @param int $cut
136
     * @return array
137
     */
138
    private function logFilter(File\ReverseRead $objFile, string $tag, int $cut): array
139
    {
140
        if (!preg_match('/^(TR[a-f0-9{8}]|CL[a-f0-9]{8}|[a-f0-9]{10})$/D', $tag)) {
141
            throw new Exception('Invalid search tag');
142
        }
143
144
        $i = 0;
145
        $results = [];
146
        $line = $objFile->getPreviousLine();
147
        while ($line !== false && ($i++ < $cut)) {
148
            if (strstr($line, '[' . $tag . ']')) {
149
                $results[] = $line;
150
            }
151
            $line = $objFile->getPreviousLine();
152
        }
153
154
        $results[] = 'Searched ' . $i . ' lines backward. ' . count($results) . ' lines found.';
155
        $results = array_reverse($results);
156
        return $results;
157
    }
158
}
159