Passed
Pull Request — master (#8)
by Moln
05:05
created

BinLogServerInfo::getRevision()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace MySQLReplication\BinLog;
5
6
class BinLogServerInfo
7
{
8
    private const MYSQL_VERSION_MARIADB = 'MariaDB';
9
    private const MYSQL_VERSION_PERCONA = 'Percona';
10
    private const MYSQL_VERSION_GENERIC = 'MySQL';
11
    /**
12
     * @var array
13
     */
14
    private $serverInfo;
15
16 58
    public static function parsePackage(string $data, string $version): BinLogServerInfo
17
    {
18 58
        $i = 0;
19 58
        $length = strlen($data);
20 58
        $serverInfo = [];
21 58
        $serverInfo['protocol_version'] = ord($data[$i]);
22 58
        ++$i;
23
24
        //version
25 58
        $serverInfo['server_version'] = '';
26 58
        $start = $i;
27 58
        for ($i = $start; $i < $length; ++$i) {
28 58
            if ($data[$i] === chr(0)) {
29 58
                ++$i;
30 58
                break;
31
            }
32 58
            $serverInfo['server_version'] .= $data[$i];
33
        }
34
35
        //connection_id 4 bytes
36 58
        $serverInfo['connection_id'] = unpack('I', $data[$i] . $data[++$i] . $data[++$i] . $data[++$i])[1];
37 58
        ++$i;
38
39
        //auth_plugin_data_part_1
40
        //[len=8] first 8 bytes of the auth-plugin data
41 58
        $serverInfo['salt'] = '';
42 58
        for ($j = $i; $j < $i + 8; ++$j) {
43 58
            $serverInfo['salt'] .= $data[$j];
44
        }
45 58
        $i += 8;
46
47
        //filler_1 (1) -- 0x00
48 58
        ++$i;
49
50
        //capability_flag_1 (2) -- lower 2 bytes of the Protocol::CapabilityFlags (optional)
51 58
        $i += 2;
52
53
        //character_set (1) -- default server character-set, only the lower 8-bits Protocol::CharacterSet (optional)
54 58
        $serverInfo['character_set'] = $data[$i];
55 58
        ++$i;
56
57
        //status_flags (2) -- Protocol::StatusFlags (optional)
58 58
        $i += 2;
59
60
        //capability_flags_2 (2) -- upper 2 bytes of the Protocol::CapabilityFlags
61 58
        $i += 2;
62
63
        //auth_plugin_data_len (1) -- length of the combined auth_plugin_data, if auth_plugin_data_len is > 0
64 58
        $saltLen = ord($data[$i]);
65 58
        ++$i;
66
67 58
        $saltLen = max(12, $saltLen - 9);
68
69 58
        $i += 10;
70
71
        //next salt
72 58
        if ($length >= $i + $saltLen) {
73 58
            for ($j = $i; $j < $i + $saltLen; ++$j) {
74 58
                $serverInfo['salt'] .= $data[$j];
75
            }
76
        }
77 58
        $serverInfo['auth_plugin_name'] = '';
78 58
        $i += $saltLen + 1;
79 58
        for ($j = $i; $j < $length - 1; ++$j) {
80 58
            $serverInfo['auth_plugin_name'] .= $data[$j];
81
        }
82
83 58
        $serverInfo['version_name'] = self::parseVersion($version);
84 58
        $serverInfo['version_revision'] = self::parseRevision($version);
85
86 58
        return new self($serverInfo);
87
    }
88
89 58
    public function __construct(array $serverInfo)
90
    {
91 58
        $this->serverInfo = $serverInfo;
92
    }
93
94 58
    public function getSalt(): string
95
    {
96 58
        return $this->serverInfo['salt'];
97
    }
98
99
    /**
100
     * @see http://stackoverflow.com/questions/37317869/determine-if-mysql-or-percona-or-mariadb
101
     */
102 58
    private static function parseVersion(string $version): string
103
    {
104 58
        if ('' !== $version) {
105 58
            if (false !== strpos($version, self::MYSQL_VERSION_MARIADB)) {
106
                return self::MYSQL_VERSION_MARIADB;
107
            }
108 58
            if (false !== strpos($version, self::MYSQL_VERSION_PERCONA)) {
109
                return self::MYSQL_VERSION_PERCONA;
110
            }
111
        }
112
113 58
        return self::MYSQL_VERSION_GENERIC;
114
    }
115
116
    public function getRevision(): float
117
    {
118
        return $this->serverInfo['version_revision'];
119
    }
120
121 58
    public function getVersion(): string
122
    {
123 58
        return $this->serverInfo['version_name'];
124
    }
125
126 58
    public function isMariaDb(): bool
127
    {
128 58
        return self::MYSQL_VERSION_MARIADB === $this->getVersion();
129
    }
130
131
    public function isPercona(): bool
132
    {
133
        return self::MYSQL_VERSION_PERCONA === $this->getVersion();
134
    }
135
136
    public function isGeneric(): bool
137
    {
138
        return self::MYSQL_VERSION_GENERIC === $this->getVersion();
139
    }
140
141 58
    private static function parseRevision(string $version): float
142
    {
143 58
        return (float)$version;
144
    }
145
}
146