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
|
|
|
private static $serverInfo = []; |
12
|
|
|
|
13
|
56 |
|
public static function parsePackage(string $data, string $version): void |
14
|
|
|
{ |
15
|
56 |
|
$i = 0; |
16
|
56 |
|
$length = strlen($data); |
17
|
56 |
|
self::$serverInfo['protocol_version'] = ord($data[$i]); |
18
|
56 |
|
++$i; |
19
|
|
|
|
20
|
|
|
//version |
21
|
56 |
|
self::$serverInfo['server_version'] = ''; |
22
|
56 |
|
$start = $i; |
23
|
56 |
|
for ($i = $start; $i < $length; ++$i) { |
24
|
56 |
|
if ($data[$i] === chr(0)) { |
25
|
56 |
|
++$i; |
26
|
56 |
|
break; |
27
|
|
|
} |
28
|
56 |
|
self::$serverInfo['server_version'] .= $data[$i]; |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
//connection_id 4 bytes |
32
|
56 |
|
self::$serverInfo['connection_id'] = unpack('I', $data[$i] . $data[++$i] . $data[++$i] . $data[++$i])[1]; |
33
|
56 |
|
++$i; |
34
|
|
|
|
35
|
|
|
//auth_plugin_data_part_1 |
36
|
|
|
//[len=8] first 8 bytes of the auth-plugin data |
37
|
56 |
|
self::$serverInfo['salt'] = ''; |
38
|
56 |
|
for ($j = $i; $j < $i + 8; ++$j) { |
39
|
56 |
|
self::$serverInfo['salt'] .= $data[$j]; |
40
|
|
|
} |
41
|
56 |
|
$i += 8; |
42
|
|
|
|
43
|
|
|
//filler_1 (1) -- 0x00 |
44
|
56 |
|
++$i; |
45
|
|
|
|
46
|
|
|
//capability_flag_1 (2) -- lower 2 bytes of the Protocol::CapabilityFlags (optional) |
47
|
56 |
|
$i += 2; |
48
|
|
|
|
49
|
|
|
//character_set (1) -- default server character-set, only the lower 8-bits Protocol::CharacterSet (optional) |
50
|
56 |
|
self::$serverInfo['character_set'] = $data[$i]; |
51
|
56 |
|
++$i; |
52
|
|
|
|
53
|
|
|
//status_flags (2) -- Protocol::StatusFlags (optional) |
|
|
|
|
54
|
56 |
|
$i += 2; |
55
|
|
|
|
56
|
|
|
//capability_flags_2 (2) -- upper 2 bytes of the Protocol::CapabilityFlags |
57
|
56 |
|
$i += 2; |
58
|
|
|
|
59
|
|
|
//auth_plugin_data_len (1) -- length of the combined auth_plugin_data, if auth_plugin_data_len is > 0 |
60
|
56 |
|
$salt_len = ord($data[$i]); |
61
|
56 |
|
++$i; |
62
|
|
|
|
63
|
56 |
|
$salt_len = max(12, $salt_len - 9); |
64
|
|
|
|
65
|
56 |
|
$i += 10; |
66
|
|
|
|
67
|
|
|
//next salt |
68
|
56 |
|
if ($length >= $i + $salt_len) { |
69
|
56 |
|
for ($j = $i; $j < $i + $salt_len; ++$j) { |
70
|
56 |
|
self::$serverInfo['salt'] .= $data[$j]; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
} |
74
|
56 |
|
self::$serverInfo['auth_plugin_name'] = ''; |
75
|
56 |
|
$i += $salt_len + 1; |
76
|
56 |
|
for ($j = $i; $j < $length - 1; ++$j) { |
77
|
56 |
|
self::$serverInfo['auth_plugin_name'] .= $data[$j]; |
78
|
|
|
} |
79
|
|
|
|
80
|
56 |
|
self::$serverInfo['version_name'] = self::parseVersion($version); |
81
|
56 |
|
} |
82
|
|
|
|
83
|
56 |
|
public static function getSalt(): string |
84
|
|
|
{ |
85
|
56 |
|
return self::$serverInfo['salt']; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* @see http://stackoverflow.com/questions/37317869/determine-if-mysql-or-percona-or-mariadb |
90
|
|
|
*/ |
91
|
56 |
|
private static function parseVersion(string $version): string |
92
|
|
|
{ |
93
|
56 |
|
if ('' !== $version) { |
94
|
56 |
|
if (false !== strpos($version, self::MYSQL_VERSION_MARIADB)) { |
95
|
|
|
return self::MYSQL_VERSION_MARIADB; |
96
|
|
|
} |
97
|
56 |
|
if (false !== strpos($version, self::MYSQL_VERSION_PERCONA)) { |
98
|
|
|
return self::MYSQL_VERSION_PERCONA; |
99
|
|
|
} |
100
|
|
|
} |
101
|
|
|
|
102
|
56 |
|
return self::MYSQL_VERSION_GENERIC; |
103
|
|
|
} |
104
|
|
|
|
105
|
56 |
|
public static function getVersion(): string |
106
|
|
|
{ |
107
|
56 |
|
return self::$serverInfo['version_name']; |
108
|
|
|
} |
109
|
|
|
|
110
|
56 |
|
public static function isMariaDb(): bool |
111
|
|
|
{ |
112
|
56 |
|
return self::MYSQL_VERSION_MARIADB === self::getVersion(); |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
public static function isPercona(): bool |
116
|
|
|
{ |
117
|
|
|
return self::MYSQL_VERSION_PERCONA === self::getVersion(); |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
public static function isGeneric(): bool |
121
|
|
|
{ |
122
|
|
|
return self::MYSQL_VERSION_GENERIC === self::getVersion(); |
123
|
|
|
} |
124
|
|
|
} |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.