Server::addUserGrant()   B
last analyzed

Complexity

Conditions 7
Paths 4

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 11
c 1
b 0
f 0
nc 4
nop 2
dl 0
loc 18
rs 8.8333
1
<?php
2
3
namespace Lagdo\DbAdmin\Driver\Db;
4
5
use Lagdo\DbAdmin\Driver\DriverInterface;
6
use Lagdo\DbAdmin\Driver\Entity\UserEntity;
7
use Lagdo\DbAdmin\Driver\Utils\Utils;
8
9
use function preg_match;
10
use function preg_match_all;
11
12
abstract class Server implements ServerInterface
13
{
14
    /**
15
     * @var DriverInterface
16
     */
17
    protected $driver;
18
19
    /**
20
     * @var Utils
21
     */
22
    protected $utils;
23
24
    /**
25
     * The constructor
26
     *
27
     * @param DriverInterface $driver
28
     * @param Utils $utils
29
     */
30
    public function __construct(DriverInterface $driver, Utils $utils)
31
    {
32
        $this->driver = $driver;
33
        $this->utils = $utils;
34
    }
35
36
    /**
37
     * @inheritDoc
38
     */
39
    public function getUsers(string $database): array
40
    {
41
        // From privileges.inc.php
42
        $clause = ($database == '' ? 'user' : 'db WHERE ' . $this->driver->quote($database) . ' LIKE Db');
43
        $query = "SELECT User, Host FROM mysql.$clause ORDER BY Host, User";
44
        $statement = $this->driver->query($query);
45
        // $grant = $statement;
46
        if (!$statement) {
47
            // list logged user, information_schema.USER_PRIVILEGES lists just the current user too
48
            $statement = $this->driver->query("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', 1) " .
49
                "AS User, SUBSTRING_INDEX(CURRENT_USER, '@', -1) AS Host");
50
        }
51
        $users = [];
52
        while ($user = $statement->fetchAssoc()) {
53
            $users[] = $user;
54
        }
55
        return $users;
56
    }
57
58
    /**
59
     * @param UserEntity $user
60
     * @param array $grant
61
     *
62
     * @return void
63
     */
64
    private function addUserGrant(UserEntity $user, array $grant)
65
    {
66
        if (preg_match('~GRANT (.*) ON (.*) TO ~', $grant[0], $match) &&
67
            preg_match_all('~ *([^(,]*[^ ,(])( *\([^)]+\))?~', $match[1], $matches, PREG_SET_ORDER)) {
68
            //! escape the part between ON and TO
69
            foreach ($matches as $val) {
70
                $match2 = $match[2] ?? '';
71
                $val2 = $val[2] ?? '';
72
                if ($val[1] != 'USAGE') {
73
                    $user->grants["$match2$val2"][$val[1]] = true;
74
                }
75
                if (preg_match('~ WITH GRANT OPTION~', $grant[0])) { //! don't check inside strings and identifiers
76
                    $user->grants["$match2$val2"]['GRANT OPTION'] = true;
77
                }
78
            }
79
        }
80
        if (preg_match("~ IDENTIFIED BY PASSWORD '([^']+)~", $grant[0], $match)) {
81
            $user->password = $match[1];
82
        }
83
    }
84
85
    /**
86
     * @inheritDoc
87
     */
88
    public function getUserGrants(string $user, string $host): UserEntity
89
    {
90
        $entity = new UserEntity($user, $host);
91
92
        // From user.inc.php
93
        //! use information_schema for MySQL 5 - column names in column privileges are not escaped
94
        $query = 'SHOW GRANTS FOR ' . $this->driver->quote($user) . '@' . $this->driver->quote($host);
95
        if (!($statement = $this->driver->query($query))) {
96
            return $entity;
97
        }
98
99
        while ($grant = $statement->fetchRow()) {
100
            $this->addUserGrant($entity, $grant);
101
        }
102
        return $entity;
103
    }
104
105
    /**
106
     * @inheritDoc
107
     */
108
    public function getUserPrivileges(UserEntity $user)
109
    {
110
        $user->privileges = $this->driver->rows('SHOW PRIVILEGES');
111
    }
112
113
    /**
114
     * @inheritDoc
115
     */
116
    public function engines()
117
    {
118
        return [];
119
    }
120
121
    /**
122
     * @inheritDoc
123
     */
124
    public function collations()
125
    {
126
        return [];
127
    }
128
129
    /**
130
     * @inheritDoc
131
     */
132
    public function databaseCollation(string $database, array $collations)
133
    {
134
        return '';
135
    }
136
    /**
137
     * @inheritDoc
138
     */
139
    public function isInformationSchema(string $database)
140
    {
141
        return false;
142
    }
143
144
    /**
145
     * @inheritDoc
146
     */
147
    public function variables()
148
    {
149
        return [];
150
    }
151
152
    /**
153
     * @inheritDoc
154
     */
155
    public function statusVariables()
156
    {
157
        return [];
158
    }
159
160
    /**
161
     * @inheritDoc
162
     */
163
    public function routineLanguages()
164
    {
165
        return [];
166
    }
167
168
    /**
169
     * @inheritDoc
170
     */
171
    public function renameDatabase(string $name, string $collation)
172
    {
173
        return false;
174
    }
175
176
    /**
177
     * @inheritDoc
178
     */
179
    public function processes()
180
    {
181
        return [];
182
    }
183
184
    /**
185
     * @inheritDoc
186
     */
187
    public function processAttr(array $process, string $key, string $val): string
188
    {
189
        return $this->utils->str->html($val);
190
    }
191
}
192