Better descriptions for Drizzle column types
[phpmyadmin.git] / server_privileges.php
blob5d0aa9eb7c2e1758153d972c64abfae3422a290d
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';
19 if ($GLOBALS['cfg']['CodemirrorEnable']) {
20 $GLOBALS['js_include'][] = 'codemirror/lib/codemirror.js';
21 $GLOBALS['js_include'][] = 'codemirror/mode/mysql/mysql.js';
23 $_add_user_error = false;
25 /**
26 * Sets globals from $_GET
29 $get_params = array(
30 'checkprivs',
31 'db',
32 'dbname',
33 'hostname',
34 'initial',
35 'tablename',
36 'username',
37 'viewing_mode'
39 foreach ($get_params as $one_get_param) {
40 if (isset($_GET[$one_get_param])) {
41 $GLOBALS[$one_get_param] = $_GET[$one_get_param];
45 /**
46 * Sets globals from $_POST
49 $post_params = array(
50 'createdb-1',
51 'createdb-2',
52 'createdb-3',
53 'grant_count',
54 'hostname',
55 'pma_pw',
56 'pma_pw2',
57 'pred_hostname',
58 'pred_password',
59 'pred_username',
60 'update_privs',
61 'username'
63 foreach ($post_params as $one_post_param) {
64 if (isset($_POST[$one_post_param])) {
65 $GLOBALS[$one_post_param] = $_POST[$one_post_param];
69 /**
70 * Sets globals from $_POST patterns, for privileges and max_* vars
73 $post_patterns = array(
74 '/_priv$/i',
75 '/^max_/i'
77 foreach (array_keys($_POST) as $post_key) {
78 foreach ($post_patterns as $one_post_pattern) {
79 if (preg_match($one_post_pattern, $post_key)) {
80 $GLOBALS[$post_key] = $_POST[$post_key];
85 require 'libraries/server_common.inc.php';
87 if ($GLOBALS['cfg']['AjaxEnable']) {
88 $conditional_class = 'ajax';
89 } else {
90 $conditional_class = '';
93 /**
94 * Messages are built using the message name
96 $strPrivDescAllPrivileges = __('Includes all privileges except GRANT.');
97 $strPrivDescAlter = __('Allows altering the structure of existing tables.');
98 $strPrivDescAlterRoutine = __('Allows altering and dropping stored routines.');
99 $strPrivDescCreateDb = __('Allows creating new databases and tables.');
100 $strPrivDescCreateRoutine = __('Allows creating stored routines.');
101 $strPrivDescCreateTbl = __('Allows creating new tables.');
102 $strPrivDescCreateTmpTable = __('Allows creating temporary tables.');
103 $strPrivDescCreateUser = __('Allows creating, dropping and renaming user accounts.');
104 $strPrivDescCreateView = __('Allows creating new views.');
105 $strPrivDescDelete = __('Allows deleting data.');
106 $strPrivDescDropDb = __('Allows dropping databases and tables.');
107 $strPrivDescDropTbl = __('Allows dropping tables.');
108 $strPrivDescEvent = __('Allows to set up events for the event scheduler');
109 $strPrivDescExecute = __('Allows executing stored routines.');
110 $strPrivDescFile = __('Allows importing data from and exporting data into files.');
111 $strPrivDescGrant = __('Allows adding users and privileges without reloading the privilege tables.');
112 $strPrivDescIndex = __('Allows creating and dropping indexes.');
113 $strPrivDescInsert = __('Allows inserting and replacing data.');
114 $strPrivDescLockTables = __('Allows locking tables for the current thread.');
115 $strPrivDescMaxConnections = __('Limits the number of new connections the user may open per hour.');
116 $strPrivDescMaxQuestions = __('Limits the number of queries the user may send to the server per hour.');
117 $strPrivDescMaxUpdates = __('Limits the number of commands that change any table or database the user may execute per hour.');
118 $strPrivDescMaxUserConnections = __('Limits the number of simultaneous connections the user may have.');
119 $strPrivDescProcess = __('Allows viewing processes of all users');
120 $strPrivDescReferences = __('Has no effect in this MySQL version.');
121 $strPrivDescReload = __('Allows reloading server settings and flushing the server\'s caches.');
122 $strPrivDescReplClient = __('Allows the user to ask where the slaves / masters are.');
123 $strPrivDescReplSlave = __('Needed for the replication slaves.');
124 $strPrivDescSelect = __('Allows reading data.');
125 $strPrivDescShowDb = __('Gives access to the complete list of databases.');
126 $strPrivDescShowView = __('Allows performing SHOW CREATE VIEW queries.');
127 $strPrivDescShutdown = __('Allows shutting down the server.');
128 $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.');
129 $strPrivDescTrigger = __('Allows creating and dropping triggers');
130 $strPrivDescUpdate = __('Allows changing data.');
131 $strPrivDescUsage = __('No privileges.');
134 * Checks if a dropdown box has been used for selecting a database / table
136 if (PMA_isValid($_REQUEST['pred_tablename'])) {
137 $tablename = $_REQUEST['pred_tablename'];
138 unset($pred_tablename);
139 } elseif (PMA_isValid($_REQUEST['tablename'])) {
140 $tablename = $_REQUEST['tablename'];
141 } else {
142 unset($tablename);
145 if (PMA_isValid($_REQUEST['pred_dbname'])) {
146 $dbname = $_REQUEST['pred_dbname'];
147 unset($pred_dbname);
148 } elseif (PMA_isValid($_REQUEST['dbname'])) {
149 $dbname = $_REQUEST['dbname'];
150 } else {
151 unset($dbname);
152 unset($tablename);
155 if (isset($dbname)) {
156 $db_and_table = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.';
157 if (isset($tablename)) {
158 $db_and_table .= PMA_backquote($tablename);
159 } else {
160 $db_and_table .= '*';
162 } else {
163 $db_and_table = '*.*';
166 // check if given $dbname is a wildcard or not
167 if (isset($dbname)) {
168 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
169 if (preg_match('/(?<!\\\\)(?:_|%)/i', $dbname)) {
170 $dbname_is_wildcard = true;
171 } else {
172 $dbname_is_wildcard = false;
177 * Checks if the user is allowed to do what he tries to...
179 if (! $is_superuser) {
180 include 'libraries/server_links.inc.php';
181 echo '<h2>' . "\n"
182 . PMA_getIcon('b_usrlist.png')
183 . __('Privileges') . "\n"
184 . '</h2>' . "\n";
185 PMA_Message::error(__('No Privileges'))->display();
186 include 'libraries/footer.inc.php';
189 // a random number that will be appended to the id of the user forms
190 $random_n = mt_rand(0, 1000000);
193 * Escapes wildcard in a database+table specification
194 * before using it in a GRANT statement.
196 * Escaping a wildcard character in a GRANT is only accepted at the global
197 * or database level, not at table level; this is why I remove
198 * the escaping character. Internally, in mysql.tables_priv.Db there are
199 * no escaping (for example test_db) but in mysql.db you'll see test\_db
200 * for a db-specific privilege.
202 * @param string $dbname Database name
203 * @param string $tablename Table name
205 * @return string the escaped (if necessary) database.table
207 function PMA_wildcardEscapeForGrant($dbname, $tablename)
210 if (! strlen($dbname)) {
211 $db_and_table = '*.*';
212 } else {
213 if (strlen($tablename)) {
214 $db_and_table
215 = PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . '.'
216 . PMA_backquote($tablename);
217 } else {
218 $db_and_table = PMA_backquote($dbname) . '.*';
221 return $db_and_table;
225 * Generates a condition on the user name
227 * @param string $initial the user's initial
229 * @return string the generated condition
231 function PMA_rangeOfUsers($initial = '')
233 // strtolower() is used because the User field
234 // might be BINARY, so LIKE would be case sensitive
235 if (! empty($initial)) {
236 $ret = " WHERE `User` LIKE '"
237 . PMA_sqlAddSlashes($initial, true) . "%'"
238 . " OR `User` LIKE '"
239 . PMA_sqlAddSlashes(strtolower($initial), true) . "%'";
240 } else {
241 $ret = '';
243 return $ret;
244 } // end function
247 * Extracts the privilege information of a priv table row
249 * @param array $row the row
250 * @param boolean $enableHTML add <dfn> tag with tooltips
252 * @global resource $user_link the database connection
254 * @return array
256 function PMA_extractPrivInfo($row = '', $enableHTML = false)
258 $grants = array(
259 array(
260 'Select_priv',
261 'SELECT',
262 __('Allows reading data.')),
263 array(
264 'Insert_priv',
265 'INSERT',
266 __('Allows inserting and replacing data.')),
267 array(
268 'Update_priv',
269 'UPDATE',
270 __('Allows changing data.')),
271 array(
272 'Delete_priv',
273 'DELETE',
274 __('Allows deleting data.')),
275 array(
276 'Create_priv',
277 'CREATE',
278 __('Allows creating new databases and tables.')),
279 array(
280 'Drop_priv',
281 'DROP',
282 __('Allows dropping databases and tables.')),
283 array(
284 'Reload_priv',
285 'RELOAD',
286 __('Allows reloading server settings and flushing the server\'s caches.')),
287 array(
288 'Shutdown_priv',
289 'SHUTDOWN',
290 __('Allows shutting down the server.')),
291 array(
292 'Process_priv',
293 'PROCESS',
294 __('Allows viewing processes of all users')),
295 array(
296 'File_priv',
297 'FILE',
298 __('Allows importing data from and exporting data into files.')),
299 array(
300 'References_priv',
301 'REFERENCES',
302 __('Has no effect in this MySQL version.')),
303 array(
304 'Index_priv',
305 'INDEX',
306 __('Allows creating and dropping indexes.')),
307 array(
308 'Alter_priv',
309 'ALTER',
310 __('Allows altering the structure of existing tables.')),
311 array(
312 'Show_db_priv',
313 'SHOW DATABASES',
314 __('Gives access to the complete list of databases.')),
315 array(
316 'Super_priv',
317 'SUPER',
318 __('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.')),
319 array(
320 'Create_tmp_table_priv',
321 'CREATE TEMPORARY TABLES',
322 __('Allows creating temporary tables.')),
323 array(
324 'Lock_tables_priv',
325 'LOCK TABLES',
326 __('Allows locking tables for the current thread.')),
327 array(
328 'Repl_slave_priv',
329 'REPLICATION SLAVE',
330 __('Needed for the replication slaves.')),
331 array(
332 'Repl_client_priv',
333 'REPLICATION CLIENT',
334 __('Allows the user to ask where the slaves / masters are.')),
335 array(
336 'Create_view_priv',
337 'CREATE VIEW',
338 __('Allows creating new views.')),
339 array(
340 'Event_priv',
341 'EVENT',
342 __('Allows to set up events for the event scheduler')),
343 array(
344 'Trigger_priv',
345 'TRIGGER',
346 __('Allows creating and dropping triggers')),
347 // for table privs:
348 array(
349 'Create View_priv',
350 'CREATE VIEW',
351 __('Allows creating new views.')),
352 array(
353 'Show_view_priv',
354 'SHOW VIEW',
355 __('Allows performing SHOW CREATE VIEW queries.')),
356 // for table privs:
357 array(
358 'Show view_priv',
359 'SHOW VIEW',
360 __('Allows performing SHOW CREATE VIEW queries.')),
361 array(
362 'Create_routine_priv',
363 'CREATE ROUTINE',
364 __('Allows creating stored routines.')),
365 array(
366 'Alter_routine_priv',
367 'ALTER ROUTINE',
368 __('Allows altering and dropping stored routines.')),
369 array(
370 'Create_user_priv',
371 'CREATE USER',
372 __('Allows creating, dropping and renaming user accounts.')),
373 array(
374 'Execute_priv',
375 'EXECUTE',
376 __('Allows executing stored routines.')),
379 if (! empty($row) && isset($row['Table_priv'])) {
380 $row1 = PMA_DBI_fetch_single_row(
381 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
382 'ASSOC', $GLOBALS['userlink']
384 $av_grants = explode(
385 '\',\'',
386 substr($row1['Type'], 5, strlen($row1['Type']) - 7)
388 unset($row1);
389 $users_grants = explode(',', $row['Table_priv']);
390 foreach ($av_grants as $current_grant) {
391 $row[$current_grant . '_priv']
392 = in_array($current_grant, $users_grants) ? 'Y' : 'N';
394 unset($current_grant);
395 unset($av_grants);
396 unset($users_grants);
398 $privs = array();
399 $allPrivileges = true;
400 foreach ($grants as $current_grant) {
401 if ((! empty($row) && isset($row[$current_grant[0]]))
402 || (empty($row) && isset($GLOBALS[$current_grant[0]]))
404 if ((! empty($row) && $row[$current_grant[0]] == 'Y')
405 || (empty($row)
406 && ($GLOBALS[$current_grant[0]] == 'Y'
407 || (is_array($GLOBALS[$current_grant[0]])
408 && count($GLOBALS[$current_grant[0]]) == $GLOBALS['column_count']
409 && empty($GLOBALS[$current_grant[0] . '_none']))))
411 if ($enableHTML) {
412 $privs[] = '<dfn title="' . $current_grant[2] . '">'
413 . $current_grant[1] . '</dfn>';
414 } else {
415 $privs[] = $current_grant[1];
417 } elseif (! empty($GLOBALS[$current_grant[0]])
418 && is_array($GLOBALS[$current_grant[0]])
419 && empty($GLOBALS[$current_grant[0] . '_none'])) {
420 if ($enableHTML) {
421 $priv_string = '<dfn title="' . $current_grant[2] . '">'
422 . $current_grant[1] . '</dfn>';
423 } else {
424 $priv_string = $current_grant[1];
426 $privs[] = $priv_string . ' (`'
427 . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
428 } else {
429 $allPrivileges = false;
433 if (empty($privs)) {
434 if ($enableHTML) {
435 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
436 } else {
437 $privs[] = 'USAGE';
439 } elseif ($allPrivileges
440 && (! isset($GLOBALS['grant_count'])
441 || count($privs) == $GLOBALS['grant_count'])
443 if ($enableHTML) {
444 $privs = array('<dfn title="'
445 . __('Includes all privileges except GRANT.')
446 . '">ALL PRIVILEGES</dfn>'
448 } else {
449 $privs = array('ALL PRIVILEGES');
452 return $privs;
453 } // end of the 'PMA_extractPrivInfo()' function
456 * Displays on which column(s) a table-specific privilege is granted
458 * @param array $columns
459 * @param array $row
460 * @param string $name_for_select
461 * @param string $priv_for_header
462 * @param string $name
463 * @param string $name_for_dfn
464 * @param string $name_for_current
466 * @return void
468 function PMA_displayColumnPrivs($columns, $row, $name_for_select,
469 $priv_for_header, $name, $name_for_dfn, $name_for_current
471 echo ' <div class="item" id="div_item_' . $name . '">' . "\n"
472 . ' <label for="select_' . $name . '_priv">' . "\n"
473 . ' <code><dfn title="' . $name_for_dfn . '">'
474 . $priv_for_header . '</dfn></code>' . "\n"
475 . ' </label><br />' . "\n"
476 . ' <select id="select_' . $name . '_priv" name="'
477 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
479 foreach ($columns as $current_column => $current_column_privileges) {
480 echo ' <option value="' . htmlspecialchars($current_column) . '"';
481 if ($row[$name_for_select] == 'Y' || $current_column_privileges[$name_for_current]) {
482 echo ' selected="selected"';
484 echo '>' . htmlspecialchars($current_column) . '</option>' . "\n";
487 echo ' </select>' . "\n"
488 . ' <i>' . __('Or') . '</i>' . "\n"
489 . ' <label for="checkbox_' . $name_for_select
490 . '_none"><input type="checkbox"'
491 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
492 . ' name="' . $name_for_select . '_none" id="checkbox_'
493 . $name_for_select . '_none" title="'
494 . _pgettext('None privileges', 'None') . '" />'
495 . _pgettext('None privileges', 'None') . '</label>' . "\n"
496 . ' </div>' . "\n";
497 } // end function
501 * Displays the privileges form table
503 * @param string $db the database
504 * @param string $table the table
505 * @param boolean $submit wheather to display the submit button or not
507 * @global array $cfg the phpMyAdmin configuration
508 * @global ressource $user_link the database connection
510 * @return void
512 function PMA_displayPrivTable($db = '*', $table = '*', $submit = true)
514 global $random_n;
516 if ($db == '*') {
517 $table = '*';
520 if (isset($GLOBALS['username'])) {
521 $username = $GLOBALS['username'];
522 $hostname = $GLOBALS['hostname'];
523 if ($db == '*') {
524 $sql_query = "SELECT * FROM `mysql`.`user`"
525 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
526 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
527 } elseif ($table == '*') {
528 $sql_query = "SELECT * FROM `mysql`.`db`"
529 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
530 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
531 ." AND '" . PMA_unescape_mysql_wildcards($db) . "'"
532 ." LIKE `Db`;";
533 } else {
534 $sql_query = "SELECT `Table_priv`"
535 ." FROM `mysql`.`tables_priv`"
536 ." WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
537 ." AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "'"
538 ." AND `Db` = '" . PMA_unescape_mysql_wildcards($db) . "'"
539 ." AND `Table_name` = '" . PMA_sqlAddSlashes($table) . "';";
541 $row = PMA_DBI_fetch_single_row($sql_query);
543 if (empty($row)) {
544 if ($table == '*') {
545 if ($db == '*') {
546 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
547 } elseif ($table == '*') {
548 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
550 $res = PMA_DBI_query($sql_query);
551 while ($row1 = PMA_DBI_fetch_row($res)) {
552 if (substr($row1[0], 0, 4) == 'max_') {
553 $row[$row1[0]] = 0;
554 } else {
555 $row[$row1[0]] = 'N';
558 PMA_DBI_free_result($res);
559 } else {
560 $row = array('Table_priv' => '');
563 if (isset($row['Table_priv'])) {
564 $row1 = PMA_DBI_fetch_single_row(
565 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
566 'ASSOC', $GLOBALS['userlink']
568 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
569 // the View for Create is spelled with uppercase V
570 // the view for Show is spelled with lowercase v
571 // and there is a space between the words
573 $av_grants = explode(
574 '\',\'',
575 substr(
576 $row1['Type'],
577 strpos($row1['Type'], '(') + 2,
578 strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3
581 unset($row1);
582 $users_grants = explode(',', $row['Table_priv']);
584 foreach ($av_grants as $current_grant) {
585 $row[$current_grant . '_priv']
586 = in_array($current_grant, $users_grants) ? 'Y' : 'N';
588 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
590 // get collumns
591 $res = PMA_DBI_try_query(
592 'SHOW COLUMNS FROM '
593 . PMA_backquote(PMA_unescape_mysql_wildcards($db))
594 . '.' . PMA_backquote($table) . ';'
596 $columns = array();
597 if ($res) {
598 while ($row1 = PMA_DBI_fetch_row($res)) {
599 $columns[$row1[0]] = array(
600 'Select' => false,
601 'Insert' => false,
602 'Update' => false,
603 'References' => false
606 PMA_DBI_free_result($res);
608 unset($res, $row1);
610 // t a b l e - s p e c i f i c p r i v i l e g e s
611 if (! empty($columns)) {
612 $res = PMA_DBI_query(
613 'SELECT `Column_name`, `Column_priv`'
614 .' FROM `mysql`.`columns_priv`'
615 .' WHERE `User`'
616 .' = \'' . PMA_sqlAddSlashes($username) . "'"
617 .' AND `Host`'
618 .' = \'' . PMA_sqlAddSlashes($hostname) . "'"
619 .' AND `Db`'
620 .' = \'' . PMA_sqlAddSlashes(PMA_unescape_mysql_wildcards($db)) . "'"
621 .' AND `Table_name`'
622 .' = \'' . PMA_sqlAddSlashes($table) . '\';'
625 while ($row1 = PMA_DBI_fetch_row($res)) {
626 $row1[1] = explode(',', $row1[1]);
627 foreach ($row1[1] as $current) {
628 $columns[$row1[0]][$current] = true;
631 PMA_DBI_free_result($res);
632 unset($res, $row1, $current);
634 echo '<input type="hidden" name="grant_count" value="' . count($row) . '" />' . "\n"
635 . '<input type="hidden" name="column_count" value="' . count($columns) . '" />' . "\n"
636 . '<fieldset id="fieldset_user_priv">' . "\n"
637 . ' <legend>' . __('Table-specific privileges')
638 . PMA_showHint(__('Note: MySQL privilege names are expressed in English'))
639 . '</legend>' . "\n";
643 // privs that are attached to a specific column
644 PMA_displayColumnPrivs(
645 $columns, $row, 'Select_priv', 'SELECT',
646 'select', __('Allows reading data.'), 'Select'
649 PMA_displayColumnPrivs(
650 $columns, $row, 'Insert_priv', 'INSERT',
651 'insert', __('Allows inserting and replacing data.'), 'Insert'
654 PMA_displayColumnPrivs(
655 $columns, $row, 'Update_priv', 'UPDATE',
656 'update', __('Allows changing data.'), 'Update'
659 PMA_displayColumnPrivs(
660 $columns, $row, 'References_priv', 'REFERENCES', 'references',
661 __('Has no effect in this MySQL version.'), 'References'
664 // privs that are not attached to a specific column
666 echo ' <div class="item">' . "\n";
667 foreach ($row as $current_grant => $current_grant_value) {
668 $grant_type = substr($current_grant, 0, (strlen($current_grant) - 5));
669 if (in_array($grant_type, array('Select', 'Insert', 'Update', 'References'))) {
670 continue;
672 // make a substitution to match the messages variables;
673 // also we must substitute the grant we get, because we can't generate
674 // a form variable containing blanks (those would get changed to
675 // an underscore when receiving the POST)
676 if ($current_grant == 'Create View_priv') {
677 $tmp_current_grant = 'CreateView_priv';
678 $current_grant = 'Create_view_priv';
679 } elseif ($current_grant == 'Show view_priv') {
680 $tmp_current_grant = 'ShowView_priv';
681 $current_grant = 'Show_view_priv';
682 } else {
683 $tmp_current_grant = $current_grant;
686 echo ' <div class="item">' . "\n"
687 . ' <input type="checkbox"'
688 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
689 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
690 . '" value="Y" '
691 . ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
692 . 'title="';
694 echo (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
695 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
696 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl']) . '"/>' . "\n";
698 echo ' <label for="checkbox_' . $current_grant
699 . '"><code><dfn title="'
700 . (isset($GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))])
701 ? $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5))]
702 : $GLOBALS['strPrivDesc' . substr($tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)) . 'Tbl'])
703 . '">' . strtoupper(substr($current_grant, 0, strlen($current_grant) - 5)) . '</dfn></code></label>' . "\n"
704 . ' </div>' . "\n";
705 } // end foreach ()
707 echo ' </div>' . "\n";
708 // for Safari 2.0.2
709 echo ' <div class="clearfloat"></div>' . "\n";
711 } else {
713 // g l o b a l o r d b - s p e c i f i c
715 $privTable_names = array(0 => __('Data'), 1 => __('Structure'), 2 => __('Administration'));
717 // d a t a
718 $privTable[0] = array(
719 array('Select', 'SELECT', __('Allows reading data.')),
720 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
721 array('Update', 'UPDATE', __('Allows changing data.')),
722 array('Delete', 'DELETE', __('Allows deleting data.'))
724 if ($db == '*') {
725 $privTable[0][] = array('File', 'FILE', __('Allows importing data from and exporting data into files.'));
728 // s t r u c t u r e
729 $privTable[1] = array(
730 array('Create', 'CREATE', ($table == '*' ? __('Allows creating new databases and tables.') : __('Allows creating new tables.'))),
731 array('Alter', 'ALTER', __('Allows altering the structure of existing tables.')),
732 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
733 array('Drop', 'DROP', ($table == '*' ? __('Allows dropping databases and tables.') : __('Allows dropping tables.'))),
734 array('Create_tmp_table', 'CREATE TEMPORARY TABLES', __('Allows creating temporary tables.')),
735 array('Show_view', 'SHOW VIEW', __('Allows performing SHOW CREATE VIEW queries.')),
736 array('Create_routine', 'CREATE ROUTINE', __('Allows creating stored routines.')),
737 array('Alter_routine', 'ALTER ROUTINE', __('Allows altering and dropping stored routines.')),
738 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
740 // this one is for a db-specific priv: Create_view_priv
741 if (isset($row['Create_view_priv'])) {
742 $privTable[1][] = array('Create_view', 'CREATE VIEW', __('Allows creating new views.'));
744 // this one is for a table-specific priv: Create View_priv
745 if (isset($row['Create View_priv'])) {
746 $privTable[1][] = array('Create View', 'CREATE VIEW', __('Allows creating new views.'));
748 if (isset($row['Event_priv'])) {
749 // MySQL 5.1.6
750 $privTable[1][] = array('Event', 'EVENT', __('Allows to set up events for the event scheduler'));
751 $privTable[1][] = array('Trigger', 'TRIGGER', __('Allows creating and dropping triggers'));
754 // a d m i n i s t r a t i o n
755 $privTable[2] = array(
756 array('Grant', 'GRANT', __('Allows adding users and privileges without reloading the privilege tables.')),
758 if ($db == '*') {
759 $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.'));
760 $privTable[2][] = array('Process', 'PROCESS', __('Allows viewing processes of all users'));
761 $privTable[2][] = array('Reload', 'RELOAD', __('Allows reloading server settings and flushing the server\'s caches.'));
762 $privTable[2][] = array('Shutdown', 'SHUTDOWN', __('Allows shutting down the server.'));
763 $privTable[2][] = array('Show_db', 'SHOW DATABASES', __('Gives access to the complete list of databases.'));
765 $privTable[2][] = array('Lock_tables', 'LOCK TABLES', __('Allows locking tables for the current thread.'));
766 $privTable[2][] = array('References', 'REFERENCES', __('Has no effect in this MySQL version.'));
767 if ($db == '*') {
768 $privTable[2][] = array('Repl_client', 'REPLICATION CLIENT', __('Allows the user to ask where the slaves / masters are.'));
769 $privTable[2][] = array('Repl_slave', 'REPLICATION SLAVE', __('Needed for the replication slaves.'));
770 $privTable[2][] = array('Create_user', 'CREATE USER', __('Allows creating, dropping and renaming user accounts.'));
772 echo '<input type="hidden" name="grant_count" value="'
773 . (count($privTable[0]) + count($privTable[1]) + count($privTable[2]) - (isset($row['Grant_priv']) ? 1 : 0))
774 . '" />' . "\n"
775 . '<fieldset id="fieldset_user_global_rights">' . "\n"
776 . ' <legend>' . "\n"
777 . ' '
778 . ($db == '*'
779 ? __('Global privileges')
780 : ($table == '*'
781 ? __('Database-specific privileges')
782 : __('Table-specific privileges'))) . "\n"
783 . ' (<a href="server_privileges.php?'
784 . $GLOBALS['url_query'] . '&amp;checkall=1" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', true); return false;">'
785 . __('Check All') . '</a> /' . "\n"
786 . ' <a href="server_privileges.php?'
787 . $GLOBALS['url_query'] . '" onclick="setCheckboxes(\'addUsersForm_' . $random_n . '\', false); return false;">'
788 . __('Uncheck All') . '</a>)' . "\n"
789 . ' </legend>' . "\n"
790 . ' <p><small><i>' . __('Note: MySQL privilege names are expressed in English') . '</i></small></p>' . "\n";
792 // Output the Global privilege tables with checkboxes
793 foreach ($privTable as $i => $table) {
794 echo ' <fieldset>' . "\n"
795 . ' <legend>' . __($privTable_names[$i]) . '</legend>' . "\n";
796 foreach ($table as $priv) {
797 echo ' <div class="item">' . "\n"
798 . ' <input type="checkbox"'
799 . ' name="' . $priv[0] . '_priv" id="checkbox_' . $priv[0] . '_priv"'
800 . ' value="Y" title="' . $priv[2] . '"'
801 . ((! empty($GLOBALS['checkall']) || $row[$priv[0] . '_priv'] == 'Y') ? ' checked="checked"' : '')
802 . '/>' . "\n"
803 . ' <label for="checkbox_' . $priv[0] . '_priv"><code><dfn title="' . $priv[2] . '">'
804 . $priv[1] . '</dfn></code></label>' . "\n"
805 . ' </div>' . "\n";
807 echo ' </fieldset>' . "\n";
810 // The "Resource limits" box is not displayed for db-specific privs
811 if ($db == '*') {
812 echo ' <fieldset>' . "\n"
813 . ' <legend>' . __('Resource limits') . '</legend>' . "\n"
814 . ' <p><small><i>' . __('Note: Setting these options to 0 (zero) removes the limit.') . '</i></small></p>' . "\n"
815 . ' <div class="item">' . "\n"
816 . ' <label for="text_max_questions"><code><dfn title="'
817 . __('Limits the number of queries the user may send to the server per hour.') . '">MAX QUERIES PER HOUR</dfn></code></label>' . "\n"
818 . ' <input type="text" name="max_questions" id="text_max_questions" value="'
819 . $row['max_questions'] . '" size="11" maxlength="11" title="' . __('Limits the number of queries the user may send to the server per hour.') . '" />' . "\n"
820 . ' </div>' . "\n"
821 . ' <div class="item">' . "\n"
822 . ' <label for="text_max_updates"><code><dfn title="'
823 . __('Limits the number of commands that change any table or database the user may execute per hour.') . '">MAX UPDATES PER HOUR</dfn></code></label>' . "\n"
824 . ' <input type="text" name="max_updates" id="text_max_updates" value="'
825 . $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"
826 . ' </div>' . "\n"
827 . ' <div class="item">' . "\n"
828 . ' <label for="text_max_connections"><code><dfn title="'
829 . __('Limits the number of new connections the user may open per hour.') . '">MAX CONNECTIONS PER HOUR</dfn></code></label>' . "\n"
830 . ' <input type="text" name="max_connections" id="text_max_connections" value="'
831 . $row['max_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of new connections the user may open per hour.') . '" />' . "\n"
832 . ' </div>' . "\n"
833 . ' <div class="item">' . "\n"
834 . ' <label for="text_max_user_connections"><code><dfn title="'
835 . __('Limits the number of simultaneous connections the user may have.') . '">MAX USER_CONNECTIONS</dfn></code></label>' . "\n"
836 . ' <input type="text" name="max_user_connections" id="text_max_user_connections" value="'
837 . $row['max_user_connections'] . '" size="11" maxlength="11" title="' . __('Limits the number of simultaneous connections the user may have.') . '" />' . "\n"
838 . ' </div>' . "\n"
839 . ' </fieldset>' . "\n";
841 // for Safari 2.0.2
842 echo ' <div class="clearfloat"></div>' . "\n";
844 echo '</fieldset>' . "\n";
845 if ($submit) {
846 echo '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">' . "\n"
847 . ' <input type="submit" name="update_privs" value="' . __('Go') . '" />' . "\n"
848 . '</fieldset>' . "\n";
850 } // end of the 'PMA_displayPrivTable()' function
854 * Displays the fields used by the "new user" form as well as the
855 * "change login information / copy user" form.
857 * @param string $mode are we creating a new user or are we just
858 * changing one? (allowed values: 'new', 'change')
860 * @global array $cfg the phpMyAdmin configuration
861 * @global ressource $user_link the database connection
863 * @return void
865 function PMA_displayLoginInformationFields($mode = 'new')
867 // Get user/host name lengths
868 $fields_info = PMA_DBI_get_columns('mysql', 'user', null, true);
869 $username_length = 16;
870 $hostname_length = 41;
871 foreach ($fields_info as $val) {
872 if ($val['Field'] == 'User') {
873 strtok($val['Type'], '()');
874 $v = strtok('()');
875 if (is_int($v)) {
876 $username_length = $v;
878 } elseif ($val['Field'] == 'Host') {
879 strtok($val['Type'], '()');
880 $v = strtok('()');
881 if (is_int($v)) {
882 $hostname_length = $v;
886 unset($fields_info);
888 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
889 $GLOBALS['pred_username'] = 'any';
891 echo '<fieldset id="fieldset_add_user_login">' . "\n"
892 . '<legend>' . __('Login Information') . '</legend>' . "\n"
893 . '<div class="item">' . "\n"
894 . '<label for="select_pred_username">' . "\n"
895 . ' ' . __('User name') . ':' . "\n"
896 . '</label>' . "\n"
897 . '<span class="options">' . "\n"
898 . ' <select name="pred_username" id="select_pred_username" title="' . __('User name') . '"' . "\n"
899 . ' onchange="if (this.value == \'any\') { username.value = \'\'; } else if (this.value == \'userdefined\') { username.focus(); username.select(); }">' . "\n"
900 . ' <option value="any"' . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any') ? ' selected="selected"' : '') . '>' . __('Any user') . '</option>' . "\n"
901 . ' <option value="userdefined"' . ((! isset($GLOBALS['pred_username']) || $GLOBALS['pred_username'] == 'userdefined') ? ' selected="selected"' : '') . '>' . __('Use text field') . ':</option>' . "\n"
902 . ' </select>' . "\n"
903 . '</span>' . "\n"
904 . '<input type="text" name="username" maxlength="'
905 . $username_length . '" title="' . __('User name') . '"'
906 . (empty($GLOBALS['username'])
907 ? ''
908 : ' value="' . htmlspecialchars(
909 isset($GLOBALS['new_username'])
910 ? $GLOBALS['new_username']
911 : $GLOBALS['username']
912 ) . '"'
914 . ' onchange="pred_username.value = \'userdefined\';" autofocus="autofocus" />' . "\n"
915 . '</div>' . "\n"
916 . '<div class="item">' . "\n"
917 . '<label for="select_pred_hostname">' . "\n"
918 . ' ' . __('Host') . ':' . "\n"
919 . '</label>' . "\n"
920 . '<span class="options">' . "\n"
921 . ' <select name="pred_hostname" id="select_pred_hostname" title="' . __('Host') . '"' . "\n";
922 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
923 if (! empty($_current_user)) {
924 $thishost = str_replace("'", '', substr($_current_user, (strrpos($_current_user, '@') + 1)));
925 if ($thishost == 'localhost' || $thishost == '127.0.0.1') {
926 unset($thishost);
929 echo ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } else if (this.value == \'localhost\') { hostname.value = \'localhost\'; } '
930 . (empty($thishost) ? '' : 'else if (this.value == \'thishost\') { hostname.value = \'' . addslashes(htmlspecialchars($thishost)) . '\'; } ')
931 . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } else if (this.value == \'userdefined\') { hostname.focus(); hostname.select(); }">' . "\n";
932 unset($_current_user);
934 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
935 if (! isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
936 switch (strtolower($GLOBALS['hostname'])) {
937 case 'localhost':
938 case '127.0.0.1':
939 $GLOBALS['pred_hostname'] = 'localhost';
940 break;
941 case '%':
942 $GLOBALS['pred_hostname'] = 'any';
943 break;
944 default:
945 $GLOBALS['pred_hostname'] = 'userdefined';
946 break;
949 echo ' <option value="any"'
950 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
951 ? ' selected="selected"' : '') . '>' . __('Any host')
952 . '</option>' . "\n"
953 . ' <option value="localhost"'
954 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'localhost')
955 ? ' selected="selected"' : '') . '>' . __('Local')
956 . '</option>' . "\n";
957 if (! empty($thishost)) {
958 echo ' <option value="thishost"'
959 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'thishost')
960 ? ' selected="selected"' : '') . '>' . __('This Host')
961 . '</option>' . "\n";
963 unset($thishost);
964 echo ' <option value="hosttable"'
965 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'hosttable')
966 ? ' selected="selected"' : '') . '>' . __('Use Host Table')
967 . '</option>' . "\n"
968 . ' <option value="userdefined"'
969 . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'userdefined')
970 ? ' selected="selected"' : '')
971 . '>' . __('Use text field') . ':</option>' . "\n"
972 . ' </select>' . "\n"
973 . '</span>' . "\n"
974 . '<input type="text" name="hostname" maxlength="'
975 . $hostname_length . '" value="'
976 . htmlspecialchars(isset($GLOBALS['hostname']) ? $GLOBALS['hostname'] : '')
977 . '" title="' . __('Host')
978 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
979 . PMA_showHint(__('When Host table is used, this field is ignored and values stored in Host table are used instead.'))
980 . '</div>' . "\n"
981 . '<div class="item">' . "\n"
982 . '<label for="select_pred_password">' . "\n"
983 . ' ' . __('Password') . ':' . "\n"
984 . '</label>' . "\n"
985 . '<span class="options">' . "\n"
986 . ' <select name="pred_password" id="select_pred_password" title="'
987 . __('Password') . '"' . "\n"
988 . ' onchange="if (this.value == \'none\') { pma_pw.value = \'\'; pma_pw2.value = \'\'; } else if (this.value == \'userdefined\') { pma_pw.focus(); pma_pw.select(); }">' . "\n"
989 . ($mode == 'change' ? ' <option value="keep" selected="selected">' . __('Do not change the password') . '</option>' . "\n" : '')
990 . ' <option value="none"';
991 if (isset($GLOBALS['username']) && $mode != 'change') {
992 echo ' selected="selected"';
994 echo '>' . __('No Password') . '</option>' . "\n"
995 . ' <option value="userdefined"' . (isset($GLOBALS['username']) ? '' : ' selected="selected"') . '>' . __('Use text field') . ':</option>' . "\n"
996 . ' </select>' . "\n"
997 . '</span>' . "\n"
998 . '<input type="password" id="text_pma_pw" name="pma_pw" title="' . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
999 . '</div>' . "\n"
1000 . '<div class="item" id="div_element_before_generate_password">' . "\n"
1001 . '<label for="text_pma_pw2">' . "\n"
1002 . ' ' . __('Re-type') . ':' . "\n"
1003 . '</label>' . "\n"
1004 . '<span class="options">&nbsp;</span>' . "\n"
1005 . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="' . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />' . "\n"
1006 . '</div>' . "\n"
1007 // Generate password added here via jQuery
1008 . '</fieldset>' . "\n";
1009 } // end of the 'PMA_displayUserAndHostFields()' function
1013 * Returns all the grants for a certain user on a certain host
1014 * Used in the export privileges for all users section
1016 * @param string $user User name
1017 * @param string $host Host name
1019 * @return string containing all the grants text
1021 function PMA_getGrants($user, $host)
1023 $grants = PMA_DBI_fetch_result("SHOW GRANTS FOR '" . PMA_sqlAddSlashes($user) . "'@'" . PMA_sqlAddSlashes($host) . "'");
1024 $response = '';
1025 foreach ($grants as $one_grant) {
1026 $response .= $one_grant . ";\n\n";
1028 return $response;
1029 } // end of the 'PMA_getGrants()' function
1032 * Changes / copies a user, part I
1034 if (isset($_REQUEST['change_copy'])) {
1035 $user_host_condition = ' WHERE `User`'
1036 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1037 .' AND `Host`'
1038 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
1039 $row = PMA_DBI_fetch_single_row('SELECT * FROM `mysql`.`user` ' . $user_host_condition);
1040 if (! $row) {
1041 PMA_Message::notice(__('No user found.'))->display();
1042 unset($_REQUEST['change_copy']);
1043 } else {
1044 extract($row, EXTR_OVERWRITE);
1045 // Recent MySQL versions have the field "Password" in mysql.user,
1046 // so the previous extract creates $Password but this script
1047 // uses $password
1048 if (! isset($password) && isset($Password)) {
1049 $password = $Password;
1051 $queries = array();
1057 * Adds a user
1058 * (Changes / copies a user, part II)
1060 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
1061 $sql_query = '';
1062 if ($pred_username == 'any') {
1063 $username = '';
1065 switch ($pred_hostname) {
1066 case 'any':
1067 $hostname = '%';
1068 break;
1069 case 'localhost':
1070 $hostname = 'localhost';
1071 break;
1072 case 'hosttable':
1073 $hostname = '';
1074 break;
1075 case 'thishost':
1076 $_user_name = PMA_DBI_fetch_value('SELECT USER()');
1077 $hostname = substr($_user_name, (strrpos($_user_name, '@') + 1));
1078 unset($_user_name);
1079 break;
1081 $sql = "SELECT '1' FROM `mysql`.`user`"
1082 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
1083 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
1084 if (PMA_DBI_fetch_value($sql) == 1) {
1085 $message = PMA_Message::error(__('The user %s already exists!'));
1086 $message->addParam('[i]\'' . $username . '\'@\'' . $hostname . '\'[/i]');
1087 $_REQUEST['adduser'] = true;
1088 $_add_user_error = true;
1089 } else {
1091 $create_user_real = 'CREATE USER \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
1093 $real_sql_query = 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
1094 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
1095 if ($pred_password != 'none' && $pred_password != 'keep') {
1096 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
1097 $real_sql_query .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
1098 if (isset($create_user_real)) {
1099 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
1100 $create_user_real .= ' IDENTIFIED BY \'' . PMA_sqlAddSlashes($pma_pw) . '\'';
1102 } else {
1103 if ($pred_password == 'keep' && ! empty($password)) {
1104 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
1105 if (isset($create_user_real)) {
1106 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
1109 $sql_query = $real_sql_query;
1110 if (isset($create_user_real)) {
1111 $create_user_show = $create_user_real;
1115 * @todo similar code appears twice in this script
1117 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1118 || (isset($max_questions) || isset($max_connections)
1119 || isset($max_updates) || isset($max_user_connections))
1121 $real_sql_query .= ' WITH';
1122 $sql_query .= ' WITH';
1123 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1124 $real_sql_query .= ' GRANT OPTION';
1125 $sql_query .= ' GRANT OPTION';
1127 if (isset($max_questions)) {
1128 // avoid negative values
1129 $max_questions = max(0, (int)$max_questions);
1130 $real_sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1131 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1133 if (isset($max_connections)) {
1134 $max_connections = max(0, (int)$max_connections);
1135 $real_sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1136 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1138 if (isset($max_updates)) {
1139 $max_updates = max(0, (int)$max_updates);
1140 $real_sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1141 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1143 if (isset($max_user_connections)) {
1144 $max_user_connections = max(0, (int)$max_user_connections);
1145 $real_sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1146 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1149 if (isset($create_user_real)) {
1150 $create_user_real .= ';';
1151 $create_user_show .= ';';
1153 $real_sql_query .= ';';
1154 $sql_query .= ';';
1155 if (empty($_REQUEST['change_copy'])) {
1156 $_error = false;
1158 if (isset($create_user_real)) {
1159 if (! PMA_DBI_try_query($create_user_real)) {
1160 $_error = true;
1162 $sql_query = $create_user_show . $sql_query;
1165 if ($_error || ! PMA_DBI_try_query($real_sql_query)) {
1166 $_REQUEST['createdb-1'] = $_REQUEST['createdb-2'] = $_REQUEST['createdb-3'] = false;
1167 $message = PMA_Message::rawError(PMA_DBI_getError());
1168 } else {
1169 $message = PMA_Message::success(__('You have added a new user.'));
1172 if (isset($_REQUEST['createdb-1'])) {
1173 // Create database with same name and grant all privileges
1174 $q = 'CREATE DATABASE IF NOT EXISTS '
1175 . PMA_backquote(PMA_sqlAddSlashes($username)) . ';';
1176 $sql_query .= $q;
1177 if (! PMA_DBI_try_query($q)) {
1178 $message = PMA_Message::rawError(PMA_DBI_getError());
1183 * If we are not in an Ajax request, we can't reload navigation now
1185 if ($GLOBALS['is_ajax_request'] != true) {
1186 // this is needed in case tracking is on:
1187 $GLOBALS['db'] = $username;
1188 $GLOBALS['reload'] = true;
1189 PMA_reloadNavigation();
1192 $q = 'GRANT ALL PRIVILEGES ON '
1193 . PMA_backquote(PMA_escape_mysql_wildcards(PMA_sqlAddSlashes($username))) . '.* TO \''
1194 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1195 $sql_query .= $q;
1196 if (! PMA_DBI_try_query($q)) {
1197 $message = PMA_Message::rawError(PMA_DBI_getError());
1201 if (isset($_REQUEST['createdb-2'])) {
1202 // Grant all privileges on wildcard name (username\_%)
1203 $q = 'GRANT ALL PRIVILEGES ON '
1204 . PMA_backquote(PMA_sqlAddSlashes($username) . '\_%') . '.* TO \''
1205 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1206 $sql_query .= $q;
1207 if (! PMA_DBI_try_query($q)) {
1208 $message = PMA_Message::rawError(PMA_DBI_getError());
1212 if (isset($_REQUEST['createdb-3'])) {
1213 // Grant all privileges on the specified database to the new user
1214 $q = 'GRANT ALL PRIVILEGES ON '
1215 . PMA_backquote(PMA_sqlAddSlashes($dbname)) . '.* TO \''
1216 . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1217 $sql_query .= $q;
1218 if (! PMA_DBI_try_query($q)) {
1219 $message = PMA_Message::rawError(PMA_DBI_getError());
1222 } else {
1223 if (isset($create_user_real)) {
1224 $queries[] = $create_user_real;
1226 $queries[] = $real_sql_query;
1227 // we put the query containing the hidden password in
1228 // $queries_for_display, at the same position occupied
1229 // by the real query in $queries
1230 $tmp_count = count($queries);
1231 if (isset($create_user_real)) {
1232 $queries_for_display[$tmp_count - 2] = $create_user_show;
1234 $queries_for_display[$tmp_count - 1] = $sql_query;
1236 unset($res, $real_sql_query);
1242 * Changes / copies a user, part III
1244 if (isset($_REQUEST['change_copy'])) {
1245 $user_host_condition = ' WHERE `User`'
1246 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1247 .' AND `Host`'
1248 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\';';
1249 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
1250 while ($row = PMA_DBI_fetch_assoc($res)) {
1251 $queries[] = 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
1252 .' ON ' . PMA_backquote($row['Db']) . '.*'
1253 .' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1254 . ($row['Grant_priv'] == 'Y' ? ' WITH GRANT OPTION;' : ';');
1256 PMA_DBI_free_result($res);
1257 $res = PMA_DBI_query(
1258 'SELECT `Db`, `Table_name`, `Table_priv` FROM `mysql`.`tables_priv`' . $user_host_condition,
1259 $GLOBALS['userlink'],
1260 PMA_DBI_QUERY_STORE
1262 while ($row = PMA_DBI_fetch_assoc($res)) {
1264 $res2 = PMA_DBI_QUERY(
1265 'SELECT `Column_name`, `Column_priv`'
1266 .' FROM `mysql`.`columns_priv`'
1267 .' WHERE `User`'
1268 .' = \'' . PMA_sqlAddSlashes($old_username) . "'"
1269 .' AND `Host`'
1270 .' = \'' . PMA_sqlAddSlashes($old_hostname) . '\''
1271 .' AND `Db`'
1272 .' = \'' . PMA_sqlAddSlashes($row['Db']) . "'"
1273 .' AND `Table_name`'
1274 .' = \'' . PMA_sqlAddSlashes($row['Table_name']) . "'"
1275 .';',
1276 null,
1277 PMA_DBI_QUERY_STORE
1280 $tmp_privs1 = PMA_extractPrivInfo($row);
1281 $tmp_privs2 = array(
1282 'Select' => array(),
1283 'Insert' => array(),
1284 'Update' => array(),
1285 'References' => array()
1288 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
1289 $tmp_array = explode(',', $row2['Column_priv']);
1290 if (in_array('Select', $tmp_array)) {
1291 $tmp_privs2['Select'][] = $row2['Column_name'];
1293 if (in_array('Insert', $tmp_array)) {
1294 $tmp_privs2['Insert'][] = $row2['Column_name'];
1296 if (in_array('Update', $tmp_array)) {
1297 $tmp_privs2['Update'][] = $row2['Column_name'];
1299 if (in_array('References', $tmp_array)) {
1300 $tmp_privs2['References'][] = $row2['Column_name'];
1302 unset($tmp_array);
1304 if (count($tmp_privs2['Select']) > 0 && ! in_array('SELECT', $tmp_privs1)) {
1305 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
1307 if (count($tmp_privs2['Insert']) > 0 && ! in_array('INSERT', $tmp_privs1)) {
1308 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
1310 if (count($tmp_privs2['Update']) > 0 && ! in_array('UPDATE', $tmp_privs1)) {
1311 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
1313 if (count($tmp_privs2['References']) > 0 && ! in_array('REFERENCES', $tmp_privs1)) {
1314 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
1316 unset($tmp_privs2);
1317 $queries[] = 'GRANT ' . join(', ', $tmp_privs1)
1318 . ' ON ' . PMA_backquote($row['Db']) . '.' . PMA_backquote($row['Table_name'])
1319 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\''
1320 . (in_array('Grant', explode(',', $row['Table_priv'])) ? ' WITH GRANT OPTION;' : ';');
1326 * Updates privileges
1328 if (! empty($update_privs)) {
1329 $db_and_table = PMA_wildcardEscapeForGrant($dbname, (isset($tablename) ? $tablename : ''));
1331 $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1332 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1333 if (! isset($Grant_priv) || $Grant_priv != 'Y') {
1334 $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
1335 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1336 } else {
1337 $sql_query1 = '';
1340 // Should not do a GRANT USAGE for a table-specific privilege, it
1341 // causes problems later (cannot revoke it)
1342 if (! (isset($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
1343 $sql_query2 = 'GRANT ' . join(', ', PMA_extractPrivInfo())
1344 . ' ON ' . $db_and_table
1345 . ' TO \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\'';
1348 * @todo similar code appears twice in this script
1350 if ((isset($Grant_priv) && $Grant_priv == 'Y')
1351 || (! isset($dbname)
1352 && (isset($max_questions) || isset($max_connections)
1353 || isset($max_updates) || isset($max_user_connections)))
1355 $sql_query2 .= 'WITH';
1356 if (isset($Grant_priv) && $Grant_priv == 'Y') {
1357 $sql_query2 .= ' GRANT OPTION';
1359 if (isset($max_questions)) {
1360 $max_questions = max(0, (int)$max_questions);
1361 $sql_query2 .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1363 if (isset($max_connections)) {
1364 $max_connections = max(0, (int)$max_connections);
1365 $sql_query2 .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1367 if (isset($max_updates)) {
1368 $max_updates = max(0, (int)$max_updates);
1369 $sql_query2 .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1371 if (isset($max_user_connections)) {
1372 $max_user_connections = max(0, (int)$max_user_connections);
1373 $sql_query2 .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1376 $sql_query2 .= ';';
1378 if (! PMA_DBI_try_query($sql_query0)) {
1379 // This might fail when the executing user does not have ALL PRIVILEGES himself.
1380 // See https://sourceforge.net/tracker/index.php?func=detail&aid=3285929&group_id=23067&atid=377408
1381 $sql_query0 = '';
1383 if (isset($sql_query1) && ! PMA_DBI_try_query($sql_query1)) {
1384 // this one may fail, too...
1385 $sql_query1 = '';
1387 if (isset($sql_query2)) {
1388 PMA_DBI_query($sql_query2);
1389 } else {
1390 $sql_query2 = '';
1392 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
1393 $message = PMA_Message::success(__('You have updated the privileges for %s.'));
1394 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1399 * Revokes Privileges
1401 if (isset($_REQUEST['revokeall'])) {
1402 $db_and_table = PMA_wildcardEscapeForGrant($dbname, isset($tablename) ? $tablename : '');
1404 $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1405 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1406 $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
1407 . ' FROM \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\';';
1409 PMA_DBI_query($sql_query0);
1410 if (! PMA_DBI_try_query($sql_query1)) {
1411 // this one may fail, too...
1412 $sql_query1 = '';
1414 $sql_query = $sql_query0 . ' ' . $sql_query1;
1415 $message = PMA_Message::success(__('You have revoked the privileges for %s'));
1416 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1417 if (! isset($tablename)) {
1418 unset($dbname);
1419 } else {
1420 unset($tablename);
1426 * Updates the password
1428 if (isset($_REQUEST['change_pw'])) {
1429 // similar logic in user_password.php
1430 $message = '';
1432 if ($nopass == 0 && isset($pma_pw) && isset($pma_pw2)) {
1433 if ($pma_pw != $pma_pw2) {
1434 $message = PMA_Message::error(__('The passwords aren\'t the same!'));
1435 } elseif (empty($pma_pw) || empty($pma_pw2)) {
1436 $message = PMA_Message::error(__('The password is empty!'));
1438 } // end if
1440 // here $nopass could be == 1
1441 if (empty($message)) {
1443 $hashing_function = (! empty($pw_hash) && $pw_hash == 'old' ? 'OLD_' : '')
1444 . 'PASSWORD';
1446 // in $sql_query which will be displayed, hide the password
1447 $sql_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . preg_replace('@.@s', '*', $pma_pw) . '\')');
1448 $local_query = 'SET PASSWORD FOR \'' . PMA_sqlAddSlashes($username) . '\'@\'' . PMA_sqlAddSlashes($hostname) . '\' = ' . (($pma_pw == '') ? '\'\'' : $hashing_function . '(\'' . PMA_sqlAddSlashes($pma_pw) . '\')');
1449 PMA_DBI_try_query($local_query)
1450 or PMA_mysqlDie(PMA_DBI_getError(), $sql_query, false, $err_url);
1451 $message = PMA_Message::success(__('The password for %s was changed successfully.'));
1452 $message->addParam('\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\'');
1458 * Deletes users
1459 * (Changes / copies a user, part IV)
1462 if (isset($_REQUEST['delete']) || (isset($_REQUEST['change_copy']) && $_REQUEST['mode'] < 4)) {
1463 if (isset($_REQUEST['change_copy'])) {
1464 $selected_usr = array($old_username . '&amp;#27;' . $old_hostname);
1465 } else {
1466 $selected_usr = $_REQUEST['selected_usr'];
1467 $queries = array();
1469 foreach ($selected_usr as $each_user) {
1470 list($this_user, $this_host) = explode('&amp;#27;', $each_user);
1471 $queries[] = '# ' . sprintf(__('Deleting %s'), '\'' . $this_user . '\'@\'' . $this_host . '\'') . ' ...';
1472 $queries[] = 'DROP USER \'' . PMA_sqlAddSlashes($this_user) . '\'@\'' . PMA_sqlAddSlashes($this_host) . '\';';
1474 if (isset($_REQUEST['drop_users_db'])) {
1475 $queries[] = 'DROP DATABASE IF EXISTS ' . PMA_backquote($this_user) . ';';
1476 $GLOBALS['reload'] = true;
1478 if ($GLOBALS['is_ajax_request'] != true) {
1479 PMA_reloadNavigation();
1483 if (empty($_REQUEST['change_copy'])) {
1484 if (empty($queries)) {
1485 $message = PMA_Message::error(__('No users selected for deleting!'));
1486 } else {
1487 if ($_REQUEST['mode'] == 3) {
1488 $queries[] = '# ' . __('Reloading the privileges') . ' ...';
1489 $queries[] = 'FLUSH PRIVILEGES;';
1491 $drop_user_error = '';
1492 foreach ($queries as $sql_query) {
1493 if ($sql_query{0} != '#') {
1494 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
1495 $drop_user_error .= PMA_DBI_getError() . "\n";
1499 // tracking sets this, causing the deleted db to be shown in navi
1500 unset($GLOBALS['db']);
1502 $sql_query = join("\n", $queries);
1503 if (! empty($drop_user_error)) {
1504 $message = PMA_Message::rawError($drop_user_error);
1505 } else {
1506 $message = PMA_Message::success(__('The selected users have been deleted successfully.'));
1509 unset($queries);
1515 * Changes / copies a user, part V
1517 if (isset($_REQUEST['change_copy'])) {
1518 $tmp_count = 0;
1519 foreach ($queries as $sql_query) {
1520 if ($sql_query{0} != '#') {
1521 PMA_DBI_query($sql_query);
1523 // when there is a query containing a hidden password, take it
1524 // instead of the real query sent
1525 if (isset($queries_for_display[$tmp_count])) {
1526 $queries[$tmp_count] = $queries_for_display[$tmp_count];
1528 $tmp_count++;
1530 $message = PMA_Message::success();
1531 $sql_query = join("\n", $queries);
1536 * Reloads the privilege tables into memory
1538 if (isset($_REQUEST['flush_privileges'])) {
1539 $sql_query = 'FLUSH PRIVILEGES;';
1540 PMA_DBI_query($sql_query);
1541 $message = PMA_Message::success(__('The privileges were reloaded successfully.'));
1545 * defines some standard links
1547 $link_edit = '<a class="edit_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . str_replace('%', '%%', $GLOBALS['url_query'])
1548 . '&amp;username=%s'
1549 . '&amp;hostname=%s'
1550 . '&amp;dbname=%s'
1551 . '&amp;tablename=%s">'
1552 . PMA_getIcon('b_usredit.png', __('Edit Privileges'))
1553 . '</a>';
1555 $link_revoke = '<a href="server_privileges.php?' . str_replace('%', '%%', $GLOBALS['url_query'])
1556 . '&amp;username=%s'
1557 . '&amp;hostname=%s'
1558 . '&amp;dbname=%s'
1559 . '&amp;tablename=%s'
1560 . '&amp;revokeall=1">'
1561 . PMA_getIcon('b_usrdrop.png', __('Revoke'))
1562 . '</a>';
1564 $link_export = '<a class="export_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . str_replace('%', '%%', $GLOBALS['url_query'])
1565 . '&amp;username=%s'
1566 . '&amp;hostname=%s'
1567 . '&amp;initial=%s'
1568 . '&amp;export=1">'
1569 . PMA_getIcon('b_tblexport.png', __('Export'))
1570 . '</a>';
1572 $link_export_all = '<a class="export_user_anchor ' . $conditional_class . '" href="server_privileges.php?' . str_replace('%', '%%', $GLOBALS['url_query'])
1573 . '&amp;username=%s'
1574 . '&amp;hostname=%s'
1575 . '&amp;initial=%s'
1576 . '&amp;export=1">'
1577 . PMA_getIcon('b_tblexport.png', __('Export all'))
1578 . '</a>';
1581 * If we are in an Ajax request for Create User/Edit User/Revoke User/
1582 * Flush Privileges, show $message and exit.
1584 if ($GLOBALS['is_ajax_request'] && ! isset($_REQUEST['export']) && (! isset($_REQUEST['submit_mult']) || $_REQUEST['submit_mult'] != 'export') && (! isset($_REQUEST['adduser']) || $_add_user_error) && (! isset($_REQUEST['initial']) || empty($_REQUEST['initial'])) && ! isset($_REQUEST['showall']) && ! isset($_REQUEST['edit_user_dialog']) && ! isset($_REQUEST['db_specific'])) {
1586 if (isset($sql_query)) {
1587 $extra_data['sql_query'] = PMA_showMessage(null, $sql_query);
1590 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
1592 * generate html on the fly for the new user that was just created.
1594 $new_user_string = '<tr>'."\n"
1595 .'<td> <input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_" value="' . htmlspecialchars($username) . '&amp;#27;' . htmlspecialchars($hostname) . '" /> </td>' . "\n"
1596 .'<td><label for="checkbox_sel_users_">' . (empty($username) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($username) ) . '</label></td>' . "\n"
1597 .'<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
1598 $new_user_string .= '<td>';
1600 if (! empty($password) || isset($pma_pw)) {
1601 $new_user_string .= __('Yes');
1602 } else {
1603 $new_user_string .= '<span style="color: #FF0000">' . __('No') . '</span>';
1606 $new_user_string .= '</td>'."\n";
1607 $new_user_string .= '<td><code>' . join(', ', PMA_extractPrivInfo('', true)) . '</code></td>'; //Fill in privileges here
1608 $new_user_string .= '<td>';
1610 if ((isset($Grant_priv) && $Grant_priv == 'Y')) {
1611 $new_user_string .= __('Yes');
1612 } else {
1613 $new_user_string .= __('No');
1616 $new_user_string .='</td>';
1618 $new_user_string .= '<td>' . sprintf($link_edit, urlencode($username), urlencode($hostname), '', '') . '</td>' . "\n";
1619 $new_user_string .= '<td>' . sprintf($link_export, urlencode($username), urlencode($hostname), (isset($initial) ? $initial : '')) . '</td>' . "\n";
1621 $new_user_string .= '</tr>';
1623 $extra_data['new_user_string'] = $new_user_string;
1626 * Generate the string for this alphabet's initial, to update the user
1627 * pagination
1629 $new_user_initial = strtoupper(substr($username, 0, 1));
1630 $new_user_initial_string = '<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&initial=' . $new_user_initial
1631 .'">' . $new_user_initial . '</a>';
1632 $extra_data['new_user_initial'] = $new_user_initial;
1633 $extra_data['new_user_initial_string'] = $new_user_initial_string;
1636 if (isset($update_privs)) {
1637 $extra_data['db_specific_privs'] = false;
1638 if (isset($dbname_is_wildcard)) {
1639 $extra_data['db_specific_privs'] = ! $dbname_is_wildcard;
1641 $new_privileges = join(', ', PMA_extractPrivInfo('', true));
1643 $extra_data['new_privileges'] = $new_privileges;
1646 if ($message instanceof PMA_Message) {
1647 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
1652 * Displays the links
1654 if (isset($viewing_mode) && $viewing_mode == 'db') {
1655 $db = $checkprivs;
1656 $url_query .= '&amp;goto=db_operations.php';
1658 // Gets the database structure
1659 $sub_part = '_structure';
1660 include 'libraries/db_info.inc.php';
1661 echo "\n";
1662 } else {
1663 include 'libraries/server_links.inc.php';
1668 * Displays the page
1671 // export user definition
1672 if (isset($_REQUEST['export']) || (isset($_REQUEST['submit_mult']) && $_REQUEST['submit_mult'] == 'export')) {
1673 $response = '<textarea class="export" cols="' . $GLOBALS['cfg']['TextareaCols'] . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
1674 if ($username == '%') {
1675 // export privileges for all users
1676 $title = __('Privileges for all users');
1677 foreach ($_SESSION['user_host_pairs'] as $pair) {
1678 $response .= PMA_getGrants($pair['user'], $pair['host']);
1679 $response .= "\n";
1681 } elseif (isset($_REQUEST['selected_usr'])) {
1682 // export privileges for selected users
1683 $title = __('Privileges');
1684 foreach ($_REQUEST['selected_usr'] as $export_user) {
1685 $export_username = substr($export_user, 0, strpos($export_user, '&'));
1686 $export_hostname = substr($export_user, strrpos($export_user, ';') + 1);
1687 $response .= '# '
1688 . sprintf(
1689 __('Privileges for %s'),
1690 '`' . htmlspecialchars($export_username) . '`@`' . htmlspecialchars($export_hostname) . '`'
1692 . "\n\n";
1693 $response .= PMA_getGrants($export_username, $export_hostname) . "\n";
1695 } else {
1696 // export privileges for a single user
1697 $title = __('User') . ' `' . htmlspecialchars($username) . '`@`' . htmlspecialchars($hostname) . '`';
1698 $response .= PMA_getGrants($username, $hostname);
1700 // remove trailing whitespace
1701 $response = trim($response);
1703 $response .= '</textarea>';
1704 unset($username, $hostname, $grants, $one_grant);
1705 if ($GLOBALS['is_ajax_request']) {
1706 PMA_ajaxResponse($response, 1, array('title' => $title));
1707 } else {
1708 echo "<h2>$title</h2>$response";
1712 if (empty($_REQUEST['adduser']) && (! isset($checkprivs) || ! strlen($checkprivs))) {
1713 if (! isset($username)) {
1714 // No username is given --> display the overview
1715 echo '<h2>' . "\n"
1716 . PMA_getIcon('b_usrlist.png')
1717 . __('Users overview') . "\n"
1718 . '</h2>' . "\n";
1720 $sql_query = 'SELECT *,' .
1721 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
1722 ' FROM `mysql`.`user`';
1724 $sql_query .= (isset($initial) ? PMA_rangeOfUsers($initial) : '');
1726 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
1727 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1729 if (! $res) {
1730 // the query failed! This may have two reasons:
1731 // - the user does not have enough privileges
1732 // - the privilege tables use a structure of an earlier version.
1733 // so let's try a more simple query
1735 $sql_query = 'SELECT * FROM `mysql`.`user`';
1736 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
1738 if (! $res) {
1739 PMA_Message::error(__('No Privileges'))->display();
1740 PMA_DBI_free_result($res);
1741 unset($res);
1742 } else {
1743 // This message is hardcoded because I will replace it by
1744 // a automatic repair feature soon.
1745 $raw = 'Your privilege table structure seems to be older than'
1746 . ' this MySQL version!<br />'
1747 . 'Please run the <code>mysql_upgrade</code> command'
1748 . '(<code>mysql_fix_privilege_tables</code> on older systems)'
1749 . ' that should be included in your MySQL server distribution'
1750 . ' to solve this problem!';
1751 PMA_Message::rawError($raw)->display();
1753 } else {
1755 // we also want users not in table `user` but in other table
1756 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
1758 $tables_to_search_for_users = array(
1759 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
1762 $db_rights_sqls = array();
1763 foreach ($tables_to_search_for_users as $table_search_in) {
1764 if (in_array($table_search_in, $tables)) {
1765 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`' . $table_search_in . '` ' . (isset($initial) ? PMA_rangeOfUsers($initial) : '');
1769 $user_defaults = array(
1770 'User' => '',
1771 'Host' => '%',
1772 'Password' => '?',
1773 'Grant_priv' => 'N',
1774 'privs' => array('USAGE'),
1777 // for all initials, even non A-Z
1778 $array_initials = array();
1779 // for the rights
1780 $db_rights = array();
1782 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
1783 .' ORDER BY `User` ASC, `Host` ASC';
1785 $db_rights_result = PMA_DBI_query($db_rights_sql);
1787 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
1788 $db_rights_row = array_merge($user_defaults, $db_rights_row);
1789 $db_rights[$db_rights_row['User']][$db_rights_row['Host']]
1790 = $db_rights_row;
1792 PMA_DBI_free_result($db_rights_result);
1793 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
1794 ksort($db_rights);
1797 * Displays the initials
1798 * In an Ajax request, we don't need to show this.
1799 * Also not necassary if there is less than 20 privileges
1801 if ($GLOBALS['is_ajax_request'] != true && PMA_DBI_num_rows($res) > 20 ) {
1803 // initialize to false the letters A-Z
1804 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++) {
1805 if (! isset($array_initials[chr($letter_counter + 64)])) {
1806 $array_initials[chr($letter_counter + 64)] = false;
1810 $initials = PMA_DBI_try_query('SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC', null, PMA_DBI_QUERY_STORE);
1811 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
1812 $array_initials[$tmp_initial] = true;
1815 // Display the initials, which can be any characters, not
1816 // just letters. For letters A-Z, we add the non-used letters
1817 // as greyed out.
1819 uksort($array_initials, "strnatcasecmp");
1821 echo '<table id="initials_table" class="' . $conditional_class . '" <cellspacing="5"><tr>';
1822 foreach ($array_initials as $tmp_initial => $initial_was_found) {
1823 if ($initial_was_found) {
1824 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;initial=' . urlencode($tmp_initial) . '">' . $tmp_initial . '</a></td>' . "\n";
1825 } else {
1826 echo '<td>' . $tmp_initial . '</td>';
1829 echo '<td><a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;showall=1" class="nowrap">[' . __('Show all') . ']</a></td>' . "\n";
1830 echo '</tr></table>';
1834 * Display the user overview
1835 * (if less than 50 users, display them immediately)
1838 if (isset($initial) || isset($showall) || PMA_DBI_num_rows($res) < 50) {
1840 while ($row = PMA_DBI_fetch_assoc($res)) {
1841 $row['privs'] = PMA_extractPrivInfo($row, true);
1842 $db_rights[$row['User']][$row['Host']] = $row;
1844 @PMA_DBI_free_result($res);
1845 unset($res);
1847 echo '<form name="usersForm" id="usersForm" action="server_privileges.php" method="post">' . "\n"
1848 . PMA_generate_common_hidden_inputs('', '')
1849 . ' <table id="tableuserrights" class="data">' . "\n"
1850 . ' <thead>' . "\n"
1851 . ' <tr><th></th>' . "\n"
1852 . ' <th>' . __('User') . '</th>' . "\n"
1853 . ' <th>' . __('Host') . '</th>' . "\n"
1854 . ' <th>' . __('Password') . '</th>' . "\n"
1855 . ' <th>' . __('Global privileges') . ' '
1856 . PMA_showHint(__('Note: MySQL privilege names are expressed in English')) . '</th>' . "\n"
1857 . ' <th>' . __('Grant') . '</th>' . "\n"
1858 . ' <th colspan="2">' . __('Action') . '</th>' . "\n";
1859 echo ' </tr>' . "\n";
1860 echo ' </thead>' . "\n";
1861 echo ' <tbody>' . "\n";
1863 $_SESSION['user_host_pairs'] = array();
1864 $pair_count = 0;
1865 $odd_row = true;
1866 $index_checkbox = -1;
1867 foreach ($db_rights as $user) {
1868 $index_checkbox++;
1869 ksort($user);
1870 foreach ($user as $host) {
1871 $index_checkbox++;
1872 echo ' <tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
1873 . ' <td><input type="checkbox" name="selected_usr[]" id="checkbox_sel_users_'
1874 . $index_checkbox . '" value="'
1875 . htmlspecialchars($host['User'] . '&amp;#27;' . $host['Host'])
1876 . '"'
1877 . (empty($GLOBALS['checkall']) ? '' : ' checked="checked"')
1878 . ' /></td>' . "\n"
1879 . ' <td><label for="checkbox_sel_users_' . $index_checkbox . '">' . (empty($host['User']) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
1880 . ' <td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
1881 echo ' <td>';
1882 switch ($host['Password']) {
1883 case 'Y':
1884 echo __('Yes');
1885 break;
1886 case 'N':
1887 echo '<span style="color: #FF0000">' . __('No') . '</span>';
1888 break;
1889 // this happens if this is a definition not coming from mysql.user
1890 default:
1891 echo '--'; // in future version, replace by "not present"
1892 break;
1893 } // end switch
1894 echo '</td>' . "\n"
1895 . ' <td><code>' . "\n"
1896 . ' ' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
1897 . ' </code></td>' . "\n"
1898 . ' <td>' . ($host['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . '</td>' . "\n"
1899 . ' <td class="center">';
1900 printf($link_edit, urlencode($host['User']), urlencode($host['Host']), '', '');
1901 echo '</td>';
1902 echo '<td class="center">';
1903 printf($link_export, urlencode($host['User']), urlencode($host['Host']), (isset($initial) ? $initial : ''));
1904 echo '</td>';
1905 echo '</tr>';
1906 $odd_row = ! $odd_row;
1908 $_SESSION['user_host_pairs'][$pair_count]['user'] = $host['User'];
1909 $_SESSION['user_host_pairs'][$pair_count]['host'] = $host['Host'];
1910 $pair_count ++;
1914 unset($user, $host, $odd_row);
1915 echo ' </tbody></table>' . "\n"
1916 .'<div>'
1917 .'<div style="float:left;">'
1918 .'<img class="selectallarrow"'
1919 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
1920 .' width="38" height="22"'
1921 .' alt="' . __('With selected:') . '" />' . "\n"
1922 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;checkall=1"'
1923 .' onclick="if (markAllRows(\'usersForm\')) return false;">'
1924 . __('Check All') . '</a>' . "\n"
1925 .'/' . "\n"
1926 .'<a href="server_privileges.php?' . $GLOBALS['url_query'] . '"'
1927 .' onclick="if (unMarkAllRows(\'usersForm\')) return false;">'
1928 . __('Uncheck All') . '</a>' . "\n"
1929 .'<i>' . __('With selected:') . '</i>' . "\n";
1931 PMA_buttonOrImage(
1932 'submit_mult', 'mult_submit', 'submit_mult_export',
1933 __('Export'), 'b_tblexport.png', 'export'
1935 echo '<input type="hidden" name="initial" value="' . (isset($initial) ? $initial : '') . '" />';
1936 echo '</div>'
1937 . '<div class="clear_both" style="clear:both"></div>'
1938 . '<div style="float:left; padding-left:10px;">';
1939 printf($link_export_all, urlencode('%'), urlencode('%'), (isset($initial) ? $initial : ''));
1940 echo '</div>'
1941 . '</div>'
1942 . '<div class="clear_both" style="clear:both"></div>';
1944 // add/delete user fieldset
1945 echo ' <fieldset id="fieldset_add_user">' . "\n"
1946 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1947 . PMA_getIcon('b_usradd.png')
1948 . ' ' . __('Add user') . '</a>' . "\n"
1949 . ' </fieldset>' . "\n"
1950 . ' <fieldset id="fieldset_delete_user">'
1951 . ' <legend>' . "\n"
1952 . PMA_getIcon('b_usrdrop.png')
1953 . ' ' . __('Remove selected users') . '' . "\n"
1954 . ' </legend>' . "\n"
1955 . ' <input type="hidden" name="mode" value="2" />' . "\n"
1956 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')<br />' . "\n"
1957 . ' <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"
1958 . ' <label for="checkbox_drop_users_db" title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
1959 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
1960 . ' </label>' . "\n"
1961 . ' </fieldset>' . "\n"
1962 . ' <fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n"
1963 . ' <input type="submit" name="delete" value="' . __('Go') . '" id="buttonGo" class="' . $conditional_class . '"/>' . "\n"
1964 . ' </fieldset>' . "\n"
1965 . '</form>' . "\n";
1966 } else {
1968 unset ($row);
1969 echo ' <fieldset id="fieldset_add_user">' . "\n"
1970 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1" class="' . $conditional_class . '">' . "\n"
1971 . PMA_getIcon('b_usradd.png')
1972 . ' ' . __('Add user') . '</a>' . "\n"
1973 . ' </fieldset>' . "\n";
1974 } // end if (display overview)
1976 if ($GLOBALS['is_ajax_request']) {
1977 exit;
1980 $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);
1981 $flushnote->addParam('<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;flush_privileges=1" id="reload_privileges_anchor" class="' . $conditional_class . '">', false);
1982 $flushnote->addParam('</a>', false);
1983 $flushnote->display();
1987 } else {
1989 // A user was selected -> display the user's properties
1991 // In an Ajax request, prevent cached values from showing
1992 if ($GLOBALS['is_ajax_request'] == true) {
1993 header('Cache-Control: no-cache');
1996 echo '<h2>' . "\n"
1997 . PMA_getIcon('b_usredit.png')
1998 . __('Edit Privileges') . ': '
1999 . __('User');
2001 if (isset($dbname)) {
2002 echo ' <i><a href="server_privileges.php?'
2003 . $GLOBALS['url_query'] . '&amp;username=' . htmlspecialchars(urlencode($username))
2004 . '&amp;hostname=' . htmlspecialchars(urlencode($hostname)) . '&amp;dbname=&amp;tablename=">\''
2005 . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
2006 . '\'</a></i>' . "\n";
2007 $url_dbname = urlencode(str_replace(array('\_', '\%'), array('_', '%'), $dbname));
2009 echo ' - ' . ($dbname_is_wildcard ? __('Databases') : __('Database') );
2010 if (isset($tablename)) {
2011 echo ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
2012 . '&amp;username=' . htmlspecialchars(urlencode($username)) . '&amp;hostname=' . htmlspecialchars(urlencode($hostname))
2013 . '&amp;dbname=' . htmlspecialchars($url_dbname) . '&amp;tablename=">' . htmlspecialchars($dbname) . '</a></i>';
2014 echo ' - ' . __('Table') . ' <i>' . htmlspecialchars($tablename) . '</i>';
2015 } else {
2016 echo ' <i>' . htmlspecialchars($dbname) . '</i>';
2019 } else {
2020 echo ' <i>\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname)
2021 . '\'</i>' . "\n";
2024 echo '</h2>' . "\n";
2027 $sql = "SELECT '1' FROM `mysql`.`user`"
2028 . " WHERE `User` = '" . PMA_sqlAddSlashes($username) . "'"
2029 . " AND `Host` = '" . PMA_sqlAddSlashes($hostname) . "';";
2030 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
2031 unset($sql);
2032 if ($user_does_not_exists) {
2033 PMA_Message::error(__('The selected user was not found in the privilege table.'))->display();
2034 PMA_displayLoginInformationFields();
2035 //require 'libraries/footer.inc.php';
2038 echo '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n";
2039 $_params = array(
2040 'username' => $username,
2041 'hostname' => $hostname,
2043 if (isset($dbname)) {
2044 $_params['dbname'] = $dbname;
2045 if (isset($tablename)) {
2046 $_params['tablename'] = $tablename;
2049 echo PMA_generate_common_hidden_inputs($_params);
2051 PMA_displayPrivTable(
2052 PMA_ifSetOr($dbname, '*', 'length'),
2053 PMA_ifSetOr($tablename, '*', 'length')
2056 echo '</form>' . "\n";
2058 if (! isset($tablename) && empty($dbname_is_wildcard)) {
2060 // no table name was given, display all table specific rights
2061 // but only if $dbname contains no wildcards
2063 // table header
2064 echo '<form action="server_privileges.php" id="db_or_table_specific_priv" method="post">' . "\n"
2065 . PMA_generate_common_hidden_inputs('', '')
2066 . '<input type="hidden" name="username" value="' . htmlspecialchars($username) . '" />' . "\n"
2067 . '<input type="hidden" name="hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
2068 . '<fieldset>' . "\n"
2069 . '<legend>' . (! isset($dbname) ? __('Database-specific privileges') : __('Table-specific privileges')) . '</legend>' . "\n"
2070 . '<table class="data">' . "\n"
2071 . '<thead>' . "\n"
2072 . '<tr><th>' . (! isset($dbname) ? __('Database') : __('Table')) . '</th>' . "\n"
2073 . ' <th>' . __('Privileges') . '</th>' . "\n"
2074 . ' <th>' . __('Grant') . '</th>' . "\n"
2075 . ' <th>' . (! isset($dbname) ? __('Table-specific privileges') : __('Column-specific privileges')) . '</th>' . "\n"
2076 . ' <th colspan="2">' . __('Action') . '</th>' . "\n"
2077 . '</tr>' . "\n"
2078 . '</thead>' . "\n"
2079 . '<tbody>' . "\n";
2081 $user_host_condition = ' WHERE `User`'
2082 . ' = \'' . PMA_sqlAddSlashes($username) . "'"
2083 . ' AND `Host`'
2084 . ' = \'' . PMA_sqlAddSlashes($hostname) . "'";
2086 // table body
2087 // get data
2089 // we also want privielgs for this user not in table `db` but in other table
2090 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
2091 if (! isset($dbname)) {
2093 // no db name given, so we want all privs for the given user
2095 $tables_to_search_for_users = array(
2096 'tables_priv', 'columns_priv',
2099 $db_rights_sqls = array();
2100 foreach ($tables_to_search_for_users as $table_search_in) {
2101 if (in_array($table_search_in, $tables)) {
2102 $db_rights_sqls[] = '
2103 SELECT DISTINCT `Db`
2104 FROM `mysql`.' . PMA_backquote($table_search_in)
2105 . $user_host_condition;
2109 $user_defaults = array(
2110 'Db' => '',
2111 'Grant_priv' => 'N',
2112 'privs' => array('USAGE'),
2113 'Table_privs' => true,
2116 // for the rights
2117 $db_rights = array();
2119 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
2120 .' ORDER BY `Db` ASC';
2122 $db_rights_result = PMA_DBI_query($db_rights_sql);
2124 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
2125 $db_rights_row = array_merge($user_defaults, $db_rights_row);
2126 // only Db names in the table `mysql`.`db` uses wildcards
2127 // as we are in the db specific rights display we want
2128 // all db names escaped, also from other sources
2129 $db_rights_row['Db'] = PMA_escape_mysql_wildcards(
2130 $db_rights_row['Db']
2132 $db_rights[$db_rights_row['Db']] = $db_rights_row;
2135 PMA_DBI_free_result($db_rights_result);
2136 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
2138 $sql_query = 'SELECT * FROM `mysql`.`db`' . $user_host_condition . ' ORDER BY `Db` ASC';
2139 $res = PMA_DBI_query($sql_query);
2140 $sql_query = '';
2142 while ($row = PMA_DBI_fetch_assoc($res)) {
2143 if (isset($db_rights[$row['Db']])) {
2144 $db_rights[$row['Db']] = array_merge($db_rights[$row['Db']], $row);
2145 } else {
2146 $db_rights[$row['Db']] = $row;
2148 // there are db specific rights for this user
2149 // so we can drop this db rights
2150 $db_rights[$row['Db']]['can_delete'] = true;
2152 PMA_DBI_free_result($res);
2153 unset($row, $res);
2155 } else {
2157 // db name was given,
2158 // so we want all user specific rights for this db
2160 $user_host_condition .=
2161 ' AND `Db`'
2162 .' LIKE \'' . PMA_sqlAddSlashes($dbname, true) . "'";
2164 $tables_to_search_for_users = array(
2165 'columns_priv',
2168 $db_rights_sqls = array();
2169 foreach ($tables_to_search_for_users as $table_search_in) {
2170 if (in_array($table_search_in, $tables)) {
2171 $db_rights_sqls[] = '
2172 SELECT DISTINCT `Table_name`
2173 FROM `mysql`.' . PMA_backquote($table_search_in)
2174 . $user_host_condition;
2178 $user_defaults = array(
2179 'Table_name' => '',
2180 'Grant_priv' => 'N',
2181 'privs' => array('USAGE'),
2182 'Column_priv' => true,
2185 // for the rights
2186 $db_rights = array();
2188 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
2189 .' ORDER BY `Table_name` ASC';
2191 $db_rights_result = PMA_DBI_query($db_rights_sql);
2193 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
2194 $db_rights_row = array_merge($user_defaults, $db_rights_row);
2195 $db_rights[$db_rights_row['Table_name']] = $db_rights_row;
2197 PMA_DBI_free_result($db_rights_result);
2198 unset($db_rights_sql, $db_rights_sqls, $db_rights_result, $db_rights_row);
2200 $sql_query = 'SELECT `Table_name`,'
2201 .' `Table_priv`,'
2202 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
2203 .' AS \'Column_priv\''
2204 .' FROM `mysql`.`tables_priv`'
2205 . $user_host_condition
2206 .' ORDER BY `Table_name` ASC;';
2207 $res = PMA_DBI_query($sql_query);
2208 $sql_query = '';
2210 while ($row = PMA_DBI_fetch_assoc($res)) {
2211 if (isset($db_rights[$row['Table_name']])) {
2212 $db_rights[$row['Table_name']] = array_merge($db_rights[$row['Table_name']], $row);
2213 } else {
2214 $db_rights[$row['Table_name']] = $row;
2217 PMA_DBI_free_result($res);
2218 unset($row, $res);
2220 ksort($db_rights);
2222 // display rows
2223 if (count($db_rights) < 1) {
2224 echo '<tr class="odd">' . "\n"
2225 . ' <td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
2226 . '</tr>' . "\n";
2227 } else {
2228 $odd_row = true;
2229 $found_rows = array();
2230 //while ($row = PMA_DBI_fetch_assoc($res)) {
2231 foreach ($db_rights as $row) {
2232 $found_rows[] = (! isset($dbname)) ? $row['Db'] : $row['Table_name'];
2234 echo '<tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2235 . ' <td>' . htmlspecialchars((! isset($dbname)) ? $row['Db'] : $row['Table_name']) . '</td>' . "\n"
2236 . ' <td><code>' . "\n"
2237 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($row, true)) . "\n"
2238 . ' </code></td>' . "\n"
2239 . ' <td>' . ((((! isset($dbname)) && $row['Grant_priv'] == 'Y') || (isset($dbname) && in_array('Grant', explode(',', $row['Table_priv'])))) ? __('Yes') : __('No')) . '</td>' . "\n"
2240 . ' <td>';
2241 if (! empty($row['Table_privs']) || ! empty ($row['Column_priv'])) {
2242 echo __('Yes');
2243 } else {
2244 echo __('No');
2246 echo '</td>' . "\n"
2247 . ' <td>';
2248 printf(
2249 $link_edit,
2250 htmlspecialchars(urlencode($username)),
2251 urlencode(htmlspecialchars($hostname)),
2252 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
2253 urlencode((! isset($dbname)) ? '' : $row['Table_name'])
2255 echo '</td>' . "\n"
2256 . ' <td>';
2257 if (! empty($row['can_delete']) || isset($row['Table_name']) && strlen($row['Table_name'])) {
2258 printf(
2259 $link_revoke,
2260 htmlspecialchars(urlencode($username)),
2261 urlencode(htmlspecialchars($hostname)),
2262 urlencode((! isset($dbname)) ? $row['Db'] : htmlspecialchars($dbname)),
2263 urlencode((! isset($dbname)) ? '' : $row['Table_name'])
2266 echo '</td>' . "\n"
2267 . '</tr>' . "\n";
2268 $odd_row = ! $odd_row;
2269 } // end while
2271 unset($row);
2272 echo '</tbody>' . "\n"
2273 . '</table>' . "\n";
2275 if (! isset($dbname)) {
2277 // no database name was given, display select db
2279 $pred_db_array =PMA_DBI_fetch_result('SHOW DATABASES;');
2281 echo ' <label for="text_dbname">' . __('Add privileges on the following database') . ':</label>' . "\n";
2282 if (! empty($pred_db_array)) {
2283 echo ' <select name="pred_dbname" class="autosubmit">' . "\n"
2284 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2285 foreach ($pred_db_array as $current_db) {
2286 $current_db = PMA_escape_mysql_wildcards($current_db);
2287 // cannot use array_diff() once, outside of the loop,
2288 // because the list of databases has special characters
2289 // already escaped in $found_rows,
2290 // contrary to the output of SHOW DATABASES
2291 if (empty($found_rows) || ! in_array($current_db, $found_rows)) {
2292 echo ' <option value="' . htmlspecialchars($current_db) . '">'
2293 . htmlspecialchars($current_db) . '</option>' . "\n";
2296 echo ' </select>' . "\n";
2298 echo ' <input type="text" id="text_dbname" name="dbname" />' . "\n"
2299 . PMA_showHint(__('Wildcards % and _ should be escaped with a \ to use them literally'));
2300 } else {
2301 echo ' <input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '"/>' . "\n"
2302 . ' <label for="text_tablename">' . __('Add privileges on the following table') . ':</label>' . "\n";
2303 if ($res = @PMA_DBI_try_query('SHOW TABLES FROM ' . PMA_backquote(PMA_unescape_mysql_wildcards($dbname)) . ';', null, PMA_DBI_QUERY_STORE)) {
2304 $pred_tbl_array = array();
2305 while ($row = PMA_DBI_fetch_row($res)) {
2306 if (! isset($found_rows) || ! in_array($row[0], $found_rows)) {
2307 $pred_tbl_array[] = $row[0];
2310 PMA_DBI_free_result($res);
2311 unset($res, $row);
2312 if (! empty($pred_tbl_array)) {
2313 echo ' <select name="pred_tablename" class="autosubmit">' . "\n"
2314 . ' <option value="" selected="selected">' . __('Use text field') . ':</option>' . "\n";
2315 foreach ($pred_tbl_array as $current_table) {
2316 echo ' <option value="' . htmlspecialchars($current_table) . '">' . htmlspecialchars($current_table) . '</option>' . "\n";
2318 echo ' </select>' . "\n";
2320 } else {
2321 unset($res);
2323 echo ' <input type="text" id="text_tablename" name="tablename" />' . "\n";
2325 echo '</fieldset>' . "\n";
2326 echo '<fieldset class="tblFooters">' . "\n"
2327 . ' <input type="submit" value="' . __('Go') . '" />'
2328 . '</fieldset>' . "\n"
2329 . '</form>' . "\n";
2333 // Provide a line with links to the relevant database and table
2334 if (isset($dbname) && empty($dbname_is_wildcard)) {
2335 echo '[ ' . __('Database')
2336 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
2337 . $GLOBALS['url_query'] . '&amp;db=' . $url_dbname . '&amp;reload=1">'
2338 . htmlspecialchars($dbname) . ': ' . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabDatabase']) . "</a> ]\n";
2340 if (isset($tablename)) {
2341 echo ' [ ' . __('Table') . ' <a href="'
2342 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
2343 . '&amp;db=' . $url_dbname . '&amp;table=' . htmlspecialchars(urlencode($tablename))
2344 . '&amp;reload=1">' . htmlspecialchars($tablename) . ': '
2345 . PMA_getTitleForTarget($GLOBALS['cfg']['DefaultTabTable'])
2346 . "</a> ]\n";
2348 unset($url_dbname);
2351 if (! isset($dbname) && ! $user_does_not_exists) {
2352 include_once 'libraries/display_change_password.lib.php';
2354 echo '<form action="server_privileges.php" method="post" onsubmit="return checkPassword(this);">' . "\n"
2355 . PMA_generate_common_hidden_inputs('', '')
2356 . '<input type="hidden" name="old_username" value="' . htmlspecialchars($username) . '" />' . "\n"
2357 . '<input type="hidden" name="old_hostname" value="' . htmlspecialchars($hostname) . '" />' . "\n"
2358 . '<fieldset id="fieldset_change_copy_user">' . "\n"
2359 . ' <legend>' . __('Change Login Information / Copy User') . '</legend>' . "\n";
2360 PMA_displayLoginInformationFields('change');
2361 echo ' <fieldset>' . "\n"
2362 . ' <legend>' . __('Create a new user with the same privileges and ...') . '</legend>' . "\n";
2363 $choices = array(
2364 '4' => __('... keep the old one.'),
2365 '1' => __('... delete the old one from the user tables.'),
2366 '2' => __('... revoke all active privileges from the old one and delete it afterwards.'),
2367 '3' => __('... delete the old one from the user tables and reload the privileges afterwards.'));
2368 PMA_display_html_radio('mode', $choices, '4', true);
2369 unset($choices);
2371 echo ' </fieldset>' . "\n"
2372 . '</fieldset>' . "\n"
2373 . '<fieldset id="fieldset_change_copy_user_footer" class="tblFooters">' . "\n"
2374 . ' <input type="submit" name="change_copy" value="' . __('Go') . '" />' . "\n"
2375 . '</fieldset>' . "\n"
2376 . '</form>' . "\n";
2379 } elseif (isset($_REQUEST['adduser'])) {
2381 // Add user
2382 $GLOBALS['url_query'] .= '&amp;adduser=1';
2383 echo '<h2>' . "\n"
2384 . PMA_getIcon('b_usradd.png') . __('Add user') . "\n"
2385 . '</h2>' . "\n"
2386 . '<form name="usersForm" id="addUsersForm_' . $random_n . '" action="server_privileges.php" method="post">' . "\n"
2387 . PMA_generate_common_hidden_inputs('', '');
2388 PMA_displayLoginInformationFields('new');
2389 echo '<fieldset id="fieldset_add_user_database">' . "\n"
2390 . '<legend>' . __('Database for user') . '</legend>' . "\n";
2392 PMA_display_html_checkbox('createdb-1', __('Create database with same name and grant all privileges'), false, false);
2393 echo '<br />' . "\n";
2394 PMA_display_html_checkbox('createdb-2', __('Grant all privileges on wildcard name (username\\_%)'), false, false);
2395 echo '<br />' . "\n";
2397 if (! empty($dbname) ) {
2398 PMA_display_html_checkbox('createdb-3', sprintf(__('Grant all privileges on database &quot;%s&quot;'), htmlspecialchars($dbname)), true, false);
2399 echo '<input type="hidden" name="dbname" value="' . htmlspecialchars($dbname) . '" />' . "\n";
2400 echo '<br />' . "\n";
2403 echo '</fieldset>' . "\n";
2404 PMA_displayPrivTable('*', '*', false);
2405 echo ' <fieldset id="fieldset_add_user_footer" class="tblFooters">' . "\n"
2406 . ' <input type="submit" name="adduser_submit" value="' . __('Go') . '" />' . "\n"
2407 . ' </fieldset>' . "\n"
2408 . '</form>' . "\n";
2409 } else {
2410 // check the privileges for a particular database.
2411 $user_form = '<form id="usersForm" action="server_privileges.php"><fieldset>' . "\n"
2412 . '<legend>' . "\n"
2413 . PMA_getIcon('b_usrcheck.png')
2414 . ' ' . sprintf(__('Users having access to &quot;%s&quot;'), '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($checkprivs) . '">' . htmlspecialchars($checkprivs) . '</a>') . "\n"
2415 . '</legend>' . "\n"
2416 . '<table id="dbspecificuserrights" class="data">' . "\n"
2417 . '<thead>' . "\n"
2418 . ' <tr><th>' . __('User') . '</th>' . "\n"
2419 . ' <th>' . __('Host') . '</th>' . "\n"
2420 . ' <th>' . __('Type') . '</th>' . "\n"
2421 . ' <th>' . __('Privileges') . '</th>' . "\n"
2422 . ' <th>' . __('Grant') . '</th>' . "\n"
2423 . ' <th>' . __('Action') . '</th>' . "\n"
2424 . ' </tr>' . "\n"
2425 . '</thead>' . "\n"
2426 . '<tbody>' . "\n";
2427 $odd_row = true;
2428 unset($row, $row1, $row2);
2430 // now, we build the table...
2431 $list_of_privileges
2432 = '`User`, '
2433 . '`Host`, '
2434 . '`Select_priv`, '
2435 . '`Insert_priv`, '
2436 . '`Update_priv`, '
2437 . '`Delete_priv`, '
2438 . '`Create_priv`, '
2439 . '`Drop_priv`, '
2440 . '`Grant_priv`, '
2441 . '`Index_priv`, '
2442 . '`Alter_priv`, '
2443 . '`References_priv`, '
2444 . '`Create_tmp_table_priv`, '
2445 . '`Lock_tables_priv`, '
2446 . '`Create_view_priv`, '
2447 . '`Show_view_priv`, '
2448 . '`Create_routine_priv`, '
2449 . '`Alter_routine_priv`, '
2450 . '`Execute_priv`';
2452 $list_of_compared_privileges
2453 = '`Select_priv` = \'N\''
2454 . ' AND `Insert_priv` = \'N\''
2455 . ' AND `Update_priv` = \'N\''
2456 . ' AND `Delete_priv` = \'N\''
2457 . ' AND `Create_priv` = \'N\''
2458 . ' AND `Drop_priv` = \'N\''
2459 . ' AND `Grant_priv` = \'N\''
2460 . ' AND `References_priv` = \'N\''
2461 . ' AND `Create_tmp_table_priv` = \'N\''
2462 . ' AND `Lock_tables_priv` = \'N\''
2463 . ' AND `Create_view_priv` = \'N\''
2464 . ' AND `Show_view_priv` = \'N\''
2465 . ' AND `Create_routine_priv` = \'N\''
2466 . ' AND `Alter_routine_priv` = \'N\''
2467 . ' AND `Execute_priv` = \'N\'';
2469 if (PMA_MYSQL_INT_VERSION >= 50106) {
2470 $list_of_privileges .=
2471 ', `Event_priv`, '
2472 . '`Trigger_priv`';
2473 $list_of_compared_privileges .=
2474 ' AND `Event_priv` = \'N\''
2475 . ' AND `Trigger_priv` = \'N\'';
2478 $sql_query = '(SELECT ' . $list_of_privileges . ', `Db`'
2479 .' FROM `mysql`.`db`'
2480 .' WHERE \'' . PMA_sqlAddSlashes($checkprivs) . "'"
2481 .' LIKE `Db`'
2482 .' AND NOT (' . $list_of_compared_privileges. ')) '
2483 .'UNION '
2484 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
2485 .' FROM `mysql`.`user` '
2486 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
2487 .' ORDER BY `User` ASC,'
2488 .' `Host` ASC,'
2489 .' `Db` ASC;';
2490 $res = PMA_DBI_query($sql_query);
2491 $row = PMA_DBI_fetch_assoc($res);
2492 if ($row) {
2493 $found = true;
2496 if ($found) {
2497 while (true) {
2498 // prepare the current user
2499 $current_privileges = array();
2500 $current_user = $row['User'];
2501 $current_host = $row['Host'];
2502 while ($row && $current_user == $row['User'] && $current_host == $row['Host']) {
2503 $current_privileges[] = $row;
2504 $row = PMA_DBI_fetch_assoc($res);
2506 $user_form .= ' <tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2507 . ' <td';
2508 if (count($current_privileges) > 1) {
2509 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2511 $user_form .= '>' . (empty($current_user) ? '<span style="color: #FF0000">' . __('Any') . '</span>' : htmlspecialchars($current_user)) . "\n"
2512 . ' </td>' . "\n"
2513 . ' <td';
2514 if (count($current_privileges) > 1) {
2515 $user_form .= ' rowspan="' . count($current_privileges) . '"';
2517 $user_form .= '>' . htmlspecialchars($current_host) . '</td>' . "\n";
2518 for ($i = 0; $i < count($current_privileges); $i++) {
2519 $current = $current_privileges[$i];
2520 $user_form .= ' <td>' . "\n"
2521 . ' ';
2522 if (! isset($current['Db']) || $current['Db'] == '*') {
2523 $user_form .= __('global');
2524 } elseif ($current['Db'] == PMA_escape_mysql_wildcards($checkprivs)) {
2525 $user_form .= __('database-specific');
2526 } else {
2527 $user_form .= __('wildcard'). ': <code>' . htmlspecialchars($current['Db']) . '</code>';
2529 $user_form .= "\n"
2530 . ' </td>' . "\n"
2531 . ' <td>' . "\n"
2532 . ' <code>' . "\n"
2533 . ' ' . join(',' . "\n" . ' ', PMA_extractPrivInfo($current, true)) . "\n"
2534 . ' </code>' . "\n"
2535 . ' </td>' . "\n"
2536 . ' <td>' . "\n"
2537 . ' ' . ($current['Grant_priv'] == 'Y' ? __('Yes') : __('No')) . "\n"
2538 . ' </td>' . "\n"
2539 . ' <td>' . "\n";
2540 $user_form .= sprintf(
2541 $link_edit,
2542 urlencode($current_user),
2543 urlencode($current_host),
2544 urlencode(! isset($current['Db']) || $current['Db'] == '*' ? '' : $current['Db']),
2547 $user_form .= '</td>' . "\n"
2548 . ' </tr>' . "\n";
2549 if (($i + 1) < count($current_privileges)) {
2550 $user_form .= '<tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">' . "\n";
2553 if (empty($row) && empty($row1) && empty($row2)) {
2554 break;
2556 $odd_row = ! $odd_row;
2558 } else {
2559 $user_form .= ' <tr class="odd">' . "\n"
2560 . ' <td colspan="6">' . "\n"
2561 . ' ' . __('No user found.') . "\n"
2562 . ' </td>' . "\n"
2563 . ' </tr>' . "\n";
2565 $user_form .= '</tbody>' . "\n"
2566 . '</table></fieldset></form>' . "\n";
2568 if ($GLOBALS['is_ajax_request'] == true) {
2569 $extra_data['user_form'] = $user_form;
2570 $message = PMA_Message::success(__('User has been added.'));
2571 PMA_ajaxResponse($message, $message->isSuccess(), $extra_data);
2572 } else {
2573 // Offer to create a new user for the current database
2574 $user_form .= '<fieldset id="fieldset_add_user">' . "\n"
2575 . '<legend>' . __('New') . '</legend>' . "\n"
2576 . ' <a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;adduser=1&amp;dbname=' . htmlspecialchars($checkprivs) .'" rel="'.'checkprivs='.htmlspecialchars($checkprivs). '&amp;'.$GLOBALS['url_query'] . '" class="'.$conditional_class.'" name="db_specific">' . "\n"
2577 . PMA_getIcon('b_usradd.png')
2578 . ' ' . __('Add user') . '</a>' . "\n"
2579 . '</fieldset>' . "\n";
2580 echo $user_form ;
2583 } // end if (empty($_REQUEST['adduser']) && empty($checkprivs)) ... elseif ... else ...
2587 * Displays the footer
2589 echo "\n\n";
2590 require 'libraries/footer.inc.php';