In this context, field is really a column
[phpmyadmin/crack.git] / server_privileges.php
blobf085889ad2b9c9236f012a969cc9713169fe5b67
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
5 * @package phpMyAdmin
6 */
8 /**
11 require_once './libraries/common.inc.php';
13 /**
14 * Does the common work
16 $GLOBALS['js_include'][] = 'server_privileges.js';
17 $GLOBALS['js_include'][] = 'functions.js';
18 $GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js';
19 $_add_user_error = false;
21 require './libraries/server_common.inc.php';
23 if ($GLOBALS['cfg']['AjaxEnable']) {
24 $conditional_class = 'ajax';
25 } else {
26 $conditional_class = '';
29 /**
30 * Messages are built using the message name
32 $strPrivDescAllPrivileges = __('Includes all privileges except GRANT.');
33 $strPrivDescAlter = __('Allows altering the structure of existing tables.');
34 $strPrivDescAlterRoutine = __('Allows altering and dropping stored routines.');
35 $strPrivDescCreateDb = __('Allows creating new databases and tables.');
36 $strPrivDescCreateRoutine = __('Allows creating stored routines.');
37 $strPrivDescCreateTbl = __('Allows creating new tables.');
38 $strPrivDescCreateTmpTable = __('Allows creating temporary tables.');
39 $strPrivDescCreateUser = __('Allows creating, dropping and renaming user accounts.');
40 $strPrivDescCreateView = __('Allows creating new views.');
41 $strPrivDescDelete = __('Allows deleting data.');
42 $strPrivDescDropDb = __('Allows dropping databases and tables.');
43 $strPrivDescDropTbl = __('Allows dropping tables.');
44 $strPrivDescEvent = __('Allows to set up events for the event scheduler');
45 $strPrivDescExecute = __('Allows executing stored routines.');
46 $strPrivDescFile = __('Allows importing data from and exporting data into files.');
47 $strPrivDescGrant = __('Allows adding users and privileges without reloading the privilege tables.');
48 $strPrivDescIndex = __('Allows creating and dropping indexes.');
49 $strPrivDescInsert = __('Allows inserting and replacing data.');
50 $strPrivDescLockTables = __('Allows locking tables for the current thread.');
51 $strPrivDescMaxConnections = __('Limits the number of new connections the user may open per hour.');
52 $strPrivDescMaxQuestions = __('Limits the number of queries the user may send to the server per hour.');
53 $strPrivDescMaxUpdates = __('Limits the number of commands that change any table or database the user may execute per hour.');
54 $strPrivDescMaxUserConnections = __('Limits the number of simultaneous connections the user may have.');
55 $strPrivDescProcess = __('Allows viewing processes of all users');
56 $strPrivDescReferences = __('Has no effect in this MySQL version.');
57 $strPrivDescReload = __('Allows reloading server settings and flushing the server\'s caches.');
58 $strPrivDescReplClient = __('Allows the user to ask where the slaves / masters are.');
59 $strPrivDescReplSlave = __('Needed for the replication slaves.');
60 $strPrivDescSelect = __('Allows reading data.');
61 $strPrivDescShowDb = __('Gives access to the complete list of databases.');
62 $strPrivDescShowView = __('Allows performing SHOW CREATE VIEW queries.');
63 $strPrivDescShutdown = __('Allows shutting down the server.');
64 $strPrivDescSuper = __('Allows connecting, even if maximum number of connections is reached; required for most administrative operations like setting global variables or killing threads of other users.');
65 $strPrivDescTrigger = __('Allows creating and dropping triggers');
66 $strPrivDescUpdate = __('Allows changing data.');
67 $strPrivDescUsage = __('No privileges.');
69 /**
70 * Checks if a dropdown box has been used for selecting a database / table
72 if (PMA_isValid($_REQUEST['pred_tablename'])) {
73 $tablename = $_REQUEST['pred_tablename'];
74 unset($pred_tablename);
75 } elseif (PMA_isValid($_REQUEST['tablename'])) {
76 $tablename = $_REQUEST['tablename'];
77 } else {
78 unset($tablename);
81 if (PMA_isValid($_REQUEST['pred_dbname'])) {
82 $dbname = $_REQUEST['pred_dbname'];
83 unset($pred_dbname);
84 } elseif (PMA_isValid($_REQUEST['dbname'])) {
85 $dbname = $_REQUEST['dbname'];
86 } else {
87 unset($dbname);
88 unset($tablename);
91 if (isset($dbname)) {
92 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
93 if (isset($tablename)) {
94 $db_and_table .= PMA_backquote($tablename);
95 } else {
96 $db_and_table .= '*';
98 } else {
99 $db_and_table = '*.*';
102 // check if given $dbname is a wildcard or not
103 if (isset($dbname)) {
104 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
105 if (preg_match('/(?<!\\\\)(?:_|%)/i', $dbname)) {
106 $dbname_is_wildcard = true;
107 } else {
108 $dbname_is_wildcard = false;
113 * Checks if the user is allowed to do what he tries to...
115 if (!$is_superuser) {
116 require './libraries/server_links.inc.php';
117 echo '<h2>' . "\n"
118 . PMA_getIcon('b_usrlist.png')
119 . __('Privileges') . "\n"
120 . '</h2>' . "\n";
121 PMA_Message::error(__('No Privileges'))->display();
122 require './libraries/footer.inc.php';
125 $random_n = mt_rand(0,1000000); // a random number that will be appended to the id of the user forms
128 * Escapes wildcard in a database+table specification
129 * before using it in a GRANT statement.
131 * Escaping a wildcard character in a GRANT is only accepted at the global
132 * or database level, not at table level; this is why I remove
133 * the escaping character. Internally, in mysql.tables_priv.Db there are
134 * no escaping (for example test_db) but in mysql.db you'll see test\_db
135 * for a db-specific privilege.
137 * @param string $dbname Database name
138 * @param string $tablename Table name
139 * @return string the escaped (if necessary) database.table
141 function PMA_wildcardEscapeForGrant($dbname, $tablename)
144 if (! strlen($dbname)) {
145 $db_and_table = '*.*';
146 } else {
147 if (strlen($tablename)) {
148 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
149 $db_and_table .= PMA_backquote($tablename);
150 } else {
151 $db_and_table = PMA_backquote($dbname) . '.';
152 $db_and_table .= '*';
155 return $db_and_table;
159 * Generates a condition on the user name
161 * @param string the user's initial
162 * @return string the generated condition
164 function PMA_rangeOfUsers($initial = '')
166 // strtolower() is used because the User field
167 // might be BINARY, so LIKE would be case sensitive
168 if (!empty($initial)) {
169 $ret = " WHERE `User` LIKE '" . PMA_sqlAddSlashes($initial, true) . "%'"
170 . " OR `User` LIKE '" . PMA_sqlAddSlashes(strtolower($initial), true) . "%'";
171 } else {
172 $ret = '';
174 return $ret;
175 } // end function
178 * Extracts the privilege information of a priv table row
180 * @param array $row the row
181 * @param boolean $enableHTML add <dfn> tag with tooltips
183 * @global resource $user_link the database connection
185 * @return array
187 function PMA_extractPrivInfo($row = '', $enableHTML = false)
189 $grants = array(
190 array(
191 'Select_priv',
192 'SELECT',
193 __('Allows reading data.')),
194 array(
195 'Insert_priv',
196 'INSERT',
197 __('Allows inserting and replacing data.')),
198 array(
199 'Update_priv',
200 'UPDATE',
201 __('Allows changing data.')),
202 array(
203 'Delete_priv',
204 'DELETE',
205 __('Allows deleting data.')),
206 array(
207 'Create_priv',
208 'CREATE',
209 __('Allows creating new databases and tables.')),
210 array(
211 'Drop_priv',
212 'DROP',
213 __('Allows dropping databases and tables.')),
214 array(
215 'Reload_priv',
216 'RELOAD',
217 __('Allows reloading server settings and flushing the server\'s caches.')),
218 array(
219 'Shutdown_priv',
220 'SHUTDOWN',
221 __('Allows shutting down the server.')),
222 array(
223 'Process_priv',
224 'PROCESS',
225 __('Allows viewing processes of all users')),
226 array(
227 'File_priv',
228 'FILE',
229 __('Allows importing data from and exporting data into files.')),
230 array(
231 'References_priv',
232 'REFERENCES',
233 __('Has no effect in this MySQL version.')),
234 array(
235 'Index_priv',
236 'INDEX',
237 __('Allows creating and dropping indexes.')),
238 array(
239 'Alter_priv',
240 'ALTER',
241 __('Allows altering the structure of existing tables.')),
242 array(
243 'Show_db_priv',
244 'SHOW DATABASES',
245 __('Gives access to the complete list of databases.')),
246 array(
247 'Super_priv',
248 'SUPER',
249 __('Allows connecting, even if maximum number of connections is reached; required for most administrative operations like setting global variables or killing threads of other users.')),
250 array(
251 'Create_tmp_table_priv',
252 'CREATE TEMPORARY TABLES',
253 __('Allows creating temporary tables.')),
254 array(
255 'Lock_tables_priv',
256 'LOCK TABLES',
257 __('Allows locking tables for the current thread.')),
258 array(
259 'Repl_slave_priv',
260 'REPLICATION SLAVE',
261 __('Needed for the replication slaves.')),
262 array(
263 'Repl_client_priv',
264 'REPLICATION CLIENT',
265 __('Allows the user to ask where the slaves / masters are.')),
266 array(
267 'Create_view_priv',
268 'CREATE VIEW',
269 __('Allows creating new views.')),
270 array(
271 'Event_priv',
272 'EVENT',
273 __('Allows to set up events for the event scheduler')),
274 array(
275 'Trigger_priv',
276 'TRIGGER',
277 __('Allows creating and dropping triggers')),
278 // for table privs:
279 array(
280 'Create View_priv',
281 'CREATE VIEW',
282 __('Allows creating new views.')),
283 array(
284 'Show_view_priv',
285 'SHOW VIEW',
286 __('Allows performing SHOW CREATE VIEW queries.')),
287 // for table privs:
288 array(
289 'Show view_priv',
290 'SHOW VIEW',
291 __('Allows performing SHOW CREATE VIEW queries.')),
292 array(
293 'Create_routine_priv',
294 'CREATE ROUTINE',
295 __('Allows creating stored routines.')),
296 array(
297 'Alter_routine_priv',
298 'ALTER ROUTINE',
299 __('Allows altering and dropping stored routines.')),
300 array(
301 'Create_user_priv',
302 'CREATE USER',
303 __('Allows creating, dropping and renaming user accounts.')),
304 array(
305 'Execute_priv',
306 'EXECUTE',
307 __('Allows executing stored routines.')),
310 if (!empty($row) && isset($row['Table_priv'])) {
311 $row1 = PMA_DBI_fetch_single_row(
312 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
313 'ASSOC', $GLOBALS['userlink']);
314 $av_grants = explode('\',\'', substr($row1['Type'], 5, strlen($row1['Type']) - 7));
315 unset($row1);
316 $users_grants = explode(',', $row['Table_priv']);
317 foreach ($av_grants as $current_grant) {
318 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
320 unset($current_grant);
321 unset($av_grants);
322 unset($users_grants);
324 $privs = array();
325 $allPrivileges = true;
326 foreach ($grants as $current_grant) {
327 if ((!empty($row) && isset($row[$current_grant[0]]))
328 || (empty($row) && isset($GLOBALS[$current_grant[0]]))) {
329 if ((!empty($row) && $row[$current_grant[0]] == 'Y')
330 || (empty($row)
331 && ($GLOBALS[$current_grant[0]] == 'Y'
332 || (is_array($GLOBALS[$current_grant[0]])
333 && count($GLOBALS[$current_grant[0]]) == $GLOBALS['column_count']
334 && empty($GLOBALS[$current_grant[0] . '_none'])))))
336 if ($enableHTML) {
337 $privs[] = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
338 } else {
339 $privs[] = $current_grant[1];
341 } elseif (!empty($GLOBALS[$current_grant[0]])
342 && is_array($GLOBALS[$current_grant[0]])
343 && empty($GLOBALS[$current_grant[0] . '_none'])) {
344 if ($enableHTML) {
345 $priv_string = '<dfn title="' . $current_grant[2] . '">' . $current_grant[1] . '</dfn>';
346 } else {
347 $priv_string = $current_grant[1];
349 $privs[] = $priv_string . ' (`' . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
350 } else {
351 $allPrivileges = false;
355 if (empty($privs)) {
356 if ($enableHTML) {
357 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
358 } else {
359 $privs[] = 'USAGE';
361 } elseif ($allPrivileges && (! isset($GLOBALS['grant_count']) || count($privs) == $GLOBALS['grant_count'])) {
362 if ($enableHTML) {
363 $privs = array('<dfn title="' . __('Includes all privileges except GRANT.') . '">ALL PRIVILEGES</dfn>');
364 } else {
365 $privs = array('ALL PRIVILEGES');
368 return $privs;
369 } // end of the 'PMA_extractPrivInfo()' function
372 * Displays on which column(s) a table-specific privilege is granted
374 function PMA_display_column_privs($columns, $row, $name_for_select,
375 $priv_for_header, $name, $name_for_dfn, $name_for_current)
377 echo ' <div class="item" id="div_item_' . $name . '">' . "\n"
378 . ' <label for="select_' . $name . '_priv">' . "\n"
379 . ' <tt><dfn title="' . $name_for_dfn . '">'
380 . $priv_for_header . '</dfn></tt>' . "\n"
381 . ' </label><br />' . "\n"
382 . ' <select id="select_' . $name . '_priv" name="'
383 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
385 foreach ($columns as $current_column => $current_column_privileges) {
386 echo ' <option value="' . htmlspecialchars($current_column) . '"';
387 if ($row[$name_for_select] == 'Y' || $current_column_privileges[$name_for_current]) {
388 echo ' selected="selected"';
390 echo '>' . htmlspecialchars($current_column) . '</option>' . "\n";
393 echo ' </select>' . "\n"
394 . ' <i>' . __('Or') . '</i>' . "\n"
395 . ' <label for="checkbox_' . $name_for_select
396 . '_none"><input type="checkbox"'
397 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
398 . ' name="' . $name_for_select . '_none" id="checkbox_'
399 . $name_for_select . '_none" title="' . _pgettext('None privileges', 'None') . '" />'
400 . _pgettext('None privileges', 'None') . '</label>' . "\n"
401 . ' </div>' . "\n";
402 } // end function
406 * Displays the privileges form table
408 * @param string $db the database
409 * @param string $table the table
410 * @param boolean $submit wheather to display the submit button or not
411 * @global array $cfg the phpMyAdmin configuration
412 * @global ressource $user_link the database connection
414 * @return void
416 function PMA_displayPrivTable($db = '*', $table = '*', $submit = true)
418 global $random_n;
420 if ($db == '*') {
421 $table = '*';
424 if (isset($GLOBALS['username'])) {
425 $username = $GLOBALS['username'];
426 $hostname = $GLOBALS['hostname'];
427 if ($db == '*') {
428 $sql_query =
429 "SELECT * FROM `mysql`.`user`"
430 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
431 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
432 } elseif ($table == '*') {
433 $sql_query =
434 "SELECT * FROM `mysql`.`db`"
435 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
436 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
437 ." AND '" . PMA_unescape_mysql_wildcards($db) . "'"
438 ." LIKE `Db`;";
439 } else {
440 $sql_query =
441 "SELECT `Table_priv`"
442 ." FROM `mysql`.`tables_priv`"
443 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
444 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
445 ." AND `Db` = '" . PMA_unescape_mysql_wildcards($db) . "'"
446 ." AND `Table_name` = '" . PMA_sqlAddSlashes($table) . "';";
448 $row = PMA_DBI_fetch_single_row($sql_query);
450 if (empty($row)) {
451 if ($table == '*') {
452 if ($db == '*') {
453 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
454 } elseif ($table == '*') {
455 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
457 $res = PMA_DBI_query($sql_query);
458 while ($row1 = PMA_DBI_fetch_row($res)) {
459 if (substr($row1[0], 0, 4) == 'max_') {
460 $row[$row1[0]] = 0;
461 } else {
462 $row[$row1[0]] = 'N';
465 PMA_DBI_free_result($res);
466 } else {
467 $row = array('Table_priv' => '');
470 if (isset($row['Table_priv'])) {
471 $row1 = PMA_DBI_fetch_single_row(
472 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
473 'ASSOC', $GLOBALS['userlink']);
474 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
475 // the View for Create is spelled with uppercase V
476 // the view for Show is spelled with lowercase v
477 // and there is a space between the words
479 $av_grants = explode('\',\'', substr($row1['Type'], strpos($row1['Type'], '(') + 2, strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3));
480 unset($row1);
481 $users_grants = explode(',', $row['Table_priv']);
483 foreach ($av_grants as $current_grant) {
484 $row[$current_grant . '_priv'] = in_array($current_grant, $users_grants) ? 'Y' : 'N';
486 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
488 // get collumns
489 $res = PMA_DBI_try_query('SHOW COLUMNS FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($db)) . '.' . PMA_backquote($table) . ';');
490 $columns = array();
491 if ($res) {
492 while ($row1 = PMA_DBI_fetch_row($res)) {
493 $columns[$row1[0]] = array(
494 'Select' => false,
495 'Insert' => false,
496 'Update' => false,
497 'References' => false
500 PMA_DBI_free_result($res);
502 unset($res, $row1);
504 // t a b l e - s p e c i f i c p r i v i l e g e s
505 if (! empty($columns)) {
506 $res = PMA_DBI_query(
507 'SELECT `Column_name`, `Column_priv`'
508 .' FROM `mysql`.`columns_priv`'
509 .' WHERE `User`'
510 .' = \'' . PMA_sqlAddSlashes($username) . "'"
511 .' AND `Host`'
512 .' = \'' . PMA_sqlAddSlashes($hostname) . "'"
513 .' AND `Db`'
514 .' = \'' . PMA_sqlAddSlashes(PMA_unescape_mysql_wildcards($db)) . "'"
515 .' AND `Table_name`'
516 .' = \'' . PMA_sqlAddSlashes($table) . '\';');
518 while ($row1 = PMA_DBI_fetch_row($res)) {
519 $row1[1] = explode(',', $row1[1]);
520 foreach ($row1[1] as $current) {
521 $columns[$row1[0]][$current] = true;
524 PMA_DBI_free_result($res);
525 unset($res, $row1, $current);
527 echo '<input type="hidden" name="grant_count" value="' . count($row) . '" />' . "\n"
528 . '<input type="hidden" name="column_count" value="' . count($columns) . '" />' . "\n"
529 . '<fieldset id="fieldset_user_priv">' . "\n"
530 . ' <legend>' . __('Table-specific privileges')
531 . PMA_showHint(__('Note: MySQL privilege names are expressed in English'))
532 . '</legend>' . "\n";
536 // privs that are attached to a specific column
537 PMA_display_column_privs($columns, $row, 'Select_priv',
538 'SELECT', 'select', __('Allows reading data.'), 'Select');
540 PMA_display_column_privs($columns, $row, 'Insert_priv',
541 'INSERT', 'insert', __('Allows inserting and replacing data.'), 'Insert');
543 PMA_display_column_privs($columns, $row, 'Update_priv',
544 'UPDATE', 'update', __('Allows changing data.'), 'Update');
546 PMA_display_column_privs($columns, $row, 'References_priv',
547 'REFERENCES', 'references', __('Has no effect in this MySQL version.'), 'References');
549 // privs that are not attached to a specific column
551 echo ' <div class="item">' . "\n";
552 foreach ($row as $current_grant => $current_grant_value) {
553 if (in_array(substr($current_grant, 0, (strlen($current_grant) - 5)),
554 array('Select', 'Insert', 'Update', 'References'))) {
555 continue;
557 // make a substitution to match the messages variables;
558 // also we must substitute the grant we get, because we can't generate
559 // a form variable containing blanks (those would get changed to
560 // an underscore when receiving the POST)
561 if ($current_grant == 'Create View_priv') {
562 $tmp_current_grant = 'CreateView_priv';
563 $current_grant = 'Create_view_priv';
564 } elseif ($current_grant == 'Show view_priv') {
565 $tmp_current_grant = 'ShowView_priv';
566 $current_grant = 'Show_view_priv';
567 } else {
568 $tmp_current_grant = $current_grant;
571 echo ' <div class="item">' . "\n"
572 . ' <input type="checkbox"'
573 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
574 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
575 . '" value="Y" '
576 . ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
577 . 'title="';
579 echo (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
580 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
581 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl']) . '"/>' . "\n";
583 echo ' <label for="checkbox_' . $current_grant
584 . '"><tt><dfn title="'
585 . (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
586 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
587 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl'])
588 . '">' . strtoupper(substr($current_grant, 0, strlen($current_grant) - 5)) . '</dfn></tt></label>' . "\n"
589 . ' </div>' . "\n";
590 } // end foreach ()
592 echo ' </div>' . "\n";
593 // for Safari 2.0.2
594 echo ' <div class="clearfloat"></div>' . "\n";
596 } else {
598 // g l o b a l o r d b - s p e c i f i c
600 $privTable_names = array(0 => __('Data'), 1 => __('Structure'), 2 => __('Administration'));
602 // d a t a
603 $privTable[0] = array(
604 array('Select', 'SELECT', __('Allows reading data.')),
605 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
606 array('Update', 'UPDATE', __('Allows changing data.')),
607 array('Delete', 'DELETE', __('Allows deleting data.'))
609 if ($db == '*') {
610 $privTable[0][] = array('File', 'FILE', __('Allows importing data from and exporting data into files.'));
613 // s t r u c t u r e
614 $privTable[1] = array(
615 array('Create', 'CREATE', ($table == '*' ? __('Allows creating new databases and tables.') : __('Allows creating new tables.'))),
616 array('Alter', 'ALTER', __('Allows altering the structure of existing tables.')),
617 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
618 array('Drop', 'DROP', ($table == '*' ? __('Allows dropping databases and tables.') : __('Allows dropping tables.'))),
619 array('Create_tmp_table', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
620 array('Show_view', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
621 array('Create_routine', 'CREATE ROUTINE', __('Allows creating stored routines.')),
622 array('Alter_routine', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
623 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
625 // this one is for a db-specific priv: Create_view_priv
626 if (isset($row['Create_view_priv'])) {
627 $privTable[1][] = array('Create_view', 'CREATE VIEW', __('Allows creating new views.'));
629 // this one is for a table-specific priv: Create View_priv
630 if (isset($row['Create View_priv'])) {
631 $privTable[1][] = array('Create View', 'CREATE VIEW', __('Allows creating new views.'));
633 if (isset($row['Event_priv'])) {
634 // MySQL 5.1.6
635 $privTable[1][] = array('Event', 'EVENT', __('Allows to set up events for the event scheduler'));
636 $privTable[1][] = array('Trigger', 'TRIGGER', __('Allows creating and dropping triggers'));
639 // a d m i n i s t r a t i o n
640 $privTable[2] = array(
641 array('Grant', 'GRANT', __('Allows adding users and privileges without reloading the privilege tables.')),
643 if ($db == '*') {
644 $privTable[2][] = array('Super', 'SUPER', __('Allows connecting, even if maximum number of connections is reached; required for most administrative operations like setting global variables or killing threads of other users.'));
645 $privTable[2][] = array('Process', 'PROCESS', __('Allows viewing processes of all users'));
646 $privTable[2][] = array('Reload', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.'));
647 $privTable[2][] = array('Shutdown', 'SHUTDOWN', __('Allows shutting down the server.'));
648 $privTable[2][] = array('Show_db', 'SHOW DATABASES', __('Gives access to the complete list of databases.'));
650 $privTable[2][] = array('Lock_tables', 'LOCK TABLES', __('Allows locking tables for the current thread.'));
651 $privTable[2][] = array('References', 'REFERENCES', __('Has no effect in this MySQL version.'));
652 if ($db == '*') {
653 $privTable[2][] = array('Repl_client', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.'));
654 $privTable[2][] = array('Repl_slave', 'REPLICATION SLAVE', __('Needed for the replication slaves.'));
655 $privTable[2][] = array('Create_user', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.'));
657 echo '<input type="hidden" name="grant_count" value="'
658 . (count($privTable[0]) + count($privTable[1]) + count($privTable[2]) - (isset($row['Grant_priv']) ? 1 : 0))
659 . '" />' . "\n"
660 . '<fieldset id="fieldset_user_global_rights">' . "\n"
661 . ' <legend>' . "\n"
662 . ' '
663 . ($db == '*'
664 ? __('Global privileges')
665 : ($table == '*'
666 ? __('Database-specific privileges')
667 : __('Table-specific privileges'))) . "\n"
668 . ' (<a href="server_privileges.php?'
669 . $GLOBALS['url_query'] . '&amp;checkall=1" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', true); return false;">'
670 . __('Check All') . '</a> /' . "\n"
671 . ' <a href="server_privileges.php?'
672 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', false); return false;">'
673 . __('Uncheck All') . '</a>)' . "\n"
674 . ' </legend>' . "\n"
675 . ' <p><small><i>' . __('Note: MySQL privilege names are expressed in English') . '</i></small></p>' . "\n";
677 // Output the Global privilege tables with checkboxes
678 foreach ($privTable as $i => $table) {
679 echo ' <fieldset>' . "\n"
680 . ' <legend>' . __($privTable_names[$i]) . '</legend>' . "\n";
681 foreach ($table as $priv)
683 echo ' <div class="item">' . "\n"
684 . ' <input type="checkbox"'
685 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0] . '_priv"'
686 . ' value="Y" title="' . $priv[2] . '"'
687 . ((!empty($GLOBALS['checkall']) || $row[$priv[0] . '_priv'] == 'Y') ? ' checked="checked"' : '')
688 . '/>' . "\n"
689 . ' <label for="checkbox_' . $priv[0] . '_priv"><tt><dfn title="' . $priv[2] . '">'
690 . $priv[1] . '</dfn></tt></label>' . "\n"
691 . ' </div>' . "\n";
693 echo ' </fieldset>' . "\n";
696 // The "Resource limits" box is not displayed for db-specific privs
697 if ($db == '*') {
698 echo ' <fieldset>' . "\n"
699 . ' <legend>' . __('Resource limits') . '</legend>' . "\n"
700 . ' <p><small><i>' . __('Note: Setting these options to 0 (zero) removes the limit.') . '</i></small></p>' . "\n"
701 . ' <div class="item">' . "\n"
702 . ' <label for="text_max_questions"><tt><dfn title="'
703 . __('Limits the number of queries the user may send to the server per hour.') . '">MAX QUERIES PER HOUR</dfn></tt></label>' . "\n"
704 . ' <input type="text" name="max_questions" id="text_max_questions" value="'
705 . $row['max_questions'] . '" size="11" maxlength="11" title="' . __('Limits the number of queries the user may send to the server per hour.') . '" />' . "\n"
706 . ' </div>' . "\n"
707 . ' <div class="item">' . "\n"
708 . ' <label for="text_max_updates"><tt><dfn title="'
709 . __('Limits the number of commands that change any table or database the user may execute per hour.') . '">MAX UPDATES PER HOUR</dfn></tt></label>' . "\n"
710 . ' <input type="text" name="max_updates" id="text_max_updates" value="'
711 . $row['max_updates'] . '" size="11" maxlength="11" title="' . __('Limits the number of commands that change any table or database the user may execute per hour.') . '" />' . "\n"
712 . ' </div>' . "\n"
713 . ' <div class="item">' . "\n"
714 . ' <label for="text_max_connections"><tt><dfn title="'
715 . __('Limits the number of new connections the user may open per hour.') . '">MAX CONNECTIONS PER HOUR</dfn></tt></label>' . "\n"
716 . ' <input type="text" name="max_connections" id="text_max_connections" value="'
717 . $row['max_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of new connections the user may open per hour.') . '" />' . "\n"
718 . ' </div>' . "\n"
719 . ' <div class="item">' . "\n"
720 . ' <label for="text_max_user_connections"><tt><dfn title="'
721 . __('Limits the number of simultaneous connections the user may have.') . '">MAX USER_CONNECTIONS</dfn></tt></label>' . "\n"
722 . ' <input type="text" name="max_user_connections" id="text_max_user_connections" value="'
723 . $row['max_user_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of simultaneous connections the user may have.') . '" />' . "\n"
724 . ' </div>' . "\n"
725 . ' </fieldset>' . "\n";
727 // for Safari 2.0.2
728 echo ' <div class="clearfloat"></div>' . "\n";
730 echo '</fieldset>' . "\n";
731 if ($submit) {
732 echo '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">' . "\n"
733 . ' <input type="submit" name="update_privs" value="' . __('Go') . '" />' . "\n"
734 . '</fieldset>' . "\n";
736 } // end of the 'PMA_displayPrivTable()' function
740 * Displays the fields used by the "new user" form as well as the
741 * "change login information / copy user" form.
743 * @param string $mode are we creating a new user or are we just
744 * changing one? (allowed values: 'new', 'change')
745 * @global array $cfg the phpMyAdmin configuration
746 * @global ressource $user_link the database connection
748 * @return void
750 function PMA_displayLoginInformationFields($mode = 'new')
752 // Get user/host name lengths
753 $fields_info = PMA_DBI_get_columns('mysql', 'user', true);
754 $username_length = 16;
755 $hostname_length = 41;
756 foreach ($fields_info as $val) {
757 if ($val['Field'] == 'User') {
758 strtok($val['Type'], '()');
759 $v = strtok('()');
760 if (is_int($v)) {
761 $username_length = $v;
763 } elseif ($val['Field'] == 'Host') {
764 strtok($val['Type'], '()');
765 $v = strtok('()');
766 if (is_int($v)) {
767 $hostname_length = $v;
771 unset($fields_info);
773 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
774 $GLOBALS['pred_username'] = 'any';
776 echo '<fieldset id="fieldset_add_user_login">' . "\n"
777 . '<legend>' . __('Login Information') . '</legend>' . "\n"
778 . '<div class="item">' . "\n"
779 . '<label for="select_pred_username">' . "\n"
780 . ' ' . __('User name') . ':' . "\n"
781 . '</label>' . "\n"
782 . '<span class="options">' . "\n"
783 . ' <select name="pred_username" id="select_pred_username" title="' . __('User name') . '"' . "\n"
784 . ' onchange="if (this.value == \'any\') { username.value = \'\'; } else if (this.value == \'userdefined\') { username.focus(); username.select(); }">' . "\n"
785 . ' <option value="any"' . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any') ? ' selected="selected"' : '') . '>' . __('Any user') . '</option>' . "\n"
786 . ' <option value="userdefined"' . ((! isset($GLOBALS['pred_username']) || $GLOBALS['pred_username'] == 'userdefined') ? ' selected="selected"' : '') . '>' . __('Use text field') . ':</option>' . "\n"
787 . ' </select>' . "\n"
788 . '</span>' . "\n"
789 . '<input type="text" name="username" maxlength="'
790 . $username_length . '" title="' . __('User name') . '"'
791 . (empty($GLOBALS['username'])
792 ? ''
793 : ' value="' . htmlspecialchars(isset($GLOBALS['new_username'])
794 ? $GLOBALS['new_username']
795 : $GLOBALS['username']) . '"')
796 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
797 . '</div>' . "\n"
798 . '<div class="item">' . "\n"
799 . '<label for="select_pred_hostname">' . "\n"
800 . ' ' . __('Host') . ':' . "\n"
801 . '</label>' . "\n"
802 . '<span class="options">' . "\n"
803 . ' <select name="pred_hostname" id="select_pred_hostname" title="' . __('Host') . '"' . "\n";
804 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
805 if (! empty($_current_user)) {
806 $thishost = str_replace("'", '', substr($_current_user, (strrpos($_current_user, '@') + 1)));
807 if ($thishost == 'localhost' || $thishost == '127.0.0.1') {
808 unset($thishost);
811 echo ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } else if (this.value == \'localhost\') { hostname.value = \'localhost\'; } '
812 . (empty($thishost) ? '' : 'else if (this.value == \'thishost\') { hostname.value = \'' . addslashes(htmlspecialchars($thishost)) . '\'; } ')
813 . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } else if (this.value == \'userdefined\') { hostname.focus(); hostname.select(); }">' . "\n";
814 unset($_current_user);
816 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
817 if (! isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
818 switch (strtolower($GLOBALS['hostname'])) {
819 case 'localhost':
820 case '127.0.0.1':
821 $GLOBALS['pred_hostname'] = 'localhost';
822 break;
823 case '%':
824 $GLOBALS['pred_hostname'] = 'any';
825 break;
826 default:
827 $GLOBALS['pred_hostname'] = 'userdefined';
828 break;
831 echo ' <option value="any"'
832 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
833 ? ' selected="selected"' : '') . '>' . __('Any host')
834 . '</option>' . "\n"
835 . ' <option value="localhost"'
836 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'localhost')
837 ? ' selected="selected"' : '') . '>' . __('Local')
838 . '</option>' . "\n";
839 if (!empty($thishost)) {
840 echo ' <option value="thishost"'
841 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'thishost')
842 ? ' selected="selected"' : '') . '>' . __('This Host')
843 . '</option>' . "\n";
845 unset($thishost);
846 echo ' <option value="hosttable"'
847 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'hosttable')
848 ? ' selected="selected"' : '') . '>' . __('Use Host Table')
849 . '</option>' . "\n"
850 . ' <option value="userdefined"'
851 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'userdefined')
852 ? ' selected="selected"' : '')
853 . '>' . __('Use text field') . ':</option>' . "\n"
854 . ' </select>' . "\n"
855 . '</span>' . "\n"
856 . '<input type="text" name="hostname" maxlength="'
857 . $hostname_length . '" value="'
858 . htmlspecialchars(isset($GLOBALS['hostname']) ? $GLOBALS['hostname'] : '')
859 . '" title="' . __('Host')
860 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
861 . PMA_showHint(__('When Host table is used, this field is ignored and values stored in Host table are used instead.'))
862 . '</div>' . "\n"
863 . '<div class="item">' . "\n"
864 . '<label for="select_pred_password">' . "\n"
865 . ' ' . __('Password') . ':' . "\n"
866 . '</label>' . "\n"
867 . '<span class="options">' . "\n"
868 . ' <select name="pred_password" id="select_pred_password" title="'
869 . __('Password') . '"' . "\n"
870 . ' onchange="if (this.value == \'none\') { pma_pw.value = \'\'; pma_pw2.value = \'\'; } else if (this.value == \'userdefined\') { pma_pw.focus(); pma_pw.select(); }">' . "\n"
871 . ($mode == 'change' ? ' <option value="keep" selected="selected">' . __('Do not change the password') . '</option>' . "\n" : '')
872 . ' <option value="none"';
873 if (isset($GLOBALS['username']) && $mode != 'change') {
874 echo ' selected="selected"';
876 echo '>' . __('No Password') . '</option>' . "\n"
877 . ' <option value="userdefined"' . (isset($GLOBALS['username']) ? '' : ' selected="selected"') . '>' . __('Use text field') . ':</option>' . "\n"
878 . ' </select>' . "\n"
879 . '</span>' . "\n"
880 . '<input type="password" id="text_pma_pw" name="pma_pw" title="' . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
881 . '</div>' . "\n"
882 . '<div class="item" id="div_element_before_generate_password">' . "\n"
883 . '<label for="text_pma_pw2">' . "\n"
884 . ' ' . __('Re-type') . ':' . "\n"
885 . '</label>' . "\n"
886 . '<span class="options">&nbsp;</span>' . "\n"
887 . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="' . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
888 . '</div>' . "\n"
889 // Generate password added here via jQuery
890 . '</fieldset>' . "\n";
891 } // end of the 'PMA_displayUserAndHostFields()' function
894 * Changes / copies a user, part I
896 if (isset($_REQUEST['change_copy'])) {
897 $user_host_condition =
898 ' WHERE `User`'
899 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
900 .' AND `Host`'
901 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
902 $row = PMA_DBI_fetch_single_row('SELECT * FROM `mysql`.`user` ' . $user_host_condition);
903 if (! $row) {
904 PMA_Message::notice(__('No user found.'))->display();
905 unset($_REQUEST['change_copy']);
906 } else {
907 extract($row, EXTR_OVERWRITE);
908 // Recent MySQL versions have the field "Password" in mysql.user,
909 // so the previous extract creates $Password but this script
910 // uses $password
911 if (! isset($password) && isset($Password)) {
912 $password = $Password;
914 $queries = array();
920 * Adds a user
921 * (Changes / copies a user, part II)
923 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
924 $sql_query = '';
925 if ($pred_username == 'any') {
926 $username = '';
928 switch ($pred_hostname) {
929 case 'any':
930 $hostname = '%';
931 break;
932 case 'localhost':
933 $hostname = 'localhost';
934 break;
935 case 'hosttable':
936 $hostname = '';
937 break;
938 case 'thishost':
939 $_user_name = PMA_DBI_fetch_value('SELECT USER()');
940 $hostname = substr($_user_name, (strrpos($_user_name, '@') + 1));
941 unset($_user_name);
942 break;
944 $sql = "SELECT '1' FROM `mysql`.`user`"
945 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
946 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
947 if (PMA_DBI_fetch_value($sql) == 1) {
948 $message = PMA_Message::error(__('The user %s already exists!'));
949 $message->addParam('[i]\'' . $username . '\'@\'' . $hostname . '\'[/i]');
950 $_REQUEST['adduser'] = true;
951 $_add_user_error = true;
952 } else {
954 $create_user_real = 'CREATE USER \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
956 $real_sql_query =
957 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
958 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
959 if ($pred_password != 'none' && $pred_password != 'keep') {
960 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
961 $real_sql_query .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
962 if (isset($create_user_real)) {
963 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
964 $create_user_real .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
966 } else {
967 if ($pred_password == 'keep' && !empty($password)) {
968 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
969 if (isset($create_user_real)) {
970 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
973 $sql_query = $real_sql_query;
974 if (isset($create_user_real)) {
975 $create_user_show = $create_user_real;
979 * @todo similar code appears twice in this script
981 if ((isset($Grant_priv) && $Grant_priv == 'Y')
982 || (isset($max_questions) || isset($max_connections)
983 || isset($max_updates) || isset($max_user_connections))) {
984 $real_sql_query .= ' WITH';
985 $sql_query .= ' WITH';
986 if (isset($Grant_priv) && $Grant_priv == 'Y') {
987 $real_sql_query .= ' GRANT OPTION';
988 $sql_query .= ' GRANT OPTION';
990 if (isset($max_questions)) {
991 // avoid negative values
992 $max_questions = max(0, (int)$max_questions);
993 $real_sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
994 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
996 if (isset($max_connections)) {
997 $max_connections = max(0, (int)$max_connections);
998 $real_sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
999 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1001 if (isset($max_updates)) {
1002 $max_updates = max(0, (int)$max_updates);
1003 $real_sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1004 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1006 if (isset($max_user_connections)) {
1007 $max_user_connections = max(0, (int)$max_user_connections);
1008 $real_sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1009 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1012 if (isset($create_user_real)) {
1013 $create_user_real .= ';';
1014 $create_user_show .= ';';
1016 $real_sql_query .= ';';
1017 $sql_query .= ';';
1018 if (empty($_REQUEST['change_copy'])) {
1019 $_error = false;
1021 if (isset($create_user_real)) {
1022 if (! PMA_DBI_try_query($create_user_real)) {
1023 $_error = true;
1025 $sql_query = $create_user_show . $sql_query;
1028 if ($_error || ! PMA_DBI_try_query($real_sql_query)) {
1029 $_REQUEST['createdb'] = false;
1030 $message = PMA_Message::rawError(PMA_DBI_getError());
1031 } else {
1032 $message = PMA_Message::success(__('You have added a new user.'));
1035 switch (PMA_ifSetOr($_REQUEST['createdb'], '0')) {
1036 case '1' :
1037 // Create database with same name and grant all privileges
1038 $q = 'CREATE DATABASE IF NOT EXISTS '
1039 . PMA_backquote(PMA_sqlAddSlashes($username)) . ';';
1040 $sql_query .= $q;
1041 if (! PMA_DBI_try_query($q)) {
1042 $message = PMA_Message::rawError(PMA_DBI_getError());
1043 break;
1048 * If we are not in an Ajax request, we can't reload navigation now
1050 if ($GLOBALS['is_ajax_request'] != true) {
1051 // this is needed in case tracking is on:
1052 $GLOBALS['db'] = $username;
1053 $GLOBALS['reload'] = true;
1054 PMA_reloadNavigation();
1057 $q = 'GRANT ALL PRIVILEGES ON '
1058 . PMA_backquote(PMA_sqlAddSlashes($username)) . '.* TO \''
1059 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1060 $sql_query .= $q;
1061 if (! PMA_DBI_try_query($q)) {
1062 $message = PMA_Message::rawError(PMA_DBI_getError());
1064 break;
1065 case '2' :
1066 // Grant all privileges on wildcard name (username\_%)
1067 $q = 'GRANT ALL PRIVILEGES ON '
1068 . PMA_backquote(PMA_sqlAddSlashes($username) . '\_%') . '.* TO \''
1069 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1070 $sql_query .= $q;
1071 if (! PMA_DBI_try_query($q)) {
1072 $message = PMA_Message::rawError(PMA_DBI_getError());
1074 break;
1075 case '3' :
1076 // Grant all privileges on the specified database to the new user
1077 $q = 'GRANT ALL PRIVILEGES ON '
1078 . PMA_backquote(PMA_sqlAddSlashes($dbname)) . '.* TO \''
1079 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1080 $sql_query .= $q;
1081 if (! PMA_DBI_try_query($q)) {
1082 $message = PMA_Message::rawError(PMA_DBI_getError());
1084 break;
1085 case '0' :
1086 default :
1087 break;
1089 } else {
1090 if (isset($create_user_real)) {
1091 $queries[] = $create_user_real;
1093 $queries[] = $real_sql_query;
1094 // we put the query containing the hidden password in
1095 // $queries_for_display, at the same position occupied
1096 // by the real query in $queries
1097 $tmp_count = count($queries);
1098 if (isset($create_user_real)) {
1099 $queries_for_display[$tmp_count - 2] = $create_user_show;
1101 $queries_for_display[$tmp_count - 1] = $sql_query;
1103 unset($res, $real_sql_query);
1109 * Changes / copies a user, part III
1111 if (isset($_REQUEST['change_copy'])) {
1112 $user_host_condition =
1113 ' WHERE `User`'
1114 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1115 .' AND `Host`'
1116 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
1117 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1118 while ($row = PMA_DBI_fetch_assoc($res)) {
1119 $queries[] =
1120 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1121 .' ON ' . PMA_backquote($row['Db']) . '.*'
1122 .' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1123 . ($row['Grant_priv'] == 'Y' ? ' WITH GRANT OPTION;' : ';');
1125 PMA_DBI_free_result($res);
1126 $res = PMA_DBI_query(
1127 'SELECT `Db`, `Table_name`, `Table_priv`'
1128 .' FROM `mysql`.`tables_priv`' . $user_host_condition,
1129 $GLOBALS['userlink'], PMA_DBI_QUERY_STORE);
1130 while ($row = PMA_DBI_fetch_assoc($res)) {
1132 $res2 = PMA_DBI_QUERY(
1133 'SELECT `Column_name`, `Column_priv`'
1134 .' FROM `mysql`.`columns_priv`'
1135 .' WHERE `User`'
1136 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1137 .' AND `Host`'
1138 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\''
1139 .' AND `Db`'
1140 .' = \'' . PMA_sqlAddSlashes($row['Db']) . "'"
1141 .' AND `Table_name`'
1142 .' = \'' . PMA_sqlAddSlashes($row['Table_name']) . "'"
1143 .';',
1144 null, PMA_DBI_QUERY_STORE);
1146 $tmp_privs1 = PMA_extractPrivInfo($row);
1147 $tmp_privs2 = array(
1148 'Select' => array(),
1149 'Insert' => array(),
1150 'Update' => array(),
1151 'References' => array()
1154 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1155 $tmp_array = explode(',', $row2['Column_priv']);
1156 if (in_array('Select', $tmp_array)) {
1157 $tmp_privs2['Select'][] = $row2['Column_name'];
1159 if (in_array('Insert', $tmp_array)) {
1160 $tmp_privs2['Insert'][] = $row2['Column_name'];
1162 if (in_array('Update', $tmp_array)) {
1163 $tmp_privs2['Update'][] = $row2['Column_name'];
1165 if (in_array('References', $tmp_array)) {
1166 $tmp_privs2['References'][] = $row2['Column_name'];
1168 unset($tmp_array);
1170 if (count($tmp_privs2['Select']) > 0 && !in_array('SELECT', $tmp_privs1)) {
1171 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1173 if (count($tmp_privs2['Insert']) > 0 && !in_array('INSERT', $tmp_privs1)) {
1174 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1176 if (count($tmp_privs2['Update']) > 0 && !in_array('UPDATE', $tmp_privs1)) {
1177 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1179 if (count($tmp_privs2['References']) > 0 && !in_array('REFERENCES', $tmp_privs1)) {
1180 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1182 unset($tmp_privs2);
1183 $queries[] =
1184 'GRANT ' . join(', ', $tmp_privs1)
1185 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1186 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1187 . (in_array('Grant', explode(',', $row['Table_priv'])) ? ' WITH GRANT OPTION;' : ';');
1193 * Updates privileges
1195 if (!empty($update_privs)) {
1196 $db_and_table = PMA_wildcardEscapeForGrant($dbname, (isset($tablename) ? $tablename : ''));
1198 $sql_query0 =
1199 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1200 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1201 if (! isset($Grant_priv) || $Grant_priv != 'Y') {
1202 $sql_query1 =
1203 'REVOKE GRANT OPTION ON ' . $db_and_table
1204 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1205 } else {
1206 $sql_query1 = '';
1209 // Should not do a GRANT USAGE for a table-specific privilege, it
1210 // causes problems later (cannot revoke it)
1211 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1212 $sql_query2 =
1213 'GRANT ' . join(', ', PMA_extractPrivInfo())
1214 . ' ON ' . $db_and_table
1215 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
1218 * @todo similar code appears twice in this script
1220 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1221 || (! isset($dbname)
1222 && (isset($max_questions) || isset($max_connections)
1223 || isset($max_updates) || isset($max_user_connections))))
1225 $sql_query2 .= 'WITH';
1226 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1227 $sql_query2 .= ' GRANT OPTION';
1229 if (isset($max_questions)) {
1230 $max_questions = max(0, (int)$max_questions);
1231 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1233 if (isset($max_connections)) {
1234 $max_connections = max(0, (int)$max_connections);
1235 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1237 if (isset($max_updates)) {
1238 $max_updates = max(0, (int)$max_updates);
1239 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1241 if (isset($max_user_connections)) {
1242 $max_user_connections = max(0, (int)$max_user_connections);
1243 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1246 $sql_query2 .= ';';
1248 if (! PMA_DBI_try_query($sql_query0)) {
1249 // This might fail when the executing user does not have ALL PRIVILEGES himself.
1250 // See https://sourceforge.net/tracker/index.php?func=detail&aid=3285929&group_id=23067&atid=377408
1251 $sql_query0 = '';
1253 if (isset($sql_query1) && !PMA_DBI_try_query($sql_query1)) {
1254 // this one may fail, too...
1255 $sql_query1 = '';
1257 if (isset($sql_query2)) {
1258 PMA_DBI_query($sql_query2);
1259 } else {
1260 $sql_query2 = '';
1262 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1263 $message = PMA_Message::success(__('You have updated the privileges for %s.'));
1264 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1269 * Revokes Privileges
1271 if (isset($_REQUEST['revokeall'])) {
1272 $db_and_table = PMA_wildcardEscapeForGrant($dbname, isset($tablename) ? $tablename : '');
1274 $sql_query0 =
1275 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1276 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1277 $sql_query1 =
1278 'REVOKE GRANT OPTION ON ' . $db_and_table
1279 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1281 PMA_DBI_query($sql_query0);
1282 if (! PMA_DBI_try_query($sql_query1)) {
1283 // this one may fail, too...
1284 $sql_query1 = '';
1286 $sql_query = $sql_query0 . ' ' . $sql_query1;
1287 $message = PMA_Message::success(__('You have revoked the privileges for %s'));
1288 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1289 if (! isset($tablename)) {
1290 unset($dbname);
1291 } else {
1292 unset($tablename);
1298 * Updates the password
1300 if (isset($_REQUEST['change_pw'])) {
1301 // similar logic in user_password.php
1302 $message = '';
1304 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1305 if ($pma_pw != $pma_pw2) {
1306 $message = PMA_Message::error(__('The passwords aren\'t the same!'));
1307 } elseif (empty($pma_pw) || empty($pma_pw2)) {
1308 $message = PMA_Message::error(__('The password is empty!'));
1310 } // end if
1312 // here $nopass could be == 1
1313 if (empty($message)) {
1315 $hashing_function = (!empty($pw_hash) && $pw_hash == 'old' ? 'OLD_' : '')
1316 . 'PASSWORD';
1318 // in $sql_query which will be displayed, hide the password
1319 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1320 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . PMA_sqlAddSlashes($pma_pw) . '\')');
1321 PMA_DBI_try_query($local_query)
1322 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, false, $err_url);
1323 $message = PMA_Message::success(__('The password for %s was changed successfully.'));
1324 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1330 * Deletes users
1331 * (Changes / copies a user, part IV)
1334 if (isset($_REQUEST['delete']) || (isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1335 if (isset($_REQUEST['change_copy'])) {
1336 $selected_usr = array($old_username . '&amp;#27;' . $old_hostname);
1337 } else {
1338 $selected_usr = $_REQUEST['selected_usr'];
1339 $queries = array();
1341 foreach ($selected_usr as $each_user) {
1342 list($this_user, $this_host) = explode('&amp;#27;', $each_user);
1343 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1344 $queries[] = 'DROP USER \'' . PMA_sqlAddSlashes($this_user) . '\'@\'' . PMA_sqlAddSlashes($this_host) . '\';';
1346 if (isset($_REQUEST['drop_users_db'])) {
1347 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1348 $GLOBALS['reload'] = true;
1350 if ($GLOBALS['is_ajax_request'] != true) {
1351 PMA_reloadNavigation();
1355 if (empty($_REQUEST['change_copy'])) {
1356 if (empty($queries)) {
1357 $message = PMA_Message::error(__('No users selected for deleting!'));
1358 } else {
1359 if ($_REQUEST['mode'] == 3) {
1360 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1361 $queries[] = 'FLUSH PRIVILEGES;';
1363 $drop_user_error = '';
1364 foreach ($queries as $sql_query) {
1365 if ($sql_query{0} != '#') {
1366 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1367 $drop_user_error .= PMA_DBI_getError() . "\n";
1371 // tracking sets this, causing the deleted db to be shown in navi
1372 unset($GLOBALS['db']);
1374 $sql_query = join("\n", $queries);
1375 if (! empty($drop_user_error)) {
1376 $message = PMA_Message::rawError($drop_user_error);
1377 } else {
1378 $message = PMA_Message::success(__('The selected users have been deleted successfully.'));
1381 unset($queries);
1387 * Changes / copies a user, part V
1389 if (isset($_REQUEST['change_copy'])) {
1390 $tmp_count = 0;
1391 foreach ($queries as $sql_query) {
1392 if ($sql_query{0} != '#') {
1393 PMA_DBI_query($sql_query);
1395 // when there is a query containing a hidden password, take it
1396 // instead of the real query sent
1397 if (isset($queries_for_display[$tmp_count])) {
1398 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1400 $tmp_count++;
1402 $message = PMA_Message::success();
1403 $sql_query = join("\n", $queries);
1408 * Reloads the privilege tables into memory
1410 if (isset($_REQUEST['flush_privileges'])) {
1411 $sql_query = 'FLUSH PRIVILEGES;';
1412 PMA_DBI_query($sql_query);
1413 $message = PMA_Message::success(__('The privileges were reloaded successfully.'));
1417 * defines some standard links
1419 $link_edit = '<a class="edit_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . $GLOBALS['url_query']
1420 . '&amp;username=%s'
1421 . '&amp;hostname=%s'
1422 . '&amp;dbname=%s'
1423 . '&amp;tablename=%s">'
1424 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1425 . '</a>';
1427 $link_revoke = '<a href="server_privileges.php?' . $GLOBALS['url_query']
1428 . '&amp;username=%s'
1429 . '&amp;hostname=%s'
1430 . '&amp;dbname=%s'
1431 . '&amp;tablename=%s'
1432 . '&amp;revokeall=1">'
1433 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1434 . '</a>';
1436 $link_export = '<a class="export_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . $GLOBALS['url_query']
1437 . '&amp;username=%s'
1438 . '&amp;hostname=%s'
1439 . '&amp;initial=%s'
1440 . '&amp;export=1">'
1441 . PMA_getIcon('b_tblexport.png', __('Export'))
1442 . '</a>';
1445 * If we are in an Ajax request for Create User/Edit User/Revoke User/Flush Privileges,
1446 * show $message and exit.
1448 if ($GLOBALS['is_ajax_request'] && ! isset($_REQUEST['export']) && (! isset($_REQUEST['adduser']) || $_add_user_error) && ! isset($_REQUEST['initial']) && ! isset($_REQUEST['showall']) && ! isset($_REQUEST['edit_user_dialog']) && ! isset($_REQUEST['db_specific'])) {
1450 if (isset($sql_query)) {
1451 $extra_data['sql_query'] = PMA_showMessage(NULL, $sql_query);
1454 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
1456 * generate html on the fly for the new user that was just created.
1458 $new_user_string = '<tr>'."\n"
1459 .'<td> <input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_" value="' . htmlspecialchars($username) . '&amp;#27;' . htmlspecialchars($hostname) . '" /> </td>'."\n"
1460 .'<td><label for="checkbox_sel_users_">' . (empty($username) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($username) ) . '</label></td>' . "\n"
1461 .'<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
1462 $new_user_string .= '<td>';
1464 if (!empty($password) || isset($pma_pw)) {
1465 $new_user_string .= __('Yes');
1467 else {
1468 $new_user_string .= '<span style="color: #FF0000">' . __('No') . '</span>';
1471 $new_user_string .= '</td>'."\n";
1472 $new_user_string .= '<td><tt>' . join(', ', PMA_extractPrivInfo('', true)) . '</tt></td>'; //Fill in privileges here
1473 $new_user_string .= '<td>';
1475 if ((isset($Grant_priv) && $Grant_priv == 'Y')) {
1476 $new_user_string .= __('Yes');
1478 else {
1479 $new_user_string .= __('No');
1482 $new_user_string .='</td>';
1484 $new_user_string .= '<td>'.sprintf($link_edit, urlencode($username), urlencode($hostname), '', '' ).'</td>'."\n";
1485 $new_user_string .= '<td>'.sprintf($link_export, urlencode($username), urlencode($hostname), (isset($initial) ? $initial : '')).'</td>'."\n";
1487 $new_user_string .= '</tr>';
1489 $extra_data['new_user_string'] = $new_user_string;
1492 * Generate the string for this alphabet's initial, to update the user
1493 * pagination
1495 $new_user_initial = strtoupper(substr($username, 0, 1));
1496 $new_user_initial_string = '<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . $new_user_initial
1497 .'">' . $new_user_initial . '</a>';
1498 $extra_data['new_user_initial'] = $new_user_initial;
1499 $extra_data['new_user_initial_string'] = $new_user_initial_string;
1502 if (isset($update_privs)) {
1503 $extra_data['db_specific_privs'] = false;
1504 if (isset($dbname_is_wildcard)) {
1505 $extra_data['db_specific_privs'] = !$dbname_is_wildcard;
1507 $new_privileges = join(', ', PMA_extractPrivInfo('', true));
1509 $extra_data['new_privileges'] = $new_privileges;
1512 if ($message instanceof PMA_Message) {
1513 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
1518 * Displays the links
1520 if (isset($viewing_mode) && $viewing_mode == 'db') {
1521 $db = $checkprivs;
1522 $url_query .= '&amp;goto=db_operations.php';
1524 // Gets the database structure
1525 $sub_part = '_structure';
1526 require './libraries/db_info.inc.php';
1527 echo "\n";
1528 } else {
1529 require './libraries/server_links.inc.php';
1534 * Displays the page
1537 // export user definition
1538 if (isset($_REQUEST['export'])) {
1539 echo '<h2>' . __('User') . ' \'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'</h2>';
1540 echo '<textarea cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1541 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddSlashes($username) . "'@'" . PMA_sqlAddSlashes($hostname) . "'");
1542 foreach ($grants as $one_grant) {
1543 echo $one_grant . ";\n\n";
1545 echo '</textarea>';
1546 unset($username, $hostname, $grants, $one_grant);
1547 if ($GLOBALS['is_ajax_request']) {
1548 exit;
1552 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs))) {
1553 if (! isset($username)) {
1554 // No username is given --> display the overview
1555 echo '<h2>' . "\n"
1556 . PMA_getIcon('b_usrlist.png')
1557 . __('User overview') . "\n"
1558 . '</h2>' . "\n";
1560 $sql_query =
1561 'SELECT *,' .
1562 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1563 ' FROM `mysql`.`user`';
1565 $sql_query .= (isset($initial) ? PMA_rangeOfUsers($initial) : '');
1567 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1568 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1570 if (! $res) {
1571 // the query failed! This may have two reasons:
1572 // - the user does not have enough privileges
1573 // - the privilege tables use a structure of an earlier version.
1574 // so let's try a more simple query
1576 $sql_query = 'SELECT * FROM `mysql`.`user`';
1577 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1579 if (!$res) {
1580 PMA_Message::error(__('No Privileges'))->display();
1581 PMA_DBI_free_result($res);
1582 unset($res);
1583 } else {
1584 // This message is hardcoded because I will replace it by
1585 // a automatic repair feature soon.
1586 $raw = 'Your privilege table structure seems to be older than'
1587 . ' this MySQL version!<br />'
1588 . 'Please run the <tt>mysql_upgrade</tt> command'
1589 . '(<tt>mysql_fix_privilege_tables</tt> on older systems)'
1590 . ' that should be included in your MySQL server distribution'
1591 . ' to solve this problem!';
1592 PMA_Message::rawError($raw)->display();
1594 } else {
1596 // we also want users not in table `user` but in other table
1597 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1599 $tables_to_search_for_users = array(
1600 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1603 $db_rights_sqls = array();
1604 foreach ($tables_to_search_for_users as $table_search_in) {
1605 if (in_array($table_search_in, $tables)) {
1606 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ? PMA_rangeOfUsers($initial) : '');
1610 $user_defaults = array(
1611 'User' => '',
1612 'Host' => '%',
1613 'Password' => '?',
1614 'Grant_priv' => 'N',
1615 'privs' => array('USAGE'),
1618 // for all initials, even non A-Z
1619 $array_initials = array();
1620 // for the rights
1621 $db_rights = array();
1623 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1624 .' ORDER BY `User` ASC, `Host` ASC';
1626 $db_rights_result = PMA_DBI_query($db_rights_sql);
1628 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1629 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1630 $db_rights[$db_rights_row['User']][$db_rights_row['Host']] =
1631 $db_rights_row;
1633 PMA_DBI_free_result($db_rights_result);
1634 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1635 ksort($db_rights);
1638 * Displays the initials
1639 * In an Ajax request, we don't need to show this. Also not necassary if there is less than 20 privileges
1642 if ($GLOBALS['is_ajax_request'] != true && PMA_DBI_num_rows($res) > 20 ) {
1644 // initialize to false the letters A-Z
1645 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++) {
1646 if (! isset($array_initials[chr($letter_counter + 64)])) {
1647 $array_initials[chr($letter_counter + 64)] = false;
1651 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE);
1652 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1653 $array_initials[$tmp_initial] = true;
1656 // Display the initials, which can be any characters, not
1657 // just letters. For letters A-Z, we add the non-used letters
1658 // as greyed out.
1660 uksort($array_initials, "strnatcasecmp");
1662 echo '<table id="initials_table" class="' . $conditional_class . '" <cellspacing="5"><tr>';
1663 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1664 if ($initial_was_found) {
1665 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1666 } else {
1667 echo '<td>' . $tmp_initial . '</td>';
1670 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;showall=1" class="nowrap">[' . __('Show all') . ']</a></td>' . "\n";
1671 echo '</tr></table>';
1675 * Display the user overview
1676 * (if less than 50 users, display them immediately)
1679 if (isset($initial) || isset($showall) || PMA_DBI_num_rows($res) < 50) {
1681 while ($row = PMA_DBI_fetch_assoc($res)) {
1682 $row['privs'] = PMA_extractPrivInfo($row, true);
1683 $db_rights[$row['User']][$row['Host']] = $row;
1685 @PMA_DBI_free_result($res);
1686 unset($res);
1688 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1689 . PMA_generate_common_hidden_inputs('', '')
1690 . ' <table id="tableuserrights" class="data">' . "\n"
1691 . ' <thead>' . "\n"
1692 . ' <tr><th></th>' . "\n"
1693 . ' <th>' . __('User') . '</th>' . "\n"
1694 . ' <th>' . __('Host') . '</th>' . "\n"
1695 . ' <th>' . __('Password') . '</th>' . "\n"
1696 . ' <th>' . __('Global privileges') . ' '
1697 . PMA_showHint(__('Note: MySQL privilege names are expressed in English')) . '</th>' . "\n"
1698 . ' <th>' . __('Grant') . '</th>' . "\n"
1699 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1700 echo ' </tr>' . "\n";
1701 echo ' </thead>' . "\n";
1702 echo ' <tbody>' . "\n";
1703 $odd_row = true;
1704 $index_checkbox = -1;
1705 foreach ($db_rights as $user) {
1706 $index_checkbox++;
1707 ksort($user);
1708 foreach ($user as $host) {
1709 $index_checkbox++;
1710 echo ' <tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
1711 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1712 . $index_checkbox . '" value="'
1713 . htmlspecialchars($host['User'] . '&amp;#27;' . $host['Host'])
1714 . '"'
1715 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
1716 . ' /></td>' . "\n"
1717 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1718 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1719 echo ' <td>';
1720 switch ($host['Password']) {
1721 case 'Y':
1722 echo __('Yes');
1723 break;
1724 case 'N':
1725 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1726 break;
1727 // this happens if this is a definition not coming from mysql.user
1728 default:
1729 echo '--'; // in future version, replace by "not present"
1730 break;
1731 } // end switch
1732 echo '</td>' . "\n"
1733 . ' <td><tt>' . "\n"
1734 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1735 . ' </tt></td>' . "\n"
1736 . ' <td>' . ($host['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . '</td>' . "\n"
1737 . ' <td align="center">';
1738 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1739 echo '</td>';
1740 echo '<td align="center">';
1741 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ? $initial : ''));
1742 echo '</td>';
1743 echo '</tr>';
1744 $odd_row = ! $odd_row;
1748 unset($user, $host, $odd_row);
1749 echo ' </tbody></table>' . "\n"
1750 .'<img class="selectallarrow"'
1751 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1752 .' width="38" height="22"'
1753 .' alt="' . __('With selected:') . '" />' . "\n"
1754 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;checkall=1"'
1755 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1756 . __('Check All') . '</a>' . "\n"
1757 .'/' . "\n"
1758 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1759 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1760 . __('Uncheck All') . '</a>' . "\n";
1762 // add/delete user fieldset
1763 echo ' <fieldset id="fieldset_add_user">' . "\n"
1764 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1765 . PMA_getIcon('b_usradd.png')
1766 . ' ' . __('Add user') . '</a>' . "\n"
1767 . ' </fieldset>' . "\n"
1768 . ' <fieldset id="fieldset_delete_user">'
1769 . ' <legend>' . "\n"
1770 . PMA_getIcon('b_usrdrop.png')
1771 . ' ' . __('Remove selected users') . '' . "\n"
1772 . ' </legend>' . "\n"
1773 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1774 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1775 . ' <input type="checkbox" title="' . __('Drop the databases that have the same names as the users.') . '" name="drop_users_db" id="checkbox_drop_users_db" />' . "\n"
1776 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1777 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1778 . ' </label>' . "\n"
1779 . ' </fieldset>' . "\n"
1780 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1781 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" class="' . $conditional_class . '"/>' . "\n"
1782 . ' </fieldset>' . "\n"
1783 . '</form>' . "\n";
1784 } else {
1786 unset ($row);
1787 echo ' <fieldset id="fieldset_add_user">' . "\n"
1788 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1789 . PMA_getIcon('b_usradd.png')
1790 . ' ' . __('Add user') . '</a>' . "\n"
1791 . ' </fieldset>' . "\n";
1792 } // end if (display overview)
1794 if ($GLOBALS['is_ajax_request']) {
1795 exit;
1798 $flushnote = new PMA_Message(__('Note: phpMyAdmin gets the users\' privileges directly from MySQL\'s privilege tables. The content of these tables may differ from the privileges the server uses, if they have been changed manually. In this case, you should %sreload the privileges%s before you continue.'), PMA_Message::NOTICE);
1799 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;flush_privileges=1" id="reload_privileges_anchor" class="' . $conditional_class . '">', false);
1800 $flushnote->addParam('</a>', false);
1801 $flushnote->display();
1805 } else {
1807 // A user was selected -> display the user's properties
1809 // In an Ajax request, prevent cached values from showing
1810 if ($GLOBALS['is_ajax_request'] == true) {
1811 header('Cache-Control: no-cache');
1814 echo '<h2>' . "\n"
1815 . PMA_getIcon('b_usredit.png')
1816 . __('Edit Privileges') . ': '
1817 . __('User') ;
1819 if (isset($dbname)) {
1820 echo ' <i><a href="server_privileges.php?'
1821 . $GLOBALS['url_query'] . '&amp;username=' . htmlspecialchars(urlencode($username))
1822 . '&amp;hostname=' . htmlspecialchars(urlencode($hostname)) . '&amp;dbname=&amp;tablename=">\''
1823 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1824 . '\'</a></i>' . "\n";
1825 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
1827 echo ' - ' . ($dbname_is_wildcard ? __('Databases') : __('Database') );
1828 if (isset($tablename)) {
1829 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
1830 . '&amp;username=' . htmlspecialchars(urlencode($username)) . '&amp;hostname=' . htmlspecialchars(urlencode($hostname))
1831 . '&amp;dbname=' . htmlspecialchars($url_dbname) . '&amp;tablename=">' . htmlspecialchars($dbname) . '</a></i>';
1832 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
1833 } else {
1834 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
1837 } else {
1838 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
1839 . '\'</i>' . "\n";
1842 echo '</h2>' . "\n";
1845 $sql = "SELECT '1' FROM `mysql`.`user`"
1846 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
1847 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
1848 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
1849 unset($sql);
1850 if ($user_does_not_exists) {
1851 PMA_Message::error(__('The selected user was not found in the privilege table.'))->display();
1852 PMA_displayLoginInformationFields();
1853 //require './libraries/footer.inc.php';
1856 echo '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n";
1857 $_params = array(
1858 'username' => $username,
1859 'hostname' => $hostname,
1861 if (isset($dbname)) {
1862 $_params['dbname'] = $dbname;
1863 if (isset($tablename)) {
1864 $_params['tablename'] = $tablename;
1867 echo PMA_generate_common_hidden_inputs($_params);
1869 PMA_displayPrivTable(PMA_ifSetOr($dbname, '*', 'length'),
1870 PMA_ifSetOr($tablename, '*', 'length'));
1872 echo '</form>' . "\n";
1874 if (! isset($tablename) && empty($dbname_is_wildcard)) {
1876 // no table name was given, display all table specific rights
1877 // but only if $dbname contains no wildcards
1879 // table header
1880 echo '<form action="server_privileges.php" method="post">' . "\n"
1881 . PMA_generate_common_hidden_inputs('', '')
1882 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
1883 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
1884 . '<fieldset>' . "\n"
1885 . '<legend>' . (! isset($dbname) ? __('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
1886 . '<table class="data">' . "\n"
1887 . '<thead>' . "\n"
1888 . '<tr><th>' . (! isset($dbname) ? __('Database') : __('Table')) . '</th>' . "\n"
1889 . ' <th>' . __('Privileges') . '</th>' . "\n"
1890 . ' <th>' . __('Grant') . '</th>' . "\n"
1891 . ' <th>' . (! isset($dbname) ? __('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
1892 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
1893 . '</tr>' . "\n"
1894 . '</thead>' . "\n"
1895 . '<tbody>' . "\n";
1897 $user_host_condition =
1898 ' WHERE `User`'
1899 . ' = \'' . PMA_sqlAddSlashes($username) . "'"
1900 . ' AND `Host`'
1901 . ' = \'' . PMA_sqlAddSlashes($hostname) . "'";
1903 // table body
1904 // get data
1906 // we also want privielgs for this user not in table `db` but in other table
1907 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1908 if (! isset($dbname)) {
1910 // no db name given, so we want all privs for the given user
1912 $tables_to_search_for_users = array(
1913 'tables_priv', 'columns_priv',
1916 $db_rights_sqls = array();
1917 foreach ($tables_to_search_for_users as $table_search_in) {
1918 if (in_array($table_search_in, $tables)) {
1919 $db_rights_sqls[] = '
1920 SELECT DISTINCT `Db`
1921 FROM `mysql`.' . PMA_backquote($table_search_in)
1922 . $user_host_condition;
1926 $user_defaults = array(
1927 'Db' => '',
1928 'Grant_priv' => 'N',
1929 'privs' => array('USAGE'),
1930 'Table_privs' => true,
1933 // for the rights
1934 $db_rights = array();
1936 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1937 .' ORDER BY `Db` ASC';
1939 $db_rights_result = PMA_DBI_query($db_rights_sql);
1941 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1942 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1943 // only Db names in the table `mysql`.`db` uses wildcards
1944 // as we are in the db specific rights display we want
1945 // all db names escaped, also from other sources
1946 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
1947 $db_rights_row['Db']);
1948 $db_rights[$db_rights_row['Db']] = $db_rights_row;
1951 PMA_DBI_free_result($db_rights_result);
1952 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1954 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
1955 $res = PMA_DBI_query($sql_query);
1956 $sql_query = '';
1958 while ($row = PMA_DBI_fetch_assoc($res)) {
1959 if (isset($db_rights[$row['Db']])) {
1960 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
1961 } else {
1962 $db_rights[$row['Db']] = $row;
1964 // there are db specific rights for this user
1965 // so we can drop this db rights
1966 $db_rights[$row['Db']]['can_delete'] = true;
1968 PMA_DBI_free_result($res);
1969 unset($row, $res);
1971 } else {
1973 // db name was given,
1974 // so we want all user specific rights for this db
1976 $user_host_condition .=
1977 ' AND `Db`'
1978 .' LIKE \'' . PMA_sqlAddSlashes($dbname, true) . "'";
1980 $tables_to_search_for_users = array(
1981 'columns_priv',
1984 $db_rights_sqls = array();
1985 foreach ($tables_to_search_for_users as $table_search_in) {
1986 if (in_array($table_search_in, $tables)) {
1987 $db_rights_sqls[] = '
1988 SELECT DISTINCT `Table_name`
1989 FROM `mysql`.' . PMA_backquote($table_search_in)
1990 . $user_host_condition;
1994 $user_defaults = array(
1995 'Table_name' => '',
1996 'Grant_priv' => 'N',
1997 'privs' => array('USAGE'),
1998 'Column_priv' => true,
2001 // for the rights
2002 $db_rights = array();
2004 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
2005 .' ORDER BY `Table_name` ASC';
2007 $db_rights_result = PMA_DBI_query($db_rights_sql);
2009 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
2010 $db_rights_row = array_merge($user_defaults, $db_rights_row);
2011 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
2013 PMA_DBI_free_result($db_rights_result);
2014 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
2016 $sql_query =
2017 'SELECT `Table_name`,'
2018 .' `Table_priv`,'
2019 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
2020 .' AS \'Column_priv\''
2021 .' FROM `mysql`.`tables_priv`'
2022 . $user_host_condition
2023 .' ORDER BY `Table_name` ASC;';
2024 $res = PMA_DBI_query($sql_query);
2025 $sql_query = '';
2027 while ($row = PMA_DBI_fetch_assoc($res)) {
2028 if (isset($db_rights[$row['Table_name']])) {
2029 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
2030 } else {
2031 $db_rights[$row['Table_name']] = $row;
2034 PMA_DBI_free_result($res);
2035 unset($row, $res);
2037 ksort($db_rights);
2039 // display rows
2040 if (count($db_rights) < 1) {
2041 echo '<tr class="odd">' . "\n"
2042 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
2043 . '</tr>' . "\n";
2044 } else {
2045 $odd_row = true;
2046 $found_rows = array();
2047 //while ($row = PMA_DBI_fetch_assoc($res)) {
2048 foreach ($db_rights as $row) {
2049 $found_rows[] = (! isset($dbname)) ? $row['Db'] : $row['Table_name'];
2051 echo '<tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2052 . ' <td>' . htmlspecialchars((! isset($dbname)) ? $row['Db'] : $row['Table_name']) . '</td>' . "\n"
2053 . ' <td><tt>' . "\n"
2054 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, true)) . "\n"
2055 . ' </tt></td>' . "\n"
2056 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') || (isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ? __('Yes') : __('No')) . '</td>' . "\n"
2057 . ' <td>';
2058 if (! empty($row['Table_privs']) || ! empty ($row['Column_priv'])) {
2059 echo __('Yes');
2060 } else {
2061 echo __('No');
2063 echo '</td>' . "\n"
2064 . ' <td>';
2065 printf($link_edit, htmlspecialchars(urlencode($username)),
2066 urlencode(htmlspecialchars($hostname)),
2067 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
2068 urlencode((! isset($dbname)) ? '' : $row['Table_name']));
2069 echo '</td>' . "\n"
2070 . ' <td>';
2071 if (! empty($row['can_delete']) || isset($row['Table_name']) && strlen($row['Table_name'])) {
2072 printf($link_revoke, htmlspecialchars(urlencode($username)),
2073 urlencode(htmlspecialchars($hostname)),
2074 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
2075 urlencode((! isset($dbname)) ? '' : $row['Table_name']));
2077 echo '</td>' . "\n"
2078 . '</tr>' . "\n";
2079 $odd_row = ! $odd_row;
2080 } // end while
2082 unset($row);
2083 echo '</tbody>' . "\n"
2084 . '</table>' . "\n";
2086 if (! isset($dbname)) {
2088 // no database name was given, display select db
2090 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
2092 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
2093 if (!empty($pred_db_array)) {
2094 echo ' <select name="pred_dbname" class="autosubmit">' . "\n"
2095 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2096 foreach ($pred_db_array as $current_db) {
2097 $current_db = PMA_escape_mysql_wildcards($current_db);
2098 // cannot use array_diff() once, outside of the loop,
2099 // because the list of databases has special characters
2100 // already escaped in $found_rows,
2101 // contrary to the output of SHOW DATABASES
2102 if (empty($found_rows) || ! in_array($current_db, $found_rows)) {
2103 echo ' <option value="' . htmlspecialchars($current_db) . '">'
2104 . htmlspecialchars($current_db) . '</option>' . "\n";
2107 echo ' </select>' . "\n";
2109 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
2110 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
2111 } else {
2112 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
2113 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
2114 if ($res = @PMA_DBI_try_query('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE)) {
2115 $pred_tbl_array = array();
2116 while ($row = PMA_DBI_fetch_row($res)) {
2117 if (! isset($found_rows) || !in_array($row[0], $found_rows)) {
2118 $pred_tbl_array[] = $row[0];
2121 PMA_DBI_free_result($res);
2122 unset($res, $row);
2123 if (!empty($pred_tbl_array)) {
2124 echo ' <select name="pred_tablename" class="autosubmit">' . "\n"
2125 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2126 foreach ($pred_tbl_array as $current_table) {
2127 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
2129 echo ' </select>' . "\n";
2131 } else {
2132 unset($res);
2134 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
2136 echo '</fieldset>' . "\n";
2137 echo '<fieldset class="tblFooters">' . "\n"
2138 . ' <input type="submit" value="' . __('Go') . '" />'
2139 . '</fieldset>' . "\n"
2140 . '</form>' . "\n";
2144 // Provide a line with links to the relevant database and table
2145 if (isset($dbname) && empty($dbname_is_wildcard)) {
2146 echo '[ ' . __('Database')
2147 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
2148 . $GLOBALS['url_query'] . '&amp;db=' . $url_dbname . '&amp;reload=1">'
2149 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
2151 if (isset($tablename)) {
2152 echo ' [ ' . __('Table') . ' <a href="'
2153 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
2154 . '&amp;db=' . $url_dbname . '&amp;table=' . htmlspecialchars(urlencode($tablename))
2155 . '&amp;reload=1">' . htmlspecialchars($tablename) . ': '
2156 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
2157 . "</a> ]\n";
2159 unset($url_dbname);
2162 if (! isset($dbname) && ! $user_does_not_exists) {
2163 require_once './libraries/display_change_password.lib.php';
2165 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
2166 . PMA_generate_common_hidden_inputs('', '')
2167 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
2168 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
2169 . '<fieldset id="fieldset_change_copy_user">' . "\n"
2170 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
2171 PMA_displayLoginInformationFields('change');
2172 echo ' <fieldset>' . "\n"
2173 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2174 $choices = array(
2175 '4' => __('... keep the old one.'),
2176 '1' => __('... delete the old one from the user tables.'),
2177 '2' => __('... revoke all active privileges from the old one and delete it afterwards.'),
2178 '3' => __('... delete the old one from the user tables and reload the privileges afterwards.'));
2179 PMA_display_html_radio('mode', $choices, '4', true);
2180 unset($choices);
2182 echo ' </fieldset>' . "\n"
2183 . '</fieldset>' . "\n"
2184 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2185 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2186 . '</fieldset>' . "\n"
2187 . '</form>' . "\n";
2190 } elseif (isset($_REQUEST['adduser'])) {
2192 // Add user
2193 $GLOBALS['url_query'] .= '&amp;adduser=1';
2194 echo '<h2>' . "\n"
2195 . PMA_getIcon('b_usradd.png') . __('Add user') . "\n"
2196 . '</h2>' . "\n"
2197 . '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n"
2198 . PMA_generate_common_hidden_inputs('', '');
2199 PMA_displayLoginInformationFields('new');
2200 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2201 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2203 $default_choice = 0;
2204 $choices = array(
2205 '0' => _pgettext('Create none database for user', 'None'),
2206 '1' => __('Create database with same name and grant all privileges'),
2207 '2' => __('Grant all privileges on wildcard name (username\\_%)'));
2209 if (! empty($dbname) ) {
2210 $choices['3'] = sprintf( __('Grant all privileges on database &quot;%s&quot;'), htmlspecialchars($dbname));
2211 $default_choice = 3;
2212 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2215 // 4th parameter set to true to add line breaks
2216 // 5th parameter set to false to avoid htmlspecialchars() escaping in the label
2217 // since we have some HTML in some labels
2218 PMA_display_html_radio('createdb', $choices, $default_choice, true, false);
2219 unset($choices);
2220 unset($default_choice);
2222 echo '</fieldset>' . "\n";
2223 PMA_displayPrivTable('*', '*', false);
2224 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2225 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2226 . ' </fieldset>' . "\n"
2227 . '</form>' . "\n";
2228 } else {
2229 // check the privileges for a particular database.
2230 $user_form = '<form id="usersForm"><table id="dbspecificuserrights" class="data">' . "\n"
2231 . '<caption class="tblHeaders">' . "\n"
2232 . PMA_getIcon('b_usrcheck.png')
2233 . ' ' . sprintf(__('Users having access to &quot;%s&quot;'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2234 . '</caption>' . "\n"
2235 . '<thead>' . "\n"
2236 . ' <tr><th>' . __('User') . '</th>' . "\n"
2237 . ' <th>' . __('Host') . '</th>' . "\n"
2238 . ' <th>' . __('Type') . '</th>' . "\n"
2239 . ' <th>' . __('Privileges') . '</th>' . "\n"
2240 . ' <th>' . __('Grant') . '</th>' . "\n"
2241 . ' <th>' . __('Action') . '</th>' . "\n"
2242 . ' </tr>' . "\n"
2243 . '</thead>' . "\n"
2244 . '<tbody>' . "\n";
2245 $odd_row = true;
2246 unset($row, $row1, $row2);
2248 // now, we build the table...
2249 $list_of_privileges =
2250 '`User`, '
2251 . '`Host`, '
2252 . '`Select_priv`, '
2253 . '`Insert_priv`, '
2254 . '`Update_priv`, '
2255 . '`Delete_priv`, '
2256 . '`Create_priv`, '
2257 . '`Drop_priv`, '
2258 . '`Grant_priv`, '
2259 . '`Index_priv`, '
2260 . '`Alter_priv`, '
2261 . '`References_priv`, '
2262 . '`Create_tmp_table_priv`, '
2263 . '`Lock_tables_priv`, '
2264 . '`Create_view_priv`, '
2265 . '`Show_view_priv`, '
2266 . '`Create_routine_priv`, '
2267 . '`Alter_routine_priv`, '
2268 . '`Execute_priv`';
2270 $list_of_compared_privileges =
2271 '`Select_priv` = \'N\''
2272 . ' AND `Insert_priv` = \'N\''
2273 . ' AND `Update_priv` = \'N\''
2274 . ' AND `Delete_priv` = \'N\''
2275 . ' AND `Create_priv` = \'N\''
2276 . ' AND `Drop_priv` = \'N\''
2277 . ' AND `Grant_priv` = \'N\''
2278 . ' AND `References_priv` = \'N\''
2279 . ' AND `Create_tmp_table_priv` = \'N\''
2280 . ' AND `Lock_tables_priv` = \'N\''
2281 . ' AND `Create_view_priv` = \'N\''
2282 . ' AND `Show_view_priv` = \'N\''
2283 . ' AND `Create_routine_priv` = \'N\''
2284 . ' AND `Alter_routine_priv` = \'N\''
2285 . ' AND `Execute_priv` = \'N\'';
2287 if (PMA_MYSQL_INT_VERSION >= 50106) {
2288 $list_of_privileges .=
2289 ', `Event_priv`, '
2290 . '`Trigger_priv`';
2291 $list_of_compared_privileges .=
2292 ' AND `Event_priv` = \'N\''
2293 . ' AND `Trigger_priv` = \'N\'';
2296 $sql_query =
2297 '(SELECT ' . $list_of_privileges . ', `Db`'
2298 .' FROM `mysql`.`db`'
2299 .' WHERE \'' . PMA_sqlAddSlashes($checkprivs) . "'"
2300 .' LIKE `Db`'
2301 .' AND NOT (' . $list_of_compared_privileges. ')) '
2302 .'UNION '
2303 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2304 .' FROM `mysql`.`user` '
2305 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2306 .' ORDER BY `User` ASC,'
2307 .' `Host` ASC,'
2308 .' `Db` ASC;';
2309 $res = PMA_DBI_query($sql_query);
2310 $row = PMA_DBI_fetch_assoc($res);
2311 if ($row) {
2312 $found = true;
2315 if ($found) {
2316 while (true) {
2317 // prepare the current user
2318 $current_privileges = array();
2319 $current_user = $row['User'];
2320 $current_host = $row['Host'];
2321 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2322 $current_privileges[] = $row;
2323 $row = PMA_DBI_fetch_assoc($res);
2325 $user_form .= ' <tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2326 . ' <td';
2327 if (count($current_privileges) > 1) {
2328 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2330 $user_form .= '>' . (empty($current_user) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2331 . ' </td>' . "\n"
2332 . ' <td';
2333 if (count($current_privileges) > 1) {
2334 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2336 $user_form .= '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2337 foreach ($current_privileges as $current) {
2338 $user_form .= ' <td>' . "\n"
2339 . ' ';
2340 if (! isset($current['Db']) || $current['Db'] == '*') {
2341 $user_form .= __('global');
2342 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2343 $user_form .= __('database-specific');
2344 } else {
2345 $user_form .= __('wildcard'). ': <tt>' . htmlspecialchars($current['Db']) . '</tt>';
2347 $user_form .= "\n"
2348 . ' </td>' . "\n"
2349 . ' <td>' . "\n"
2350 . ' <tt>' . "\n"
2351 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, true)) . "\n"
2352 . ' </tt>' . "\n"
2353 . ' </td>' . "\n"
2354 . ' <td>' . "\n"
2355 . ' ' . ($current['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . "\n"
2356 . ' </td>' . "\n"
2357 . ' <td>' . "\n";
2358 $user_form .= sprintf($link_edit, urlencode($current_user),
2359 urlencode($current_host),
2360 urlencode(! isset($current['Db']) || $current['Db'] == '*' ? '' : $current['Db']),
2361 '');
2362 $user_form .= '</td>' . "\n"
2363 . ' </tr>' . "\n";
2365 if (empty($row) && empty($row1) && empty($row2)) {
2366 break;
2368 $odd_row = ! $odd_row;
2370 } else {
2371 $user_form .= ' <tr class="odd">' . "\n"
2372 . ' <td colspan="6">' . "\n"
2373 . ' ' . __('No user found.') . "\n"
2374 . ' </td>' . "\n"
2375 . ' </tr>' . "\n";
2377 $user_form .= '</tbody>' . "\n"
2378 . '</table></form>' . "\n";
2380 if ($GLOBALS['is_ajax_request'] == true) {
2381 $extra_data['user_form'] = $user_form;
2382 $message = PMA_Message::success(__('User has been added.'));
2383 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
2384 }else{
2385 // Offer to create a new user for the current database
2386 $user_form .= '<fieldset id="fieldset_add_user">' . "\n"
2387 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1&amp;dbname=' . htmlspecialchars($checkprivs) .'" val="'.'checkprivs='.htmlspecialchars($checkprivs). '&'.$GLOBALS['url_query'] . '" class="'.$conditional_class.'" name="db_specific">' . "\n"
2388 . PMA_getIcon('b_usradd.png')
2389 . ' ' . __('Add user') . '</a>' . "\n"
2390 . '</fieldset>' . "\n";
2391 echo $user_form ;
2394 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2398 * Displays the footer
2400 echo "\n\n";
2401 require './libraries/footer.inc.php';