Passed
Push — master ( cbcad3...a04810 )
by Nils
02:15
created

OpenPortsCollector::getIdentifier()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Startwind\Inventorio\Collector\System\Ports;
4
5
use Startwind\Inventorio\Collector\Collector;
6
7
class OpenPortsCollector implements Collector
8
{
9
    private array $portMap = [];
10
11
    protected const COLLECTION_IDENTIFIER = 'SystemOpenPorts';
12
13
    public function __construct()
14
    {
15
        $this->loadPorts();
16
    }
17
18
    public function getIdentifier(): string
19
    {
20
        return self::COLLECTION_IDENTIFIER;
21
    }
22
23
    public function collect(): array
24
    {
25
        $ports = $this->getOpenPortsCLI();
26
27
        $enrichedPorts = [];
28
29
        foreach ($ports as $port) {
30
            $enrichedPorts[] = [
31
                'port' => $port,
32
                'tool' => $this->getTool($port)
33
            ];
34
        }
35
36
        return [
37
            'ports' => $enrichedPorts
38
        ];
39
    }
40
41
    private function getOpenPortsCLI(): array
42
    {
43
        $os = PHP_OS_FAMILY;
44
        $ports = [];
45
46
        if ($os === 'Windows') {
0 ignored issues
show
introduced by
The condition $os === 'Windows' is always false.
Loading history...
47
            $output = [];
48
            exec('netstat -an | findstr LISTENING', $output);
49
            foreach ($output as $line) {
50
                if (preg_match('/:(\d+)\s+LISTENING/', $line, $matches)) {
51
                    $ports[] = (int)$matches[1];
52
                }
53
            }
54
        } elseif ($os === 'Linux' || $os === 'Darwin') {
0 ignored issues
show
introduced by
The condition $os === 'Linux' is always true.
Loading history...
55
            // macOS and Linux
56
            $output = [];
57
58
            // Try lsof first
59
            exec("lsof -i -n -P | grep LISTEN", $output);
60
            if (empty($output)) {
61
                // Fallback to netstat
62
                exec("netstat -tuln", $output);
63
            }
64
65
            foreach ($output as $line) {
66
                if (preg_match('/:(\d+)\s/', $line, $matches)) {
67
                    $ports[] = (int)$matches[1];
68
                }
69
            }
70
        }
71
72
        return array_values(array_unique($ports));
73
    }
74
75
    private function loadPorts()
76
    {
77
        $csv = [];
78
        if (($handle = fopen(__DIR__ . '/ports.csv', "r")) !== false) {
79
            while (($data = fgetcsv($handle, null, ',', '"', '\\')) !== false) {
80
                $csv[$data[1]] = $data[2];
81
            }
82
            fclose($handle);
83
        }
84
        $this->portMap = $csv;
85
    }
86
87
    private function getTool(int $port): string
88
    {
89
        return $this->portMap[$port] ?? $port;
90
    }
91
}
92