Logpeek   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 115
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 43
dl 0
loc 115
rs 10
c 0
b 0
f 0
wmc 13

4 Methods

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