Translated using Weblate (Kurdish Sorani)
[phpmyadmin.git] / libraries / server_privileges.lib.php
blob8e4752972ebba8a425241bf28b80d79ce9253c24
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * set of functions with the Privileges section in pma
6 * @package PhpMyAdmin
7 */
9 if (! defined('PHPMYADMIN')) {
10 exit;
13 /**
14 * Get Html for User Group Dialog
16 * @param string $username username
17 * @param bool $is_menuswork Is menuswork set in configuration
19 * @return string html
21 function PMA_getHtmlForUserGroupDialog($username, $is_menuswork)
23 $html = '';
24 if (! empty($_REQUEST['edit_user_group_dialog']) && $is_menuswork) {
25 $dialog = PMA_getHtmlToChooseUserGroup($username);
26 $response = PMA_Response::getInstance();
27 if ($GLOBALS['is_ajax_request']) {
28 $response->addJSON('message', $dialog);
29 exit;
30 } else {
31 $html .= $dialog;
35 return $html;
38 /**
39 * Escapes wildcard in a database+table specification
40 * before using it in a GRANT statement.
42 * Escaping a wildcard character in a GRANT is only accepted at the global
43 * or database level, not at table level; this is why I remove
44 * the escaping character. Internally, in mysql.tables_priv.Db there are
45 * no escaping (for example test_db) but in mysql.db you'll see test\_db
46 * for a db-specific privilege.
48 * @param string $dbname Database name
49 * @param string $tablename Table name
51 * @return string the escaped (if necessary) database.table
53 function PMA_wildcardEscapeForGrant($dbname, $tablename)
55 if (! strlen($dbname)) {
56 $db_and_table = '*.*';
57 } else {
58 if (strlen($tablename)) {
59 $db_and_table = PMA_Util::backquote(
60 PMA_Util::unescapeMysqlWildcards($dbname)
62 . '.' . PMA_Util::backquote($tablename);
63 } else {
64 $db_and_table = PMA_Util::backquote($dbname) . '.*';
67 return $db_and_table;
70 /**
71 * Generates a condition on the user name
73 * @param string $initial the user's initial
75 * @return string the generated condition
77 function PMA_rangeOfUsers($initial = '')
79 // strtolower() is used because the User field
80 // might be BINARY, so LIKE would be case sensitive
81 if (! empty($initial)) {
82 $ret = " WHERE `User` LIKE '"
83 . PMA_Util::sqlAddSlashes($initial, true) . "%'"
84 . " OR `User` LIKE '"
85 . PMA_Util::sqlAddSlashes(strtolower($initial), true) . "%'";
86 } else {
87 $ret = '';
89 return $ret;
90 } // end function
92 /**
93 * Extracts the privilege information of a priv table row
95 * @param array $row the row
96 * @param boolean $enableHTML add <dfn> tag with tooltips
97 * @param boolean $tablePrivs whether row contains table privileges
99 * @global resource $user_link the database connection
101 * @return array
103 function PMA_extractPrivInfo($row = '', $enableHTML = false, $tablePrivs = false)
105 if ($tablePrivs) {
106 $grants = PMA_getTableGrantsArray();
107 } else {
108 $grants = PMA_getGrantsArray();
111 if (! empty($row) && isset($row['Table_priv'])) {
112 $row1 = $GLOBALS['dbi']->fetchSingleRow(
113 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
114 'ASSOC', $GLOBALS['userlink']
116 $av_grants = explode(
117 '\',\'',
118 substr($row1['Type'], 5, strlen($row1['Type']) - 7)
120 unset($row1);
121 $users_grants = explode(',', $row['Table_priv']);
122 foreach ($av_grants as $current_grant) {
123 $row[$current_grant . '_priv']
124 = in_array($current_grant, $users_grants) ? 'Y' : 'N';
126 unset($current_grant);
129 $privs = array();
130 $allPrivileges = true;
131 foreach ($grants as $current_grant) {
132 if ((! empty($row) && isset($row[$current_grant[0]]))
133 || (empty($row) && isset($GLOBALS[$current_grant[0]]))
135 if ((! empty($row) && $row[$current_grant[0]] == 'Y')
136 || (empty($row)
137 && ($GLOBALS[$current_grant[0]] == 'Y'
138 || (is_array($GLOBALS[$current_grant[0]])
139 && count($GLOBALS[$current_grant[0]]) == $_REQUEST['column_count']
140 && empty($GLOBALS[$current_grant[0] . '_none']))))
142 if ($enableHTML) {
143 $privs[] = '<dfn title="' . $current_grant[2] . '">'
144 . $current_grant[1] . '</dfn>';
145 } else {
146 $privs[] = $current_grant[1];
148 } elseif (! empty($GLOBALS[$current_grant[0]])
149 && is_array($GLOBALS[$current_grant[0]])
150 && empty($GLOBALS[$current_grant[0] . '_none'])
152 if ($enableHTML) {
153 $priv_string = '<dfn title="' . $current_grant[2] . '">'
154 . $current_grant[1] . '</dfn>';
155 } else {
156 $priv_string = $current_grant[1];
158 $privs[] = $priv_string . ' (`'
159 . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
160 } else {
161 $allPrivileges = false;
165 if (empty($privs)) {
166 if ($enableHTML) {
167 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
168 } else {
169 $privs[] = 'USAGE';
171 } elseif ($allPrivileges
172 && (! isset($_POST['grant_count']) || count($privs) == $_POST['grant_count'])
174 if ($enableHTML) {
175 $privs = array('<dfn title="'
176 . __('Includes all privileges except GRANT.')
177 . '">ALL PRIVILEGES</dfn>'
179 } else {
180 $privs = array('ALL PRIVILEGES');
183 return $privs;
184 } // end of the 'PMA_extractPrivInfo()' function
187 * Returns an array of table grants and their descriptions
189 * @return array array of table grants
191 function PMA_getTableGrantsArray()
193 return array(
194 array(
195 'Delete',
196 'DELETE',
197 $GLOBALS['strPrivDescDelete']
199 array(
200 'Create',
201 'CREATE',
202 $GLOBALS['strPrivDescCreateTbl']
204 array(
205 'Drop',
206 'DROP',
207 $GLOBALS['strPrivDescDropTbl']
209 array(
210 'Index',
211 'INDEX',
212 $GLOBALS['strPrivDescIndex']
214 array(
215 'Alter',
216 'ALTER',
217 $GLOBALS['strPrivDescAlter']
219 array(
220 'Create View',
221 'CREATE_VIEW',
222 $GLOBALS['strPrivDescCreateView']
224 array(
225 'Show view',
226 'SHOW_VIEW',
227 $GLOBALS['strPrivDescShowView']
229 array(
230 'Trigger',
231 'TRIGGER',
232 $GLOBALS['strPrivDescTrigger']
238 * Get the grants array which contains all the privilege types
239 * and relevent grant messages
241 * @return array
243 function PMA_getGrantsArray()
245 return array(
246 array(
247 'Select_priv',
248 'SELECT',
249 __('Allows reading data.')
251 array(
252 'Insert_priv',
253 'INSERT',
254 __('Allows inserting and replacing data.')
256 array(
257 'Update_priv',
258 'UPDATE',
259 __('Allows changing data.')
261 array(
262 'Delete_priv',
263 'DELETE',
264 __('Allows deleting data.')
266 array(
267 'Create_priv',
268 'CREATE',
269 __('Allows creating new databases and tables.')
271 array(
272 'Drop_priv',
273 'DROP',
274 __('Allows dropping databases and tables.')
276 array(
277 'Reload_priv',
278 'RELOAD',
279 __('Allows reloading server settings and flushing the server\'s caches.')
281 array(
282 'Shutdown_priv',
283 'SHUTDOWN',
284 __('Allows shutting down the server.')
286 array(
287 'Process_priv',
288 'PROCESS',
289 __('Allows viewing processes of all users')
291 array(
292 'File_priv',
293 'FILE',
294 __('Allows importing data from and exporting data into files.')
296 array(
297 'References_priv',
298 'REFERENCES',
299 __('Has no effect in this MySQL version.')
301 array(
302 'Index_priv',
303 'INDEX',
304 __('Allows creating and dropping indexes.')
306 array(
307 'Alter_priv',
308 'ALTER',
309 __('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.')
316 array(
317 'Super_priv',
318 'SUPER',
320 'Allows connecting, even if maximum number of connections '
321 . 'is reached; required for most administrative operations '
322 . 'like setting global variables or killing threads of other users.'
325 array(
326 'Create_tmp_table_priv',
327 'CREATE TEMPORARY TABLES',
328 __('Allows creating temporary tables.')
330 array(
331 'Lock_tables_priv',
332 'LOCK TABLES',
333 __('Allows locking tables for the current thread.')
335 array(
336 'Repl_slave_priv',
337 'REPLICATION SLAVE',
338 __('Needed for the replication slaves.')
340 array(
341 'Repl_client_priv',
342 'REPLICATION CLIENT',
343 __('Allows the user to ask where the slaves / masters are.')
345 array(
346 'Create_view_priv',
347 'CREATE VIEW',
348 __('Allows creating new views.')
350 array(
351 'Event_priv',
352 'EVENT',
353 __('Allows to set up events for the event scheduler')
355 array(
356 'Trigger_priv',
357 'TRIGGER',
358 __('Allows creating and dropping triggers')
360 // for table privs:
361 array(
362 'Create View_priv',
363 'CREATE VIEW',
364 __('Allows creating new views.')
366 array(
367 'Show_view_priv',
368 'SHOW VIEW',
369 __('Allows performing SHOW CREATE VIEW queries.')
371 // for table privs:
372 array(
373 'Show view_priv',
374 'SHOW VIEW',
375 __('Allows performing SHOW CREATE VIEW queries.')
377 array(
378 'Create_routine_priv',
379 'CREATE ROUTINE',
380 __('Allows creating stored routines.')
382 array(
383 'Alter_routine_priv',
384 'ALTER ROUTINE',
385 __('Allows altering and dropping stored routines.')
387 array(
388 'Create_user_priv',
389 'CREATE USER',
390 __('Allows creating, dropping and renaming user accounts.')
392 array(
393 'Execute_priv',
394 'EXECUTE',
395 __('Allows executing stored routines.')
401 * Displays on which column(s) a table-specific privilege is granted
403 * @param array $columns columns array
404 * @param array $row first row from result or boolean false
405 * @param string $name_for_select privilege types - Select_priv, Insert_priv
406 * Update_priv, References_priv
407 * @param string $priv_for_header privilege for header
408 * @param string $name privilege name: insert, select, update, references
409 * @param string $name_for_dfn name for dfn
410 * @param string $name_for_current name for current
412 * @return $html_output html snippet
414 function PMA_getHtmlForDisplayColumnPrivileges($columns, $row, $name_for_select,
415 $priv_for_header, $name, $name_for_dfn, $name_for_current
417 $html_output = '<div class="item" id="div_item_' . $name . '">' . "\n"
418 . '<label for="select_' . $name . '_priv">' . "\n"
419 . '<code><dfn title="' . $name_for_dfn . '">'
420 . $priv_for_header . '</dfn></code>' . "\n"
421 . '</label><br />' . "\n"
422 . '<select id="select_' . $name . '_priv" name="'
423 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
425 foreach ($columns as $current_column => $current_column_privileges) {
426 $html_output .= '<option '
427 . 'value="' . htmlspecialchars($current_column) . '"';
428 if ($row[$name_for_select] == 'Y'
429 || $current_column_privileges[$name_for_current]
431 $html_output .= ' selected="selected"';
433 $html_output .= '>'
434 . htmlspecialchars($current_column) . '</option>' . "\n";
437 $html_output .= '</select>' . "\n"
438 . '<i>' . __('Or') . '</i>' . "\n"
439 . '<label for="checkbox_' . $name_for_select
440 . '_none"><input type="checkbox"'
441 . ' name="' . $name_for_select . '_none" id="checkbox_'
442 . $name_for_select . '_none" title="'
443 . _pgettext('None privileges', 'None') . '" />'
444 . _pgettext('None privileges', 'None') . '</label>' . "\n"
445 . '</div>' . "\n";
446 return $html_output;
447 } // end function
450 * Get sql query for display privileges table
452 * @param string $db the database
453 * @param string $table the table
454 * @param string $username username for database connection
455 * @param string $hostname hostname for database connection
457 * @return string sql query
459 function PMA_getSqlQueryForDisplayPrivTable($db, $table, $username, $hostname)
461 if ($db == '*') {
462 return "SELECT * FROM `mysql`.`user`"
463 ." WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
464 ." AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "';";
465 } elseif ($table == '*') {
466 return "SELECT * FROM `mysql`.`db`"
467 ." WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
468 ." AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "'"
469 ." AND '" . PMA_Util::unescapeMysqlWildcards($db) . "'"
470 ." LIKE `Db`;";
472 return "SELECT `Table_priv`"
473 ." FROM `mysql`.`tables_priv`"
474 ." WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
475 ." AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "'"
476 ." AND `Db` = '" . PMA_Util::unescapeMysqlWildcards($db) . "'"
477 ." AND `Table_name` = '" . PMA_Util::sqlAddSlashes($table) . "';";
481 * Displays a dropdown to select the user group
482 * with menu items configured to each of them.
484 * @param string $username username
486 * @return string html to select the user group
488 function PMA_getHtmlToChooseUserGroup($username)
490 $html_output = '<form class="ajax" id="changeUserGroupForm"'
491 . ' action="server_privileges.php" method="post">';
492 $params = array('username' => $username);
493 $html_output .= PMA_URL_getHiddenInputs($params);
494 $html_output .= '<fieldset id="fieldset_user_group_selection">';
495 $html_output .= '<legend>' . __('User group') . '</legend>';
497 $groupTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb'])
498 . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['usergroups']);
499 $userTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb'])
500 . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['users']);
502 $userGroups = array();
503 $sql_query = "SELECT DISTINCT `usergroup` FROM " . $groupTable;
504 $result = PMA_queryAsControlUser($sql_query, false);
505 if ($result) {
506 while ($row = $GLOBALS['dbi']->fetchRow($result)) {
507 $userGroups[] = $row[0];
510 $GLOBALS['dbi']->freeResult($result);
512 $userGroup = '';
513 if (isset($GLOBALS['username'])) {
514 $sql_query = "SELECT `usergroup` FROM " . $userTable
515 . " WHERE `username` = '" . PMA_Util::sqlAddSlashes($username) . "'";
516 $userGroup = $GLOBALS['dbi']->fetchValue(
517 $sql_query, 0, 0, $GLOBALS['controllink']
521 $html_output .= __('User group') . ': ';
522 $html_output .= '<select name="userGroup">';
523 $html_output .= '<option value=""></option>';
524 foreach ($userGroups as $oneUserGroup) {
525 $html_output .= '<option value="' . htmlspecialchars($oneUserGroup) . '"'
526 . ($oneUserGroup == $userGroup ? ' selected="selected"' : '')
527 . '>'
528 . htmlspecialchars($oneUserGroup)
529 . '</option>';
531 $html_output .= '</select>';
532 $html_output .= '<input type="hidden" name="changeUserGroup" value="1">';
533 $html_output .= '</fieldset>';
534 $html_output .= '</form>';
535 return $html_output;
539 * Sets the user group from request values
541 * @param string $username username
542 * @param string $userGroup user group to set
544 * @return void
546 function PMA_setUserGroup($username, $userGroup)
548 $userTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb'])
549 . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['users']);
551 $sql_query = "SELECT `usergroup` FROM " . $userTable
552 . " WHERE `username` = '" . PMA_Util::sqlAddSlashes($username) . "'";
553 $oldUserGroup = $GLOBALS['dbi']->fetchValue(
554 $sql_query, 0, 0, $GLOBALS['controllink']
557 if ($oldUserGroup === false) {
558 $upd_query = "INSERT INTO " . $userTable . "(`username`, `usergroup`)"
559 . " VALUES ('" . PMA_Util::sqlAddSlashes($username) . "', "
560 . "'" . PMA_Util::sqlAddSlashes($userGroup) . "')";
561 } else {
562 if (empty($userGroup)) {
563 $upd_query = "DELETE FROM " . $userTable
564 . " WHERE `username`='" . PMA_Util::sqlAddSlashes($username) . "'";
565 } elseif ($oldUserGroup != $userGroup) {
566 $upd_query = "UPDATE " . $userTable
567 . " SET `usergroup`='" . PMA_Util::sqlAddSlashes($userGroup) . "'"
568 . " WHERE `username`='" . PMA_Util::sqlAddSlashes($username) . "'";
571 if (isset($upd_query)) {
572 PMA_queryAsControlUser($upd_query);
577 * Displays the privileges form table
579 * @param string $db the database
580 * @param string $table the table
581 * @param boolean $submit wheather to display the submit button or not
583 * @global array $cfg the phpMyAdmin configuration
584 * @global ressource $user_link the database connection
586 * @return string html snippet
588 function PMA_getHtmlToDisplayPrivilegesTable($db = '*',
589 $table = '*', $submit = true
591 $html_output = '';
593 if ($db == '*') {
594 $table = '*';
597 if (isset($GLOBALS['username'])) {
598 $username = $GLOBALS['username'];
599 $hostname = $GLOBALS['hostname'];
600 $sql_query = PMA_getSqlQueryForDisplayPrivTable(
601 $db, $table, $username, $hostname
603 $row = $GLOBALS['dbi']->fetchSingleRow($sql_query);
605 if (empty($row)) {
606 if ($table == '*') {
607 if ($db == '*') {
608 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
609 } elseif ($table == '*') {
610 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
612 $res = $GLOBALS['dbi']->query($sql_query);
613 while ($row1 = $GLOBALS['dbi']->fetchRow($res)) {
614 if (substr($row1[0], 0, 4) == 'max_') {
615 $row[$row1[0]] = 0;
616 } else {
617 $row[$row1[0]] = 'N';
620 $GLOBALS['dbi']->freeResult($res);
621 } else {
622 $row = array('Table_priv' => '');
625 if (isset($row['Table_priv'])) {
626 $row1 = $GLOBALS['dbi']->fetchSingleRow(
627 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
628 'ASSOC', $GLOBALS['userlink']
630 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
631 // the View for Create is spelled with uppercase V
632 // the view for Show is spelled with lowercase v
633 // and there is a space between the words
635 $av_grants = explode(
636 '\',\'',
637 substr(
638 $row1['Type'],
639 strpos($row1['Type'], '(') + 2,
640 strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3
643 unset($row1);
644 $users_grants = explode(',', $row['Table_priv']);
646 foreach ($av_grants as $current_grant) {
647 $row[$current_grant . '_priv']
648 = in_array($current_grant, $users_grants) ? 'Y' : 'N';
650 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
652 // get columns
653 $res = $GLOBALS['dbi']->tryQuery(
654 'SHOW COLUMNS FROM '
655 . PMA_Util::backquote(
656 PMA_Util::unescapeMysqlWildcards($db)
658 . '.' . PMA_Util::backquote($table) . ';'
660 $columns = array();
661 if ($res) {
662 while ($row1 = $GLOBALS['dbi']->fetchRow($res)) {
663 $columns[$row1[0]] = array(
664 'Select' => false,
665 'Insert' => false,
666 'Update' => false,
667 'References' => false
670 $GLOBALS['dbi']->freeResult($res);
672 unset($res, $row1);
674 // table-specific privileges
675 if (! empty($columns)) {
676 $html_output .= PMA_getHtmlForTableSpecificPrivileges(
677 $username, $hostname, $db, $table, $columns, $row
679 } else {
680 // global or db-specific
681 $html_output .= PMA_getHtmlForGlobalOrDbSpecificPrivs($db, $table, $row);
683 $html_output .= '</fieldset>' . "\n";
684 if ($submit) {
685 $html_output .= '<fieldset id="fieldset_user_privtable_footer" '
686 . 'class="tblFooters">' . "\n"
687 . '<input type="submit" name="update_privs" '
688 . 'value="' . __('Go') . '" />' . "\n"
689 . '</fieldset>' . "\n";
691 return $html_output;
692 } // end of the 'PMA_displayPrivTable()' function
695 * Get HTML for "Resource limits"
697 * @param array $row first row from result or boolean false
699 * @return string html snippet
701 function PMA_getHtmlForDisplayResourceLimits($row)
703 $html_output = '<fieldset>' . "\n"
704 . '<legend>' . __('Resource limits') . '</legend>' . "\n"
705 . '<p><small>'
706 . '<i>' . __('Note: Setting these options to 0 (zero) removes the limit.')
707 . '</i></small></p>' . "\n";
709 $html_output .= '<div class="item">' . "\n"
710 . '<label for="text_max_questions">'
711 . '<code><dfn title="'
712 . __(
713 'Limits the number of queries the user may send to the server per hour.'
715 . '">'
716 . 'MAX QUERIES PER HOUR'
717 . '</dfn></code></label>' . "\n"
718 . '<input type="number" name="max_questions" id="text_max_questions" '
719 . 'value="' . $row['max_questions'] . '" '
720 . 'size="6" maxlength="11" min="0" '
721 . 'title="'
722 . __(
723 'Limits the number of queries the user may send to the server per hour.'
725 . '" />' . "\n"
726 . '</div>' . "\n";
728 $html_output .= '<div class="item">' . "\n"
729 . '<label for="text_max_updates">'
730 . '<code><dfn title="'
731 . __(
732 'Limits the number of commands that change any table '
733 . 'or database the user may execute per hour.'
734 ) . '">'
735 . 'MAX UPDATES PER HOUR'
736 . '</dfn></code></label>' . "\n"
737 . '<input type="number" name="max_updates" id="text_max_updates" '
738 . 'value="' . $row['max_updates'] . '" size="6" maxlength="11" min="0" '
739 . 'title="'
740 . __(
741 'Limits the number of commands that change any table '
742 . 'or database the user may execute per hour.'
744 . '" />' . "\n"
745 . '</div>' . "\n";
747 $html_output .= '<div class="item">' . "\n"
748 . '<label for="text_max_connections">'
749 . '<code><dfn title="'
750 . __(
751 'Limits the number of new connections the user may open per hour.'
752 ) . '">'
753 . 'MAX CONNECTIONS PER HOUR'
754 . '</dfn></code></label>' . "\n"
755 . '<input type="number" name="max_connections" id="text_max_connections" '
756 . 'value="' . $row['max_connections'] . '" size="6" maxlength="11" min="0" '
757 . 'title="' . __(
758 'Limits the number of new connections the user may open per hour.'
760 . '" />' . "\n"
761 . '</div>' . "\n";
763 $html_output .= '<div class="item">' . "\n"
764 . '<label for="text_max_user_connections">'
765 . '<code><dfn title="'
766 . __('Limits the number of simultaneous connections the user may have.')
767 . '">'
768 . 'MAX USER_CONNECTIONS'
769 . '</dfn></code></label>' . "\n"
770 . '<input type="number" name="max_user_connections" '
771 . 'id="text_max_user_connections" '
772 . 'value="' . $row['max_user_connections'] . '" size="6" maxlength="11" '
773 . 'title="'
774 . __('Limits the number of simultaneous connections the user may have.')
775 . '" />' . "\n"
776 . '</div>' . "\n";
778 $html_output .= '</fieldset>' . "\n";
780 return $html_output;
784 * Get the HTML snippet for table specific privileges
786 * @param string $username username for database connection
787 * @param string $hostname hostname for database connection
788 * @param string $db the database
789 * @param string $table the table
790 * @param boolean $columns columns array
791 * @param array $row current privileges row
793 * @return string $html_output
795 function PMA_getHtmlForTableSpecificPrivileges(
796 $username, $hostname, $db, $table, $columns, $row
798 $res = $GLOBALS['dbi']->query(
799 'SELECT `Column_name`, `Column_priv`'
800 .' FROM `mysql`.`columns_priv`'
801 .' WHERE `User`'
802 .' = \'' . PMA_Util::sqlAddSlashes($username) . "'"
803 .' AND `Host`'
804 .' = \'' . PMA_Util::sqlAddSlashes($hostname) . "'"
805 .' AND `Db`'
806 .' = \'' . PMA_Util::sqlAddSlashes(
807 PMA_Util::unescapeMysqlWildcards($db)
808 ) . "'"
809 .' AND `Table_name`'
810 .' = \'' . PMA_Util::sqlAddSlashes($table) . '\';'
813 while ($row1 = $GLOBALS['dbi']->fetchRow($res)) {
814 $row1[1] = explode(',', $row1[1]);
815 foreach ($row1[1] as $current) {
816 $columns[$row1[0]][$current] = true;
819 $GLOBALS['dbi']->freeResult($res);
820 unset($res, $row1, $current);
822 $html_output = '<input type="hidden" name="grant_count" '
823 . 'value="' . count($row) . '" />' . "\n"
824 . '<input type="hidden" name="column_count" '
825 . 'value="' . count($columns) . '" />' . "\n"
826 . '<fieldset id="fieldset_user_priv">' . "\n"
827 . '<legend>' . __('Table-specific privileges')
828 . PMA_Util::showHint(
829 __('Note: MySQL privilege names are expressed in English')
831 . '</legend>' . "\n";
833 // privs that are attached to a specific column
834 $html_output .= PMA_getHtmlForAttachedPrivilegesToTableSpecificColumn(
835 $columns, $row
838 // privs that are not attached to a specific column
839 $html_output .= '<div class="item">' . "\n"
840 . PMA_getHtmlForNotAttachedPrivilegesToTableSpecificColumn($row)
841 . '</div>' . "\n";
843 // for Safari 2.0.2
844 $html_output .= '<div class="clearfloat"></div>' . "\n";
846 return $html_output;
850 * Get HTML snippet for privileges that are attached to a specific column
852 * @param string $columns olumns array
853 * @param array $row first row from result or boolean false
855 * @return string $html_output
857 function PMA_getHtmlForAttachedPrivilegesToTableSpecificColumn($columns, $row)
859 $html_output = PMA_getHtmlForDisplayColumnPrivileges(
860 $columns, $row, 'Select_priv', 'SELECT',
861 'select', __('Allows reading data.'), 'Select'
864 $html_output .= PMA_getHtmlForDisplayColumnPrivileges(
865 $columns, $row, 'Insert_priv', 'INSERT',
866 'insert', __('Allows inserting and replacing data.'), 'Insert'
869 $html_output .= PMA_getHtmlForDisplayColumnPrivileges(
870 $columns, $row, 'Update_priv', 'UPDATE',
871 'update', __('Allows changing data.'), 'Update'
874 $html_output .= PMA_getHtmlForDisplayColumnPrivileges(
875 $columns, $row, 'References_priv', 'REFERENCES', 'references',
876 __('Has no effect in this MySQL version.'), 'References'
878 return $html_output;
882 * Get HTML for privileges that are not attached to a specific column
884 * @param array $row first row from result or boolean false
886 * @return string $html_output
888 function PMA_getHtmlForNotAttachedPrivilegesToTableSpecificColumn($row)
890 $html_output = '';
891 foreach ($row as $current_grant => $current_grant_value) {
892 $grant_type = substr($current_grant, 0, (strlen($current_grant) - 5));
893 if (in_array($grant_type, array('Select', 'Insert', 'Update', 'References'))
895 continue;
897 // make a substitution to match the messages variables;
898 // also we must substitute the grant we get, because we can't generate
899 // a form variable containing blanks (those would get changed to
900 // an underscore when receiving the POST)
901 if ($current_grant == 'Create View_priv') {
902 $tmp_current_grant = 'CreateView_priv';
903 $current_grant = 'Create_view_priv';
904 } elseif ($current_grant == 'Show view_priv') {
905 $tmp_current_grant = 'ShowView_priv';
906 $current_grant = 'Show_view_priv';
907 } else {
908 $tmp_current_grant = $current_grant;
911 $html_output .= '<div class="item">' . "\n"
912 . '<input type="checkbox"'
913 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
914 . '" value="Y" '
915 . ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
916 . 'title="';
918 $html_output .= (isset($GLOBALS[
919 'strPrivDesc' . substr(
920 $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
923 ? $GLOBALS[
924 'strPrivDesc' . substr(
925 $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
928 : $GLOBALS[
929 'strPrivDesc' . substr(
930 $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
931 ) . 'Tbl'
934 . '"/>' . "\n";
936 $html_output .= '<label for="checkbox_' . $current_grant
937 . '"><code><dfn title="'
938 . (isset($GLOBALS[
939 'strPrivDesc' . substr(
940 $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
943 ? $GLOBALS[
944 'strPrivDesc' . substr(
945 $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
948 : $GLOBALS[
949 'strPrivDesc' . substr(
950 $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
951 ) . 'Tbl'
954 . '">'
955 . strtoupper(
956 substr($current_grant, 0, strlen($current_grant) - 5)
958 . '</dfn></code></label>' . "\n"
959 . '</div>' . "\n";
960 } // end foreach ()
961 return $html_output;
965 * Get HTML for global or database specific privileges
967 * @param string $db the database
968 * @param string $table the table
969 * @param string $row first row from result or boolean false
971 * @return string $html_output
973 function PMA_getHtmlForGlobalOrDbSpecificPrivs($db, $table, $row)
975 $privTable_names = array(0 => __('Data'),
976 1 => __('Structure'),
977 2 => __('Administration')
979 $privTable = array();
980 // d a t a
981 $privTable[0] = PMA_getDataPrivilegeTable($db);
983 // s t r u c t u r e
984 $privTable[1] = PMA_getStructurePrivilegeTable($table, $row);
986 // a d m i n i s t r a t i o n
987 $privTable[2] = PMA_getAdministrationPrivilegeTable($db);
989 $html_output = '<input type="hidden" name="grant_count" value="'
990 . (count($privTable[0])
991 + count($privTable[1])
992 + count($privTable[2])
993 - (isset($row['Grant_priv']) ? 1 : 0)
995 . '" />';
996 $html_output .= '<fieldset id="fieldset_user_global_rights"><legend>';
997 if ($db == '*') {
998 $html_output .= __('Global privileges');
999 } else if ($table == '*') {
1000 $html_output .= __('Database-specific privileges');
1001 } else {
1002 $html_output .= __('Table-specific privileges');
1004 $html_output .= '<input type="checkbox" id="addUsersForm_checkall" '
1005 . 'class="checkall_box" title="' . __('Check All') . '" /> '
1006 . '<label for="addUsersForm_checkall">' . __('Check All') . '</label> ';
1007 $html_output .= '</legend>';
1008 $html_output .= '<p><small><i>'
1009 . __('Note: MySQL privilege names are expressed in English')
1010 . '</i></small></p>';
1012 // Output the Global privilege tables with checkboxes
1013 $html_output .= PMA_getHtmlForGlobalPrivTableWithCheckboxes(
1014 $privTable, $privTable_names, $row
1017 // The "Resource limits" box is not displayed for db-specific privs
1018 if ($db == '*') {
1019 $html_output .= PMA_getHtmlForDisplayResourceLimits($row);
1021 // for Safari 2.0.2
1022 $html_output .= '<div class="clearfloat"></div>';
1024 return $html_output;
1028 * Get data privilege table as an array
1030 * @param string $db the database
1032 * @return string data privilege table
1034 function PMA_getDataPrivilegeTable($db)
1036 $data_privTable = array(
1037 array('Select', 'SELECT', __('Allows reading data.')),
1038 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
1039 array('Update', 'UPDATE', __('Allows changing data.')),
1040 array('Delete', 'DELETE', __('Allows deleting data.'))
1042 if ($db == '*') {
1043 $data_privTable[]
1044 = array('File',
1045 'FILE',
1046 __('Allows importing data from and exporting data into files.')
1049 return $data_privTable;
1053 * Get structure privilege table as an array
1055 * @param string $table the table
1056 * @param array $row first row from result or boolean false
1058 * @return string structure privilege table
1060 function PMA_getStructurePrivilegeTable($table, $row)
1062 $structure_privTable = array(
1063 array('Create',
1064 'CREATE',
1065 ($table == '*'
1066 ? __('Allows creating new databases and tables.')
1067 : __('Allows creating new tables.')
1070 array('Alter',
1071 'ALTER',
1072 __('Allows altering the structure of existing tables.')
1074 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
1075 array('Drop',
1076 'DROP',
1077 ($table == '*'
1078 ? __('Allows dropping databases and tables.')
1079 : __('Allows dropping tables.')
1082 array('Create_tmp_table',
1083 'CREATE TEMPORARY TABLES',
1084 __('Allows creating temporary tables.')
1086 array('Show_view',
1087 'SHOW VIEW',
1088 __('Allows performing SHOW CREATE VIEW queries.')
1090 array('Create_routine',
1091 'CREATE ROUTINE',
1092 __('Allows creating stored routines.')
1094 array('Alter_routine',
1095 'ALTER ROUTINE',
1096 __('Allows altering and dropping stored routines.')
1098 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
1100 // this one is for a db-specific priv: Create_view_priv
1101 if (isset($row['Create_view_priv'])) {
1102 $structure_privTable[] = array('Create_view',
1103 'CREATE VIEW',
1104 __('Allows creating new views.')
1107 // this one is for a table-specific priv: Create View_priv
1108 if (isset($row['Create View_priv'])) {
1109 $structure_privTable[] = array('Create View',
1110 'CREATE VIEW',
1111 __('Allows creating new views.')
1114 if (isset($row['Event_priv'])) {
1115 // MySQL 5.1.6
1116 $structure_privTable[] = array('Event',
1117 'EVENT',
1118 __('Allows to set up events for the event scheduler')
1120 $structure_privTable[] = array('Trigger',
1121 'TRIGGER',
1122 __('Allows creating and dropping triggers')
1125 return $structure_privTable;
1129 * Get administration privilege table as an array
1131 * @param string $db the table
1133 * @return string administration privilege table
1135 function PMA_getAdministrationPrivilegeTable($db)
1137 $administration_privTable = array(
1138 array('Grant',
1139 'GRANT',
1141 'Allows adding users and privileges '
1142 . 'without reloading the privilege tables.'
1146 if ($db == '*') {
1147 $administration_privTable[] = array('Super',
1148 'SUPER',
1150 'Allows connecting, even if maximum number '
1151 . 'of connections is reached; required for '
1152 . 'most administrative operations like '
1153 . 'setting global variables or killing threads of other users.'
1156 $administration_privTable[] = array('Process',
1157 'PROCESS',
1158 __('Allows viewing processes of all users')
1160 $administration_privTable[] = array('Reload',
1161 'RELOAD',
1162 __('Allows reloading server settings and flushing the server\'s caches.')
1164 $administration_privTable[] = array('Shutdown',
1165 'SHUTDOWN',
1166 __('Allows shutting down the server.')
1168 $administration_privTable[] = array('Show_db',
1169 'SHOW DATABASES',
1170 __('Gives access to the complete list of databases.')
1173 $administration_privTable[] = array('Lock_tables',
1174 'LOCK TABLES',
1175 __('Allows locking tables for the current thread.')
1177 $administration_privTable[] = array('References',
1178 'REFERENCES',
1179 __('Has no effect in this MySQL version.')
1181 if ($db == '*') {
1182 $administration_privTable[] = array('Repl_client',
1183 'REPLICATION CLIENT',
1184 __('Allows the user to ask where the slaves / masters are.')
1186 $administration_privTable[] = array('Repl_slave',
1187 'REPLICATION SLAVE',
1188 __('Needed for the replication slaves.')
1190 $administration_privTable[] = array('Create_user',
1191 'CREATE USER',
1192 __('Allows creating, dropping and renaming user accounts.')
1195 return $administration_privTable;
1199 * Get HTML snippet for global privileges table with check boxes
1201 * @param array $privTable privileges table array
1202 * @param array $privTable_names names of the privilege tables
1203 * (Data, Structure, Administration)
1204 * @param array $row first row from result or boolean false
1206 * @return string $html_output
1208 function PMA_getHtmlForGlobalPrivTableWithCheckboxes(
1209 $privTable, $privTable_names, $row
1211 $html_output = '';
1212 foreach ($privTable as $i => $table) {
1213 $html_output .= '<fieldset>' . "\n"
1214 . '<legend>' . $privTable_names[$i] . '</legend>' . "\n";
1215 foreach ($table as $priv) {
1216 $html_output .= '<div class="item">' . "\n"
1217 . '<input type="checkbox" class="checkall"'
1218 . ' name="' . $priv[0] . '_priv" '
1219 . 'id="checkbox_' . $priv[0] . '_priv"'
1220 . ' value="Y" title="' . $priv[2] . '"'
1221 . (($row[$priv[0] . '_priv'] == 'Y')
1222 ? ' checked="checked"'
1223 : ''
1225 . '/>' . "\n"
1226 . '<label for="checkbox_' . $priv[0] . '_priv">'
1227 . '<code><dfn title="' . $priv[2] . '">'
1228 . $priv[1] . '</dfn></code></label>' . "\n"
1229 . '</div>' . "\n";
1231 $html_output .= '</fieldset>' . "\n";
1233 return $html_output;
1237 * Displays the fields used by the "new user" form as well as the
1238 * "change login information / copy user" form.
1240 * @param string $mode are we creating a new user or are we just
1241 * changing one? (allowed values: 'new', 'change')
1243 * @global array $cfg the phpMyAdmin configuration
1244 * @global ressource $user_link the database connection
1246 * @return string $html_output a HTML snippet
1248 function PMA_getHtmlForDisplayLoginInformationFields($mode = 'new')
1250 list($username_length, $hostname_length) = PMA_getUsernameAndHostnameLength();
1252 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
1253 $GLOBALS['pred_username'] = 'any';
1255 $html_output = '<fieldset id="fieldset_add_user_login">' . "\n"
1256 . '<legend>' . __('Login Information') . '</legend>' . "\n"
1257 . '<div class="item">' . "\n"
1258 . '<label for="select_pred_username">' . "\n"
1259 . ' ' . __('User name:') . "\n"
1260 . '</label>' . "\n"
1261 . '<span class="options">' . "\n";
1263 $html_output .= '<select name="pred_username" id="select_pred_username" '
1264 . 'title="' . __('User name') . '"' . "\n";
1267 $html_output .= ' onchange="'
1268 . 'if (this.value == \'any\') {'
1269 . ' username.value = \'\'; '
1270 . ' user_exists_warning.style.display = \'none\'; '
1271 . '} else if (this.value == \'userdefined\') {'
1272 . ' username.focus(); username.select(); '
1273 . '}">' . "\n";
1275 $html_output .= '<option value="any"'
1276 . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any')
1277 ? ' selected="selected"'
1278 : '') . '>'
1279 . __('Any user')
1280 . '</option>' . "\n";
1282 $html_output .= '<option value="userdefined"'
1283 . ((! isset($GLOBALS['pred_username'])
1284 || $GLOBALS['pred_username'] == 'userdefined'
1286 ? ' selected="selected"'
1287 : '') . '>'
1288 . __('Use text field')
1289 . ':</option>' . "\n";
1291 $html_output .= '</select>' . "\n"
1292 . '</span>' . "\n";
1294 $html_output .= '<input type="text" name="username" class="autofocus"'
1295 . ' maxlength="' . $username_length . '" title="' . __('User name') . '"'
1296 . (empty($GLOBALS['username'])
1297 ? ''
1298 : ' value="' . htmlspecialchars(
1299 isset($GLOBALS['new_username'])
1300 ? $GLOBALS['new_username']
1301 : $GLOBALS['username']
1302 ) . '"'
1304 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n";
1306 $html_output .= '<div id="user_exists_warning"'
1307 . ' name="user_exists_warning" style="display:none;">'
1308 . PMA_Message::notice(
1310 'An account already exists with the same username '
1311 . 'but possibly a different hostname. '
1312 . 'Are you sure you wish to proceed?'
1314 )->getDisplay()
1315 . '</div>';
1316 $html_output .= '</div>';
1318 $html_output .= '<div class="item">' . "\n"
1319 . '<label for="select_pred_hostname">' . "\n"
1320 . ' ' . __('Host:') . "\n"
1321 . '</label>' . "\n";
1323 $html_output .= '<span class="options">' . "\n"
1324 . ' <select name="pred_hostname" id="select_pred_hostname" '
1325 . 'title="' . __('Host') . '"' . "\n";
1326 $_current_user = $GLOBALS['dbi']->fetchValue('SELECT USER();');
1327 if (! empty($_current_user)) {
1328 $thishost = str_replace(
1329 "'",
1331 substr($_current_user, (strrpos($_current_user, '@') + 1))
1333 if ($thishost == 'localhost' || $thishost == '127.0.0.1') {
1334 unset($thishost);
1337 $html_output .= ' onchange="'
1338 . 'if (this.value == \'any\') { '
1339 . ' hostname.value = \'%\'; '
1340 . '} else if (this.value == \'localhost\') { '
1341 . ' hostname.value = \'localhost\'; '
1342 . '} '
1343 . (empty($thishost)
1344 ? ''
1345 : 'else if (this.value == \'thishost\') { '
1346 . ' hostname.value = \'' . addslashes(htmlspecialchars($thishost))
1347 . '\'; '
1348 . '} '
1350 . 'else if (this.value == \'hosttable\') { '
1351 . ' hostname.value = \'\'; '
1352 . '} else if (this.value == \'userdefined\') {'
1353 . ' hostname.focus(); hostname.select(); '
1354 . '}">' . "\n";
1355 unset($_current_user);
1357 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
1358 if (! isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
1359 switch (strtolower($GLOBALS['hostname'])) {
1360 case 'localhost':
1361 case '127.0.0.1':
1362 $GLOBALS['pred_hostname'] = 'localhost';
1363 break;
1364 case '%':
1365 $GLOBALS['pred_hostname'] = 'any';
1366 break;
1367 default:
1368 $GLOBALS['pred_hostname'] = 'userdefined';
1369 break;
1372 $html_output .= '<option value="any"'
1373 . ((isset($GLOBALS['pred_hostname'])
1374 && $GLOBALS['pred_hostname'] == 'any'
1376 ? ' selected="selected"'
1377 : '') . '>'
1378 . __('Any host')
1379 . '</option>' . "\n"
1380 . '<option value="localhost"'
1381 . ((isset($GLOBALS['pred_hostname'])
1382 && $GLOBALS['pred_hostname'] == 'localhost'
1384 ? ' selected="selected"'
1385 : '') . '>'
1386 . __('Local')
1387 . '</option>' . "\n";
1388 if (! empty($thishost)) {
1389 $html_output .= '<option value="thishost"'
1390 . ((isset($GLOBALS['pred_hostname'])
1391 && $GLOBALS['pred_hostname'] == 'thishost'
1393 ? ' selected="selected"'
1394 : '') . '>'
1395 . __('This Host')
1396 . '</option>' . "\n";
1398 unset($thishost);
1399 $html_output .= '<option value="hosttable"'
1400 . ((isset($GLOBALS['pred_hostname'])
1401 && $GLOBALS['pred_hostname'] == 'hosttable'
1403 ? ' selected="selected"'
1404 : '') . '>'
1405 . __('Use Host Table')
1406 . '</option>' . "\n";
1408 $html_output .= '<option value="userdefined"'
1409 . ((isset($GLOBALS['pred_hostname'])
1410 && $GLOBALS['pred_hostname'] == 'userdefined'
1412 ? ' selected="selected"'
1413 : '') . '>'
1414 . __('Use text field:') . '</option>' . "\n"
1415 . '</select>' . "\n"
1416 . '</span>' . "\n";
1418 $html_output .= '<input type="text" name="hostname" maxlength="'
1419 . $hostname_length . '" value="'
1420 . htmlspecialchars(isset($GLOBALS['hostname']) ? $GLOBALS['hostname'] : '')
1421 . '" title="' . __('Host')
1422 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
1423 . PMA_Util::showHint(
1425 'When Host table is used, this field is ignored '
1426 . 'and values stored in Host table are used instead.'
1429 . '</div>' . "\n";
1431 $html_output .= '<div class="item">' . "\n"
1432 . '<label for="select_pred_password">' . "\n"
1433 . ' ' . __('Password:') . "\n"
1434 . '</label>' . "\n"
1435 . '<span class="options">' . "\n"
1436 . '<select name="pred_password" id="select_pred_password" title="'
1437 . __('Password') . '"' . "\n";
1439 $html_output .= ' onchange="'
1440 . 'if (this.value == \'none\') { '
1441 . ' pma_pw.value = \'\'; pma_pw2.value = \'\'; '
1442 . '} else if (this.value == \'userdefined\') { '
1443 . ' pma_pw.focus(); pma_pw.select(); '
1444 . '}">' . "\n"
1445 . ($mode == 'change' ? '<option value="keep" selected="selected">'
1446 . __('Do not change the password')
1447 . '</option>' . "\n" : '')
1448 . '<option value="none"';
1450 if (isset($GLOBALS['username']) && $mode != 'change') {
1451 $html_output .= ' selected="selected"';
1453 $html_output .= '>' . __('No Password') . '</option>' . "\n"
1454 . '<option value="userdefined"'
1455 . (isset($GLOBALS['username']) ? '' : ' selected="selected"') . '>'
1456 . __('Use text field')
1457 . ':</option>' . "\n"
1458 . '</select>' . "\n"
1459 . '</span>' . "\n"
1460 . '<input type="password" id="text_pma_pw" name="pma_pw" '
1461 . 'title="' . __('Password') . '" '
1462 . 'onchange="pred_password.value = \'userdefined\';" />' . "\n"
1463 . '</div>' . "\n";
1465 $html_output .= '<div class="item" '
1466 . 'id="div_element_before_generate_password">' . "\n"
1467 . '<label for="text_pma_pw2">' . "\n"
1468 . ' ' . __('Re-type:') . "\n"
1469 . '</label>' . "\n"
1470 . '<span class="options">&nbsp;</span>' . "\n"
1471 . '<input type="password" name="pma_pw2" id="text_pma_pw2" '
1472 . 'title="' . __('Re-type') . '" '
1473 . 'onchange="pred_password.value = \'userdefined\';" />' . "\n"
1474 . '</div>' . "\n"
1475 // Generate password added here via jQuery
1476 . '</fieldset>' . "\n";
1478 return $html_output;
1479 } // end of the 'PMA_displayUserAndHostFields()' function
1482 * Get username and hostname length
1484 * @return array username length and hostname length
1486 function PMA_getUsernameAndHostnameLength()
1488 $fields_info = $GLOBALS['dbi']->getColumns('mysql', 'user', null, true);
1489 $username_length = 16;
1490 $hostname_length = 41;
1491 foreach ($fields_info as $val) {
1492 if ($val['Field'] == 'User') {
1493 strtok($val['Type'], '()');
1494 $value = strtok('()');
1495 if (is_int($value)) {
1496 $username_length = $value;
1498 } elseif ($val['Field'] == 'Host') {
1499 strtok($val['Type'], '()');
1500 $value = strtok('()');
1501 if (is_int($value)) {
1502 $hostname_length = $value;
1506 return array($username_length, $hostname_length);
1510 * Returns all the grants for a certain user on a certain host
1511 * Used in the export privileges for all users section
1513 * @param string $user User name
1514 * @param string $host Host name
1516 * @return string containing all the grants text
1518 function PMA_getGrants($user, $host)
1520 $grants = $GLOBALS['dbi']->fetchResult(
1521 "SHOW GRANTS FOR '"
1522 . PMA_Util::sqlAddSlashes($user) . "'@'"
1523 . PMA_Util::sqlAddSlashes($host) . "'"
1525 $response = '';
1526 foreach ($grants as $one_grant) {
1527 $response .= $one_grant . ";\n\n";
1529 return $response;
1530 } // end of the 'PMA_getGrants()' function
1533 * Update password and get message for password updating
1535 * @param string $err_url error url
1536 * @param string $username username
1537 * @param string $hostname hostname
1539 * @return string $message success or error message after updating password
1541 function PMA_updatePassword($err_url, $username, $hostname)
1543 // similar logic in user_password.php
1544 $message = '';
1546 if (empty($_REQUEST['nopass'])
1547 && isset($_POST['pma_pw'])
1548 && isset($_POST['pma_pw2'])
1550 if ($_POST['pma_pw'] != $_POST['pma_pw2']) {
1551 $message = PMA_Message::error(__('The passwords aren\'t the same!'));
1552 } elseif (empty($_POST['pma_pw']) || empty($_POST['pma_pw2'])) {
1553 $message = PMA_Message::error(__('The password is empty!'));
1557 // here $nopass could be == 1
1558 if (empty($message)) {
1560 $hashing_function
1561 = (! empty($_REQUEST['pw_hash']) && $_REQUEST['pw_hash'] == 'old'
1562 ? 'OLD_'
1563 : ''
1565 . 'PASSWORD';
1567 // in $sql_query which will be displayed, hide the password
1568 $sql_query = 'SET PASSWORD FOR \''
1569 . PMA_Util::sqlAddSlashes($username)
1570 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\' = '
1571 . (($_POST['pma_pw'] == '')
1572 ? '\'\''
1573 : $hashing_function . '(\''
1574 . preg_replace('@.@s', '*', $_POST['pma_pw']) . '\')');
1576 $local_query = 'SET PASSWORD FOR \''
1577 . PMA_Util::sqlAddSlashes($username)
1578 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\' = '
1579 . (($_POST['pma_pw'] == '') ? '\'\'' : $hashing_function
1580 . '(\'' . PMA_Util::sqlAddSlashes($_POST['pma_pw']) . '\')');
1582 $GLOBALS['dbi']->tryQuery($local_query)
1583 or PMA_Util::mysqlDie(
1584 $GLOBALS['dbi']->getError(), $sql_query, false, $err_url
1586 $message = PMA_Message::success(
1587 __('The password for %s was changed successfully.')
1589 $message->addParam(
1590 '\'' . htmlspecialchars($username)
1591 . '\'@\'' . htmlspecialchars($hostname) . '\''
1594 return $message;
1598 * Revokes privileges and get message and SQL query for privileges revokes
1600 * @param string $db_and_table wildcard Escaped database+table specification
1601 * @param string $dbname database name
1602 * @param string $tablename table name
1603 * @param string $username username
1604 * @param string $hostname host name
1606 * @return array ($message, $sql_query)
1608 function PMA_getMessageAndSqlQueryForPrivilegesRevoke($db_and_table, $dbname,
1609 $tablename, $username, $hostname
1611 $db_and_table = PMA_wildcardEscapeForGrant($dbname, $tablename);
1613 $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1614 . ' FROM \''
1615 . PMA_Util::sqlAddSlashes($username) . '\'@\''
1616 . PMA_Util::sqlAddSlashes($hostname) . '\';';
1618 $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
1619 . ' FROM \'' . PMA_Util::sqlAddSlashes($username) . '\'@\''
1620 . PMA_Util::sqlAddSlashes($hostname) . '\';';
1622 $GLOBALS['dbi']->query($sql_query0);
1623 if (! $GLOBALS['dbi']->tryQuery($sql_query1)) {
1624 // this one may fail, too...
1625 $sql_query1 = '';
1627 $sql_query = $sql_query0 . ' ' . $sql_query1;
1628 $message = PMA_Message::success(
1629 __('You have revoked the privileges for %s.')
1631 $message->addParam(
1632 '\'' . htmlspecialchars($username)
1633 . '\'@\'' . htmlspecialchars($hostname) . '\''
1636 return array($message, $sql_query);
1640 * Get a WITH clause for 'update privileges' and 'add user'
1642 * @return string $sql_query
1644 function PMA_getWithClauseForAddUserAndUpdatePrivs()
1646 $sql_query = '';
1647 if (isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y') {
1648 $sql_query .= ' GRANT OPTION';
1650 if (isset($_POST['max_questions'])) {
1651 $max_questions = max(0, (int)$_POST['max_questions']);
1652 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1654 if (isset($_POST['max_connections'])) {
1655 $max_connections = max(0, (int)$_POST['max_connections']);
1656 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1658 if (isset($_POST['max_updates'])) {
1659 $max_updates = max(0, (int)$_POST['max_updates']);
1660 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1662 if (isset($_POST['max_user_connections'])) {
1663 $max_user_connections = max(0, (int)$_POST['max_user_connections']);
1664 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1666 return ((!empty($sql_query)) ? 'WITH' . $sql_query : '');
1670 * Get HTML for addUsersForm, This function call if isset($_REQUEST['adduser'])
1672 * @param string $dbname database name
1674 * @return string HTML for addUserForm
1676 function PMA_getHtmlForAddUser($dbname)
1678 $html_output = '<h2>' . "\n"
1679 . PMA_Util::getIcon('b_usradd.png') . __('Add user') . "\n"
1680 . '</h2>' . "\n"
1681 . '<form name="usersForm" class="ajax" id="addUsersForm"'
1682 . ' action="server_privileges.php" method="post" autocomplete="off" >' . "\n"
1683 . PMA_URL_getHiddenInputs('', '')
1684 . PMA_getHtmlForDisplayLoginInformationFields('new');
1686 $html_output .= '<fieldset id="fieldset_add_user_database">' . "\n"
1687 . '<legend>' . __('Database for user') . '</legend>' . "\n";
1689 $html_output .= PMA_Util::getCheckbox(
1690 'createdb-1',
1691 __('Create database with same name and grant all privileges.'),
1692 false, false
1694 $html_output .= '<br />' . "\n";
1695 $html_output .= PMA_Util::getCheckbox(
1696 'createdb-2',
1697 __('Grant all privileges on wildcard name (username\\_%).'),
1698 false, false
1700 $html_output .= '<br />' . "\n";
1702 if (! empty($dbname) ) {
1703 $html_output .= PMA_Util::getCheckbox(
1704 'createdb-3',
1705 sprintf(
1706 __('Grant all privileges on database &quot;%s&quot;.'),
1707 htmlspecialchars($dbname)
1709 true,
1710 false
1712 $html_output .= '<input type="hidden" name="dbname" value="'
1713 . htmlspecialchars($dbname) . '" />' . "\n";
1714 $html_output .= '<br />' . "\n";
1717 $html_output .= '</fieldset>' . "\n";
1718 $html_output .= PMA_getHtmlToDisplayPrivilegesTable('*', '*', false);
1719 $html_output .= '<fieldset id="fieldset_add_user_footer" class="tblFooters">'
1720 . "\n"
1721 . '<input type="submit" name="adduser_submit" '
1722 . 'value="' . __('Go') . '" />' . "\n"
1723 . '</fieldset>' . "\n"
1724 . '</form>' . "\n";
1726 return $html_output;
1730 * Get the list of privileges and list of compared privileges as strings
1731 * and return a array that contains both strings
1733 * @return array $list_of_privileges, $list_of_compared_privileges
1735 function PMA_getListOfPrivilegesAndComparedPrivileges()
1737 $list_of_privileges
1738 = '`User`, '
1739 . '`Host`, '
1740 . '`Select_priv`, '
1741 . '`Insert_priv`, '
1742 . '`Update_priv`, '
1743 . '`Delete_priv`, '
1744 . '`Create_priv`, '
1745 . '`Drop_priv`, '
1746 . '`Grant_priv`, '
1747 . '`Index_priv`, '
1748 . '`Alter_priv`, '
1749 . '`References_priv`, '
1750 . '`Create_tmp_table_priv`, '
1751 . '`Lock_tables_priv`, '
1752 . '`Create_view_priv`, '
1753 . '`Show_view_priv`, '
1754 . '`Create_routine_priv`, '
1755 . '`Alter_routine_priv`, '
1756 . '`Execute_priv`';
1758 $list_of_compared_privileges
1759 = '`Select_priv` = \'N\''
1760 . ' AND `Insert_priv` = \'N\''
1761 . ' AND `Update_priv` = \'N\''
1762 . ' AND `Delete_priv` = \'N\''
1763 . ' AND `Create_priv` = \'N\''
1764 . ' AND `Drop_priv` = \'N\''
1765 . ' AND `Grant_priv` = \'N\''
1766 . ' AND `References_priv` = \'N\''
1767 . ' AND `Create_tmp_table_priv` = \'N\''
1768 . ' AND `Lock_tables_priv` = \'N\''
1769 . ' AND `Create_view_priv` = \'N\''
1770 . ' AND `Show_view_priv` = \'N\''
1771 . ' AND `Create_routine_priv` = \'N\''
1772 . ' AND `Alter_routine_priv` = \'N\''
1773 . ' AND `Execute_priv` = \'N\'';
1775 if (PMA_MYSQL_INT_VERSION >= 50106) {
1776 $list_of_privileges .=
1777 ', `Event_priv`, '
1778 . '`Trigger_priv`';
1779 $list_of_compared_privileges .=
1780 ' AND `Event_priv` = \'N\''
1781 . ' AND `Trigger_priv` = \'N\'';
1783 return array($list_of_privileges, $list_of_compared_privileges);
1787 * Get the HTML for user form and check the privileges for a particular database.
1789 * @param string $db database name
1791 * @return string $html_output
1793 function PMA_getHtmlForSpecificDbPrivileges($db)
1795 // check the privileges for a particular database.
1796 $html_output = '<form id="usersForm" action="server_privileges.php">'
1797 . '<fieldset>' . "\n";
1798 $html_output .= '<legend>' . "\n"
1799 . PMA_Util::getIcon('b_usrcheck.png')
1800 . ' '
1801 . sprintf(
1802 __('Users having access to &quot;%s&quot;'),
1803 '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
1804 . PMA_URL_getCommon($db) . '">'
1805 . htmlspecialchars($db)
1806 . '</a>'
1808 . "\n"
1809 . '</legend>' . "\n";
1811 $html_output .= '<table id="dbspecificuserrights" class="data">' . "\n"
1812 . '<thead>' . "\n"
1813 . '<tr><th>' . __('User') . '</th>' . "\n"
1814 . '<th>' . __('Host') . '</th>' . "\n"
1815 . '<th>' . __('Type') . '</th>' . "\n"
1816 . '<th>' . __('Privileges') . '</th>' . "\n"
1817 . '<th>' . __('Grant') . '</th>' . "\n"
1818 . '<th>' . __('Action') . '</th>' . "\n"
1819 . '</tr>' . "\n"
1820 . '</thead>' . "\n";
1821 $odd_row = true;
1822 // now, we build the table...
1823 list($list_of_privileges, $list_of_compared_privileges)
1824 = PMA_getListOfPrivilegesAndComparedPrivileges();
1826 $sql_query = '(SELECT ' . $list_of_privileges . ', `Db`, \'d\' AS `Type`'
1827 .' FROM `mysql`.`db`'
1828 .' WHERE \'' . PMA_Util::sqlAddSlashes($db)
1829 . "'"
1830 .' LIKE `Db`'
1831 .' AND NOT (' . $list_of_compared_privileges. ')) '
1832 .'UNION '
1833 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`, \'g\' AS `Type`'
1834 .' FROM `mysql`.`user` '
1835 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
1836 .' ORDER BY `User` ASC,'
1837 .' `Host` ASC,'
1838 .' `Db` ASC;';
1839 $res = $GLOBALS['dbi']->query($sql_query);
1841 $privMap = array();
1842 while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
1843 $user = $row['User'];
1844 $host = $row['Host'];
1845 if (! isset($privMap[$user])) {
1846 $privMap[$user] = array();
1848 if (! isset($privMap[$user][$host])) {
1849 $privMap[$user][$host] = array();
1851 $privMap[$user][$host][] = $row;
1854 $html_output .= PMA_getHtmlTableBodyForSpecificDbOrTablePrivs($privMap, $db);
1855 $html_output .= '</table>'
1856 . '</fieldset>'
1857 . '</form>' . "\n";
1859 if ($GLOBALS['is_ajax_request'] == true
1860 && empty($_REQUEST['ajax_page_request'])
1862 $message = PMA_Message::success(__('User has been added.'));
1863 $response = PMA_Response::getInstance();
1864 $response->addJSON('message', $message);
1865 $response->addJSON('user_form', $html_output);
1866 exit;
1867 } else {
1868 // Offer to create a new user for the current database
1869 $html_output .= '<fieldset id="fieldset_add_user">' . "\n"
1870 . '<legend>' . _pgettext('Create new user', 'New') . '</legend>' . "\n";
1872 $html_output .= '<a href="server_privileges.php'
1873 . PMA_URL_getCommon(
1874 array(
1875 'adduser' => 1,
1876 'dbname' => $db,
1879 .'" rel="'
1880 . PMA_URL_getCommon(array('checkprivsdb' => $db))
1881 . '" class="ajax" name="db_specific">' . "\n"
1882 . PMA_Util::getIcon('b_usradd.png')
1883 . ' ' . __('Add user') . '</a>' . "\n";
1885 $html_output .= '</fieldset>' . "\n";
1887 return $html_output;
1891 * Get the HTML for user form and check the privileges for a particular table.
1893 * @param string $db database name
1894 * @param string $table table name
1896 * @return string $html_output
1898 function PMA_getHtmlForSpecificTablePrivileges($db, $table)
1900 // check the privileges for a particular table.
1901 $html_output = '<form id="usersForm" action="server_privileges.php">';
1902 $html_output .= '<fieldset>';
1903 $html_output .= '<legend>'
1904 . PMA_Util::getIcon('b_usrcheck.png')
1905 . sprintf(
1906 __('Users having access to &quot;%s&quot;'),
1907 '<a href="' . $GLOBALS['cfg']['DefaultTabTable']
1908 . PMA_URL_getCommon(
1909 array(
1910 'db' => $db,
1911 'table' => $table,
1913 ) . '">'
1914 . htmlspecialchars($db) . '.' . htmlspecialchars($table)
1915 . '</a>'
1917 . '</legend>';
1919 $html_output .= '<table id="tablespecificuserrights" class="data">';
1920 $html_output .= '<thead>'
1921 . '<tr><th>' . __('User') . '</th>'
1922 . '<th>' . __('Host') . '</th>'
1923 . '<th>' . __('Type') . '</th>'
1924 . '<th>' . __('Privileges') . '</th>'
1925 . '<th>' . __('Grant') . '</th>'
1926 . '<th>' . __('Action') . '</th>'
1927 . '</tr>'
1928 . '</thead>';
1930 list($list_of_privileges, $list_of_compared_privileges)
1931 = PMA_getListOfPrivilegesAndComparedPrivileges();
1932 $sql_query
1933 = "("
1934 . " SELECT " . $list_of_privileges . ", '*' AS `Db`, 'g' AS `Type`"
1935 . " FROM `mysql`.`user`"
1936 . " WHERE NOT (" . $list_of_compared_privileges . ")"
1937 . ")"
1938 . " UNION "
1939 . "("
1940 . " SELECT " . $list_of_privileges . ", `Db`, 'd' AS `Type`"
1941 . " FROM `mysql`.`db`"
1942 . " WHERE '" . PMA_Util::sqlAddSlashes($db) . "' LIKE `Db`"
1943 . " AND NOT (" . $list_of_compared_privileges. ")"
1944 . ")"
1945 . " ORDER BY `User` ASC, `Host` ASC, `Db` ASC;";
1946 $res = $GLOBALS['dbi']->query($sql_query);
1948 $privMap = array();
1949 while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
1950 $user = $row['User'];
1951 $host = $row['Host'];
1952 if (! isset($privMap[$user])) {
1953 $privMap[$user] = array();
1955 if (! isset($privMap[$user][$host])) {
1956 $privMap[$user][$host] = array();
1958 $privMap[$user][$host][] = $row;
1961 $sql_query = "SELECT `User`, `Host`, `Db`,"
1962 . " 't' AS `Type`, `Table_name`, `Table_priv`"
1963 . " FROM `mysql`.`tables_priv`"
1964 . " WHERE '" . PMA_Util::sqlAddSlashes($db) . "' LIKE `Db`"
1965 . " AND '" . PMA_Util::sqlAddSlashes($table) . "' LIKE `Table_name`"
1966 . " AND NOT (`Table_priv` = '' AND Column_priv = '')"
1967 . " ORDER BY `User` ASC, `Host` ASC, `Db` ASC, `Table_priv` ASC;";
1968 $res = $GLOBALS['dbi']->query($sql_query);
1970 while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
1971 $user = $row['User'];
1972 $host = $row['Host'];
1973 if (! isset($privMap[$user])) {
1974 $privMap[$user] = array();
1976 if (! isset($privMap[$user][$host])) {
1977 $privMap[$user][$host] = array();
1979 $privMap[$user][$host][] = $row;
1982 $html_output .= PMA_getHtmlTableBodyForSpecificDbOrTablePrivs(
1983 $privMap, $db, $table
1985 $html_output .= '</table>';
1986 $html_output .= '</fieldset>';
1987 $html_output .= '</form>';
1989 // Offer to create a new user for the current database
1990 $html_output .= '<fieldset id="fieldset_add_user">'
1991 . '<legend>' . _pgettext('Create new user', 'New') . '</legend>';
1992 $html_output .= '<a href="server_privileges.php'
1993 . PMA_URL_getCommon(
1994 array(
1995 'adduser' => 1,
1996 'dbname' => $db,
1997 'tablename' => $table
2000 . '" rel="' . PMA_URL_getCommon(
2001 array('checkprivsdb' => $db, 'checkprivstable' => $table)
2003 . '" class="ajax" name="table_specific">'
2004 . PMA_Util::getIcon('b_usradd.png') . __('Add user') . '</a>';
2006 $html_output .= '</fieldset>';
2007 return $html_output;
2011 * Get HTML snippet for table body of specific database or table privileges
2013 * @param boolean $privMap priviledge map
2014 * @param boolean $db database
2015 * @param boolean $table table
2017 * @return string $html_output
2019 function PMA_getHtmlTableBodyForSpecificDbOrTablePrivs($privMap, $db, $table = null)
2021 $html_output = '<tbody>';
2022 $odd_row = true;
2023 if (! empty($privMap)) {
2024 foreach ($privMap as $current_user => $val) {
2025 foreach ($val as $current_host => $current_privileges) {
2026 $html_output .= '<tr class="noclick '
2027 . ($odd_row ? 'odd' : 'even') . '">';
2029 // user
2030 $html_output .= '<td';
2031 if (count($current_privileges) > 1) {
2032 $html_output .= ' rowspan="' . count($current_privileges) . '"';
2034 $html_output .= '>';
2035 if (empty($current_user)) {
2036 $html_output .= '<span style="color: #FF0000">'
2037 . __('Any') . '</span>';
2038 } else {
2039 $html_output .= htmlspecialchars($current_user);
2041 $html_output .= '</td>';
2043 // host
2044 $html_output .= '<td';
2045 if (count($current_privileges) > 1) {
2046 $html_output .= ' rowspan="' . count($current_privileges) . '"';
2048 $html_output .= '>';
2049 $html_output .= htmlspecialchars($current_host);
2050 $html_output .= '</td>';
2052 for ($i = 0; $i < count($current_privileges); $i++) {
2053 $current = $current_privileges[$i];
2055 // type
2056 $html_output .= '<td>';
2057 if ($current['Type'] == 'g') {
2058 $html_output .= __('global');
2059 } elseif ($current['Type'] == 'd') {
2060 if ($current['Db'] == PMA_Util::escapeMysqlWildcards($db)) {
2061 $html_output .= __('database-specific');
2062 } else {
2063 $html_output .= __('wildcard'). ': '
2064 . '<code>'
2065 . htmlspecialchars($current['Db'])
2066 . '</code>';
2068 } elseif ($current['Type'] == 't') {
2069 $html_output .= __('table-specific');
2071 $html_output .= '</td>';
2073 // privileges
2074 $html_output .= '<td>';
2075 if (isset($current['Table_name'])) {
2076 $privList = explode(',', $current['Table_priv']);
2077 $privs = array();
2078 $grantsArr = PMA_getTableGrantsArray();
2079 foreach ($grantsArr as $grant) {
2080 $privs[$grant[0]] = 'N';
2081 foreach ($privList as $priv) {
2082 if ($grant[0] == $priv) {
2083 $privs[$grant[0]] = 'Y';
2087 $html_output .= '<code>'
2088 . join(
2089 ',',
2090 PMA_extractPrivInfo($privs, true, true)
2092 . '</code>';
2093 } else {
2094 $html_output .= '<code>'
2095 . join(
2096 ',',
2097 PMA_extractPrivInfo($current, true, false)
2099 . '</code>';
2101 $html_output .= '</td>';
2103 // grant
2104 $html_output .= '<td>';
2105 $containsGrant = false;
2106 if (isset($current['Table_name'])) {
2107 $privList = explode(',', $current['Table_priv']);
2108 foreach ($privList as $priv) {
2109 if ($priv == 'Grant') {
2110 $containsGrant = true;
2113 } else {
2114 $containsGrant = $current['Grant_priv'] == 'Y';
2116 $html_output .= ($containsGrant ? __('Yes') : __('No'));
2117 $html_output .= '</td>';
2119 // action
2120 $html_output .= '<td>';
2121 $specific_db = (isset($current['Db']) && $current['Db'] != '*')
2122 ? $current['Db'] : '';
2123 $specific_table = (isset($current['Table_name'])
2124 && $current['Table_name'] != '*')
2125 ? $current['Table_name'] : '';
2126 $html_output .= PMA_getUserEditLink(
2127 $current_user,
2128 $current_host,
2129 $specific_db,
2130 $specific_table
2132 $html_output .= '</td>';
2134 $html_output .= '</tr>';
2135 if (($i + 1) < count($current_privileges)) {
2136 $html_output .= '<tr class="noclick '
2137 . ($odd_row ? 'odd' : 'even') . '">';
2140 $odd_row = ! $odd_row;
2143 } else {
2144 $html_output .= '<tr class="odd">'
2145 . '<td colspan="6">'
2146 . __('No user found.')
2147 . '</td>'
2148 . '</tr>';
2150 $html_output .= '</tbody>';
2152 return $html_output;
2156 * Returns edit link for a user.
2158 * @param string $username User name
2159 * @param string $hostname Host name
2160 * @param string $dbname Database name
2161 * @param string $tablename Table name
2163 * @return HTML code with link
2165 function PMA_getUserEditLink($username, $hostname, $dbname = '', $tablename = '')
2167 return '<a class="edit_user_anchor ajax"'
2168 . ' href="server_privileges.php'
2169 . PMA_URL_getCommon(
2170 array(
2171 'username' => $username,
2172 'hostname' => $hostname,
2173 'dbname' => $dbname,
2174 'tablename' => $tablename,
2177 . '">'
2178 . PMA_Util::getIcon('b_usredit.png', __('Edit Privileges'))
2179 . '</a>';
2183 * Returns revoke link for a user.
2185 * @param string $username User name
2186 * @param string $hostname Host name
2187 * @param string $dbname Database name
2188 * @param string $tablename Table name
2190 * @return HTML code with link
2192 function PMA_getUserRevokeLink($username, $hostname, $dbname = '', $tablename = '')
2194 return '<a href="server_privileges.php'
2195 . PMA_URL_getCommon(
2196 array(
2197 'username' => $username,
2198 'hostname' => $hostname,
2199 'dbname' => $dbname,
2200 'tablename' => $tablename,
2201 'revokeall' => 1,
2204 . '">'
2205 . PMA_Util::getIcon('b_usrdrop.png', __('Revoke'))
2206 . '</a>';
2210 * Returns export link for a user.
2212 * @param string $username User name
2213 * @param string $hostname Host name
2214 * @param string $initial Initial value
2216 * @return HTML code with link
2218 function PMA_getUserExportLink($username, $hostname, $initial = '')
2220 return '<a class="export_user_anchor ajax"'
2221 . ' href="server_privileges.php'
2222 . PMA_URL_getCommon(
2223 array(
2224 'username' => $username,
2225 'hostname' => $hostname,
2226 'initial' => $initial,
2227 'export' => 1,
2230 . '">'
2231 . PMA_Util::getIcon('b_tblexport.png', __('Export'))
2232 . '</a>';
2236 * This function return the extra data array for the ajax behavior
2238 * @param string $password password
2239 * @param string $sql_query sql query
2240 * @param string $hostname hostname
2241 * @param string $username username
2243 * @return array $extra_data
2245 function PMA_getExtraDataForAjaxBehavior(
2246 $password, $sql_query, $hostname, $username
2248 if (isset($GLOBALS['dbname'])) {
2249 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
2250 if (preg_match('/(?<!\\\\)(?:_|%)/i', $GLOBALS['dbname'])) {
2251 $dbname_is_wildcard = true;
2252 } else {
2253 $dbname_is_wildcard = false;
2257 $extra_data = array();
2258 if (strlen($sql_query)) {
2259 $extra_data['sql_query']
2260 = PMA_Util::getMessage(null, $sql_query);
2263 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
2265 * generate html on the fly for the new user that was just created.
2267 $new_user_string = '<tr>'."\n"
2268 . '<td> <input type="checkbox" name="selected_usr[]" '
2269 . 'id="checkbox_sel_users_"'
2270 . 'value="'
2271 . htmlspecialchars($username)
2272 . '&amp;#27;' . htmlspecialchars($hostname) . '" />'
2273 . '</td>' . "\n"
2274 . '<td><label for="checkbox_sel_users_">'
2275 . (empty($_REQUEST['username'])
2276 ? '<span style="color: #FF0000">' . __('Any') . '</span>'
2277 : htmlspecialchars($username) ) . '</label></td>' . "\n"
2278 . '<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
2280 $new_user_string .= '<td>';
2282 if (! empty($password) || isset($_POST['pma_pw'])) {
2283 $new_user_string .= __('Yes');
2284 } else {
2285 $new_user_string .= '<span style="color: #FF0000">'
2286 . __('No')
2287 . '</span>';
2290 $new_user_string .= '</td>'."\n";
2291 $new_user_string .= '<td>'
2292 . '<code>' . join(', ', PMA_extractPrivInfo('', true)) . '</code>'
2293 . '</td>'; //Fill in privileges here
2294 $new_user_string .= '<td class="usrGroup"></td>';
2295 $new_user_string .= '<td>';
2297 if ((isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y')) {
2298 $new_user_string .= __('Yes');
2299 } else {
2300 $new_user_string .= __('No');
2303 $new_user_string .='</td>';
2305 $new_user_string .= '<td>'
2306 . PMA_getUserEditLink($username, $hostname)
2307 . '</td>' . "\n";
2308 $new_user_string .= '<td>'
2309 . PMA_getUserExportLink(
2310 $username,
2311 $hostname,
2312 isset($_GET['initial']) ? $_GET['initial'] : ''
2314 . '</td>' . "\n";
2316 $new_user_string .= '</tr>';
2318 $extra_data['new_user_string'] = $new_user_string;
2321 * Generate the string for this alphabet's initial, to update the user
2322 * pagination
2324 $new_user_initial = strtoupper(substr($username, 0, 1));
2325 $new_user_initial_string = '<a href="server_privileges.php'
2326 . PMA_URL_getCommon(array('initial' => $new_user_initial)) .'">'
2327 . $new_user_initial . '</a>';
2328 $extra_data['new_user_initial'] = $new_user_initial;
2329 $extra_data['new_user_initial_string'] = $new_user_initial_string;
2332 if (isset($_POST['update_privs'])) {
2333 $extra_data['db_specific_privs'] = false;
2334 $extra_data['db_wildcard_privs'] = false;
2335 if (isset($dbname_is_wildcard)) {
2336 $extra_data['db_specific_privs'] = ! $dbname_is_wildcard;
2337 $extra_data['db_wildcard_privs'] = $dbname_is_wildcard;
2339 $new_privileges = join(', ', PMA_extractPrivInfo('', true));
2341 $extra_data['new_privileges'] = $new_privileges;
2344 if (isset($_REQUEST['validate_username'])) {
2345 $sql_query = "SELECT * FROM `mysql`.`user` WHERE `User` = '"
2346 . $_REQUEST['username'] . "';";
2347 $res = $GLOBALS['dbi']->query($sql_query);
2348 $row = $GLOBALS['dbi']->fetchRow($res);
2349 if (empty($row)) {
2350 $extra_data['user_exists'] = false;
2351 } else {
2352 $extra_data['user_exists'] = true;
2356 return $extra_data;
2360 * Get the HTML snippet for change user login information
2362 * @param string $username username
2363 * @param string $hostname host name
2365 * @return string HTML snippet
2367 function PMA_getChangeLoginInformationHtmlForm($username, $hostname)
2369 $choices = array(
2370 '4' => __('… keep the old one.'),
2371 '1' => __('… delete the old one from the user tables.'),
2372 '2' => __(
2373 '… revoke all active privileges from '
2374 . 'the old one and delete it afterwards.'
2376 '3' => __(
2377 '… delete the old one from the user tables '
2378 . 'and reload the privileges afterwards.'
2382 $class = ' ajax';
2383 $html_output = '<form action="server_privileges.php" '
2384 . 'method="post" class="copyUserForm' . $class .'">' . "\n"
2385 . PMA_URL_getHiddenInputs('', '')
2386 . '<input type="hidden" name="old_username" '
2387 . 'value="' . htmlspecialchars($username) . '" />' . "\n"
2388 . '<input type="hidden" name="old_hostname" '
2389 . 'value="' . htmlspecialchars($hostname) . '" />' . "\n"
2390 . '<fieldset id="fieldset_change_copy_user">' . "\n"
2391 . '<legend>' . __('Change Login Information / Copy User')
2392 . '</legend>' . "\n"
2393 . PMA_getHtmlForDisplayLoginInformationFields('change');
2395 $html_output .= '<fieldset id="fieldset_mode">' . "\n"
2396 . ' <legend>'
2397 . __('Create a new user with the same privileges and …')
2398 . '</legend>' . "\n";
2399 $html_output .= PMA_Util::getRadioFields(
2400 'mode', $choices, '4', true
2402 $html_output .= '</fieldset>' . "\n"
2403 . '</fieldset>' . "\n";
2405 $html_output .= '<fieldset id="fieldset_change_copy_user_footer" '
2406 . 'class="tblFooters">' . "\n"
2407 . '<input type="submit" name="change_copy" '
2408 . 'value="' . __('Go') . '" />' . "\n"
2409 . '</fieldset>' . "\n"
2410 . '</form>' . "\n";
2412 return $html_output;
2416 * Provide a line with links to the relevant database and table
2418 * @param string $url_dbname url database name that urlencode() string
2419 * @param string $dbname database name
2420 * @param string $tablename table name
2422 * @return string HTML snippet
2424 function PMA_getLinkToDbAndTable($url_dbname, $dbname, $tablename)
2426 $html_output = '[ ' . __('Database')
2427 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase']
2428 . PMA_URL_getCommon(
2429 array(
2430 'db' => $url_dbname,
2431 'reload' => 1
2434 . '">'
2435 . htmlspecialchars($dbname) . ': '
2436 . PMA_Util::getTitleForTarget(
2437 $GLOBALS['cfg']['DefaultTabDatabase']
2439 . "</a> ]\n";
2441 if (strlen($tablename)) {
2442 $html_output .= ' [ ' . __('Table') . ' <a href="'
2443 . $GLOBALS['cfg']['DefaultTabTable']
2444 . PMA_URL_getCommon(
2445 array(
2446 'db' => $url_dbname,
2447 'table' => $tablename,
2448 'reload' => 1,
2451 . '">' . htmlspecialchars($tablename) . ': '
2452 . PMA_Util::getTitleForTarget(
2453 $GLOBALS['cfg']['DefaultTabTable']
2455 . "</a> ]\n";
2457 return $html_output;
2461 * no db name given, so we want all privs for the given user
2462 * db name was given, so we want all user specific rights for this db
2463 * So this function returns user rights as an array
2465 * @param array $tables tables
2466 * @param string $user_host_condition a where clause that containd user's host
2467 * condition
2468 * @param string $dbname database name
2470 * @return array $db_rights database rights
2472 function PMA_getUserSpecificRights($tables, $user_host_condition, $dbname)
2474 if (! strlen($dbname)) {
2475 $tables_to_search_for_users = array(
2476 'tables_priv', 'columns_priv',
2478 $dbOrTableName = 'Db';
2479 } else {
2480 $user_host_condition .=
2481 ' AND `Db`'
2482 .' LIKE \''
2483 . PMA_Util::sqlAddSlashes($dbname, true) . "'";
2484 $tables_to_search_for_users = array('columns_priv',);
2485 $dbOrTableName = 'Table_name';
2488 $db_rights_sqls = array();
2489 foreach ($tables_to_search_for_users as $table_search_in) {
2490 if (in_array($table_search_in, $tables)) {
2491 $db_rights_sqls[] = '
2492 SELECT DISTINCT `' . $dbOrTableName .'`
2493 FROM `mysql`.' . PMA_Util::backquote($table_search_in)
2494 . $user_host_condition;
2498 $user_defaults = array(
2499 $dbOrTableName => '',
2500 'Grant_priv' => 'N',
2501 'privs' => array('USAGE'),
2502 'Column_priv' => true,
2505 // for the rights
2506 $db_rights = array();
2508 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
2509 .' ORDER BY `' . $dbOrTableName .'` ASC';
2511 $db_rights_result = $GLOBALS['dbi']->query($db_rights_sql);
2513 while ($db_rights_row = $GLOBALS['dbi']->fetchAssoc($db_rights_result)) {
2514 $db_rights_row = array_merge($user_defaults, $db_rights_row);
2515 if (! strlen($dbname)) {
2516 // only Db names in the table `mysql`.`db` uses wildcards
2517 // as we are in the db specific rights display we want
2518 // all db names escaped, also from other sources
2519 $db_rights_row['Db'] = PMA_Util::escapeMysqlWildcards(
2520 $db_rights_row['Db']
2523 $db_rights[$db_rights_row[$dbOrTableName]] = $db_rights_row;
2526 $GLOBALS['dbi']->freeResult($db_rights_result);
2528 if (! strlen($dbname)) {
2529 $sql_query = 'SELECT * FROM `mysql`.`db`'
2530 . $user_host_condition . ' ORDER BY `Db` ASC';
2531 } else {
2532 $sql_query = 'SELECT `Table_name`,'
2533 .' `Table_priv`,'
2534 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
2535 .' AS \'Column_priv\''
2536 .' FROM `mysql`.`tables_priv`'
2537 . $user_host_condition
2538 .' ORDER BY `Table_name` ASC;';
2541 $result = $GLOBALS['dbi']->query($sql_query);
2542 $sql_query = '';
2544 while ($row = $GLOBALS['dbi']->fetchAssoc($result)) {
2545 if (isset($db_rights[$row[$dbOrTableName]])) {
2546 $db_rights[$row[$dbOrTableName]]
2547 = array_merge($db_rights[$row[$dbOrTableName]], $row);
2548 } else {
2549 $db_rights[$row[$dbOrTableName]] = $row;
2551 if (! strlen($dbname)) {
2552 // there are db specific rights for this user
2553 // so we can drop this db rights
2554 $db_rights[$row['Db']]['can_delete'] = true;
2557 $GLOBALS['dbi']->freeResult($result);
2558 return $db_rights;
2562 * Display user rights in table rows(Table specific or database specific privs)
2564 * @param array $db_rights user's database rights array
2565 * @param string $dbname database name
2566 * @param string $hostname host name
2567 * @param string $username username
2569 * @return array $found_rows, $html_output
2571 function PMA_getHtmlForDisplayUserRightsInRows($db_rights, $dbname,
2572 $hostname, $username
2574 $html_output = '';
2575 $found_rows = array();
2576 // display rows
2577 if (count($db_rights) < 1) {
2578 $html_output .= '<tr class="odd">' . "\n"
2579 . '<td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
2580 . '</tr>' . "\n";
2581 } else {
2582 $odd_row = true;
2583 //while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
2584 foreach ($db_rights as $row) {
2585 $found_rows[] = (! strlen($dbname)) ? $row['Db'] : $row['Table_name'];
2587 $html_output .= '<tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2588 . '<td>'
2589 . htmlspecialchars(
2590 (! strlen($dbname)) ? $row['Db'] : $row['Table_name']
2592 . '</td>' . "\n"
2593 . '<td><code>' . "\n"
2594 . ' '
2595 . join(
2596 ',' . "\n" . ' ',
2597 PMA_extractPrivInfo($row, true)
2598 ) . "\n"
2599 . '</code></td>' . "\n"
2600 . '<td>'
2601 . ((((! strlen($dbname)) && $row['Grant_priv'] == 'Y')
2602 || (strlen($dbname)
2603 && in_array('Grant', explode(',', $row['Table_priv']))))
2604 ? __('Yes')
2605 : __('No'))
2606 . '</td>' . "\n"
2607 . '<td>';
2608 if (! empty($row['Table_privs']) || ! empty ($row['Column_priv'])) {
2609 $html_output .= __('Yes');
2610 } else {
2611 $html_output .= __('No');
2613 $html_output .= '</td>' . "\n"
2614 . '<td>';
2615 $html_output .= PMA_getUserEditLink(
2616 $username,
2617 $hostname,
2618 (! strlen($dbname)) ? $row['Db'] : $dbname,
2619 (! strlen($dbname)) ? '' : $row['Table_name']
2621 $html_output .= '</td>' . "\n"
2622 . ' <td>';
2623 if (! empty($row['can_delete'])
2624 || isset($row['Table_name'])
2625 && strlen($row['Table_name'])
2627 $html_output .= PMA_getUserRevokeLink(
2628 $username,
2629 $hostname,
2630 (! strlen($dbname)) ? $row['Db'] : $dbname,
2631 (! strlen($dbname)) ? '' : $row['Table_name']
2634 $html_output .= '</td>' . "\n"
2635 . '</tr>' . "\n";
2636 $odd_row = ! $odd_row;
2637 } // end while
2638 } //end if
2639 return array($found_rows, $html_output);
2643 * Get a HTML table for display user's tabel specific or database specific rights
2645 * @param string $username username
2646 * @param string $hostname host name
2647 * @param string $dbname database name
2649 * @return array $html_output, $found_rows
2651 function PMA_getTableForDisplayAllTableSpecificRights(
2652 $username, $hostname, $dbname
2654 // table header
2655 $html_output = PMA_URL_getHiddenInputs('', '')
2656 . '<input type="hidden" name="username" '
2657 . 'value="' . htmlspecialchars($username) . '" />' . "\n"
2658 . '<input type="hidden" name="hostname" '
2659 . 'value="' . htmlspecialchars($hostname) . '" />' . "\n"
2660 . '<fieldset>' . "\n"
2661 . '<legend>'
2662 . (! strlen($dbname)
2663 ? __('Database-specific privileges')
2664 : __('Table-specific privileges')
2666 . '</legend>' . "\n"
2667 . '<table class="data">' . "\n"
2668 . '<thead>' . "\n"
2669 . '<tr><th>'
2670 . (! strlen($dbname) ? __('Database') : __('Table'))
2671 . '</th>' . "\n"
2672 . '<th>' . __('Privileges') . '</th>' . "\n"
2673 . '<th>' . __('Grant') . '</th>' . "\n"
2674 . '<th>'
2675 . (! strlen($dbname)
2676 ? __('Table-specific privileges')
2677 : __('Column-specific privileges')
2679 . '</th>' . "\n"
2680 . '<th colspan="2">' . __('Action') . '</th>' . "\n"
2681 . '</tr>' . "\n"
2682 . '</thead>' . "\n";
2684 $user_host_condition = ' WHERE `User`'
2685 . ' = \'' . PMA_Util::sqlAddSlashes($username) . "'"
2686 . ' AND `Host`'
2687 . ' = \'' . PMA_Util::sqlAddSlashes($hostname) . "'";
2689 // table body
2690 // get data
2692 // we also want privielgs for this user not in table `db` but in other table
2693 $tables = $GLOBALS['dbi']->fetchResult('SHOW TABLES FROM `mysql`;');
2696 * no db name given, so we want all privs for the given user
2697 * db name was given, so we want all user specific rights for this db
2699 $db_rights = PMA_getUserSpecificRights($tables, $user_host_condition, $dbname);
2701 ksort($db_rights);
2703 $html_output .= '<tbody>' . "\n";
2704 // display rows
2705 list ($found_rows, $html_out) = PMA_getHtmlForDisplayUserRightsInRows(
2706 $db_rights, $dbname, $hostname, $username
2709 $html_output .= $html_out;
2710 $html_output .= '</tbody>' . "\n";
2711 $html_output .='</table>' . "\n";
2713 return array($html_output, $found_rows);
2717 * Get HTML for display select db
2719 * @param array $found_rows isset($dbname)) ? $row['Db'] : $row['Table_name']
2721 * @return string HTML snippet
2723 function PMA_getHtmlForDisplaySelectDbInEditPrivs($found_rows)
2725 $pred_db_array = $GLOBALS['dbi']->fetchResult('SHOW DATABASES;');
2727 $html_output = '<label for="text_dbname">'
2728 . __('Add privileges on the following database:') . '</label>' . "\n";
2729 if (! empty($pred_db_array)) {
2730 $html_output .= '<select name="pred_dbname" class="autosubmit">' . "\n"
2731 . '<option value="" selected="selected">'
2732 . __('Use text field:') . '</option>' . "\n";
2733 foreach ($pred_db_array as $current_db) {
2734 $current_db_show = $current_db;
2735 $current_db = PMA_Util::escapeMysqlWildcards($current_db);
2736 // cannot use array_diff() once, outside of the loop,
2737 // because the list of databases has special characters
2738 // already escaped in $found_rows,
2739 // contrary to the output of SHOW DATABASES
2740 if (empty($found_rows) || ! in_array($current_db, $found_rows)) {
2741 $html_output .= '<option value="'
2742 . htmlspecialchars($current_db) . '">'
2743 . htmlspecialchars($current_db_show) . '</option>' . "\n";
2746 $html_output .= '</select>' . "\n";
2748 $html_output .= '<input type="text" id="text_dbname" name="dbname" '
2749 . 'required="required" />'
2750 . "\n"
2751 . PMA_Util::showHint(
2752 __('Wildcards % and _ should be escaped with a \ to use them literally.')
2754 return $html_output;
2758 * Get HTML for display table in edit privilege
2760 * @param string $dbname database naame
2761 * @param array $found_rows isset($dbname)) ? $row['Db'] : $row['Table_name']
2763 * @return string HTML snippet
2765 function PMA_displayTablesInEditPrivs($dbname, $found_rows)
2767 $html_output = '<input type="hidden" name="dbname"
2768 '. 'value="' . htmlspecialchars($dbname) . '"/>' . "\n";
2769 $html_output .= '<label for="text_tablename">'
2770 . __('Add privileges on the following table:') . '</label>' . "\n";
2772 $result = @$GLOBALS['dbi']->tryQuery(
2773 'SHOW TABLES FROM ' . PMA_Util::backquote(
2774 PMA_Util::unescapeMysqlWildcards($dbname)
2775 ) . ';',
2776 null,
2777 PMA_DatabaseInterface::QUERY_STORE
2780 if ($result) {
2781 $pred_tbl_array = array();
2782 while ($row = $GLOBALS['dbi']->fetchRow($result)) {
2783 if (! isset($found_rows) || ! in_array($row[0], $found_rows)) {
2784 $pred_tbl_array[] = $row[0];
2787 $GLOBALS['dbi']->freeResult($result);
2789 if (! empty($pred_tbl_array)) {
2790 $html_output .= '<select name="pred_tablename" '
2791 . 'class="autosubmit">' . "\n"
2792 . '<option value="" selected="selected">' . __('Use text field')
2793 . ':</option>' . "\n";
2794 foreach ($pred_tbl_array as $current_table) {
2795 $html_output .= '<option '
2796 . 'value="' . htmlspecialchars($current_table) . '">'
2797 . htmlspecialchars($current_table)
2798 . '</option>' . "\n";
2800 $html_output .= '</select>' . "\n";
2803 $html_output .= '<input type="text" id="text_tablename" name="tablename" />'
2804 . "\n";
2806 return $html_output;
2810 * Get HTML for display the users overview
2811 * (if less than 50 users, display them immediately)
2813 * @param array $result ran sql query
2814 * @param array $db_rights user's database rights array
2815 * @param string $pmaThemeImage a image source link
2816 * @param string $text_dir text directory
2818 * @return string HTML snippet
2820 function PMA_getUsersOverview($result, $db_rights, $pmaThemeImage, $text_dir)
2822 while ($row = $GLOBALS['dbi']->fetchAssoc($result)) {
2823 $row['privs'] = PMA_extractPrivInfo($row, true);
2824 $db_rights[$row['User']][$row['Host']] = $row;
2826 @$GLOBALS['dbi']->freeResult($result);
2828 $html_output
2829 = '<form name="usersForm" id="usersForm" action="server_privileges.php" '
2830 . 'method="post">' . "\n"
2831 . PMA_URL_getHiddenInputs('', '')
2832 . '<table id="tableuserrights" class="data">' . "\n"
2833 . '<thead>' . "\n"
2834 . '<tr><th></th>' . "\n"
2835 . '<th>' . __('User') . '</th>' . "\n"
2836 . '<th>' . __('Host') . '</th>' . "\n"
2837 . '<th>' . __('Password') . '</th>' . "\n"
2838 . '<th>' . __('Global privileges') . ' '
2839 . PMA_Util::showHint(
2840 __('Note: MySQL privilege names are expressed in English')
2842 . '</th>' . "\n";
2843 if ($GLOBALS['cfgRelation']['menuswork']) {
2844 $html_output .= '<th>' . __('User group') . '</th>' . "\n";
2846 $html_output .= '<th>' . __('Grant') . '</th>' . "\n"
2847 . '<th colspan="3">' . __('Action') . '</th>' . "\n"
2848 . '</tr>' . "\n"
2849 . '</thead>' . "\n";
2851 $html_output .= '<tbody>' . "\n";
2852 $html_output .= PMA_getTableBodyForUserRightsTable($db_rights);
2853 $html_output .= '</tbody>'
2854 . '</table>' . "\n";
2856 $html_output .= '<div style="float:left;">'
2857 . '<img class="selectallarrow"'
2858 . ' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
2859 . ' width="38" height="22"'
2860 . ' alt="' . __('With selected:') . '" />' . "\n"
2861 . '<input type="checkbox" id="usersForm_checkall" class="checkall_box" '
2862 . 'title="' . __('Check All') . '" /> '
2863 . '<label for="usersForm_checkall">' . __('Check All') . '</label> '
2864 . '<i style="margin-left: 2em">' . __('With selected:') . '</i>' . "\n";
2866 $html_output .= PMA_Util::getButtonOrImage(
2867 'submit_mult', 'mult_submit', 'submit_mult_export',
2868 __('Export'), 'b_tblexport.png', 'export'
2870 $html_output .= '<input type="hidden" name="initial" '
2871 . 'value="' . (isset($_GET['initial']) ? $_GET['initial'] : '') . '" />';
2872 $html_output .= '</div>'
2873 . '<div class="clear_both" style="clear:both"></div>';
2875 // add/delete user fieldset
2876 $html_output .= PMA_getFieldsetForAddDeleteUser();
2877 $html_output .= '</form>' . "\n";
2879 return $html_output;
2883 * Get table body for 'tableuserrights' table in userform
2885 * @param array $db_rights user's database rights array
2887 * @return string HTML snippet
2889 function PMA_getTableBodyForUserRightsTable($db_rights)
2891 if ($GLOBALS['cfgRelation']['menuswork']) {
2892 $usersTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb'])
2893 . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['users']);
2894 $sqlQuery = "SELECT * FROM " . $usersTable;
2895 $result = PMA_queryAsControlUser($sqlQuery, false);
2896 $groupAssignment = array();
2897 if ($result) {
2898 while ($row = $GLOBALS['dbi']->fetchAssoc($result)) {
2899 $groupAssignment[$row['username']] = $row['usergroup'];
2902 $GLOBALS['dbi']->freeResult($result);
2904 $userGroupTable = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb'])
2905 . "." . PMA_Util::backquote($GLOBALS['cfg']['Server']['usergroups']);
2906 $sqlQuery = "SELECT COUNT(*) FROM " . $userGroupTable;
2907 $userGroupCount = $GLOBALS['dbi']->fetchValue(
2908 $sqlQuery, 0, 0, $GLOBALS['controllink']
2912 $odd_row = true;
2913 $index_checkbox = 0;
2914 $html_output = '';
2915 foreach ($db_rights as $user) {
2916 ksort($user);
2917 foreach ($user as $host) {
2918 $index_checkbox++;
2919 $html_output .= '<tr class="' . ($odd_row ? 'odd' : 'even') . '">'
2920 . "\n";
2921 $html_output .= '<td>'
2922 . '<input type="checkbox" class="checkall" name="selected_usr[]" '
2923 . 'id="checkbox_sel_users_'
2924 . $index_checkbox . '" value="'
2925 . htmlspecialchars($host['User'] . '&amp;#27;' . $host['Host'])
2926 . '"'
2927 . ' /></td>' . "\n";
2929 $html_output .= '<td><label '
2930 . 'for="checkbox_sel_users_' . $index_checkbox . '">'
2931 . (empty($host['User'])
2932 ? '<span style="color: #FF0000">' . __('Any') . '</span>'
2933 : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
2934 . '<td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
2936 $html_output .= '<td>';
2937 switch ($host['Password']) {
2938 case 'Y':
2939 $html_output .= __('Yes');
2940 break;
2941 case 'N':
2942 $html_output .= '<span style="color: #FF0000">' . __('No')
2943 . '</span>';
2944 break;
2945 // this happens if this is a definition not coming from mysql.user
2946 default:
2947 $html_output .= '--'; // in future version, replace by "not present"
2948 break;
2949 } // end switch
2950 $html_output .= '</td>' . "\n";
2952 $html_output .= '<td><code>' . "\n"
2953 . '' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
2954 . '</code></td>' . "\n";
2955 if ($GLOBALS['cfgRelation']['menuswork']) {
2956 $html_output .= '<td class="usrGroup">' . "\n"
2957 . (isset($groupAssignment[$host['User']])
2958 ? $groupAssignment[$host['User']]
2959 : ''
2961 . '</td>' . "\n";
2963 $html_output .= '<td>'
2964 . ($host['Grant_priv'] == 'Y' ? __('Yes') : __('No'))
2965 . '</td>' . "\n";
2967 $html_output .= '<td class="center">'
2968 . PMA_getUserEditLink(
2969 $host['User'],
2970 $host['Host']
2972 . '</td>';
2973 if ($GLOBALS['cfgRelation']['menuswork'] && $userGroupCount > 0) {
2974 if (empty($host['User'])) {
2975 $html_output .= '<td class="center"></td>';
2976 } else {
2977 $html_output .= '<td class="center">'
2978 . '<a class="edit_user_group_anchor ajax"'
2979 . ' href="server_privileges.php'
2980 . PMA_URL_getCommon(array('username' => $host['User']))
2981 . '">'
2982 . PMA_Util::getIcon('b_usrlist.png', __('Edit user group'))
2983 . '</a>'
2984 . '</td>';
2987 $html_output .= '<td class="center">'
2988 . PMA_getUserExportLink(
2989 $host['User'],
2990 $host['Host'],
2991 isset($_GET['initial']) ? $_GET['initial'] : ''
2993 . '</td>';
2994 $html_output .= '</tr>';
2995 $odd_row = ! $odd_row;
2998 return $html_output;
3002 * Get HTML fieldset for Add/Delete user
3004 * @return string HTML snippet
3006 function PMA_getFieldsetForAddDeleteUser()
3008 $html_output = '<fieldset id="fieldset_add_user">' . "\n";
3009 $html_output .= '<a href="server_privileges.php'
3010 . PMA_URL_getCommon(array('adduser' => 1))
3011 . '" class="ajax">' . "\n"
3012 . PMA_Util::getIcon('b_usradd.png')
3013 . ' ' . __('Add user') . '</a>' . "\n";
3014 $html_output .= '</fieldset>' . "\n";
3016 $html_output .= '<fieldset id="fieldset_delete_user">'
3017 . '<legend>' . "\n"
3018 . PMA_Util::getIcon('b_usrdrop.png')
3019 . ' ' . __('Remove selected users') . '' . "\n"
3020 . '</legend>' . "\n";
3022 $html_output .= '<input type="hidden" name="mode" value="2" />' . "\n"
3023 . '('
3024 . __(
3025 'Revoke all active privileges from the users '
3026 . 'and delete them afterwards.'
3028 . ')'
3029 . '<br />' . "\n";
3031 $html_output .= '<input type="checkbox" '
3032 . 'title="'
3033 . __('Drop the databases that have the same names as the users.')
3034 . '" '
3035 . 'name="drop_users_db" id="checkbox_drop_users_db" />' . "\n";
3037 $html_output .= '<label for="checkbox_drop_users_db" '
3038 . 'title="'
3039 . __('Drop the databases that have the same names as the users.')
3040 . '">' . "\n"
3041 . ' '
3042 . __('Drop the databases that have the same names as the users.')
3043 . "\n"
3044 . '</label>' . "\n"
3045 . '</fieldset>' . "\n";
3047 $html_output .= '<fieldset id="fieldset_delete_user_footer" class="tblFooters">'
3048 . "\n";
3049 $html_output .= '<input type="submit" name="delete" '
3050 . 'value="' . __('Go') . '" id="buttonGo" '
3051 . 'class="ajax"/>' . "\n";
3053 $html_output .= '</fieldset>' . "\n";
3055 return $html_output;
3059 * Get HTML for Displays the initials
3061 * @param array $array_initials array for all initials, even non A-Z
3063 * @return string HTML snippet
3065 function PMA_getHtmlForDisplayTheInitials($array_initials)
3067 // initialize to false the letters A-Z
3068 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++) {
3069 if (! isset($array_initials[chr($letter_counter + 64)])) {
3070 $array_initials[chr($letter_counter + 64)] = false;
3074 $initials = $GLOBALS['dbi']->tryQuery(
3075 'SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC',
3076 null,
3077 PMA_DatabaseInterface::QUERY_STORE
3079 while (list($tmp_initial) = $GLOBALS['dbi']->fetchRow($initials)) {
3080 $array_initials[$tmp_initial] = true;
3083 // Display the initials, which can be any characters, not
3084 // just letters. For letters A-Z, we add the non-used letters
3085 // as greyed out.
3087 uksort($array_initials, "strnatcasecmp");
3089 $html_output = '<table id="initials_table" <cellspacing="5">'
3090 . '<tr>';
3091 foreach ($array_initials as $tmp_initial => $initial_was_found) {
3092 if (! empty($tmp_initial)) {
3093 if ($initial_was_found) {
3094 $html_output .= '<td>'
3095 . '<a class="ajax"'
3096 . ' href="server_privileges.php'
3097 . PMA_URL_getCommon(array('initial' => $tmp_initial))
3098 . '">' . $tmp_initial
3099 . '</a>'
3100 . '</td>' . "\n";
3101 } else {
3102 $html_output .= '<td>' . $tmp_initial . '</td>';
3106 $html_output .= '<td>'
3107 . '<a href="server_privileges.php'
3108 . PMA_URL_getCommon(array('showall' => 1))
3109 . '" class="nowrap">[' . __('Show all') . ']</a></td>' . "\n";
3110 $html_output .= '</tr></table>';
3112 return $html_output;
3116 * Get the database rigths array for Display user overview
3118 * @return array $db_rights database rights array
3120 function PMA_getDbRightsForUserOverview()
3122 // we also want users not in table `user` but in other table
3123 $tables = $GLOBALS['dbi']->fetchResult('SHOW TABLES FROM `mysql`;');
3125 $tables_to_search_for_users = array(
3126 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
3129 $db_rights_sqls = array();
3130 foreach ($tables_to_search_for_users as $table_search_in) {
3131 if (in_array($table_search_in, $tables)) {
3132 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`'
3133 . $table_search_in . '` '
3134 . (isset($_GET['initial'])
3135 ? PMA_rangeOfUsers($_GET['initial'])
3136 : '');
3139 $user_defaults = array(
3140 'User' => '',
3141 'Host' => '%',
3142 'Password' => '?',
3143 'Grant_priv' => 'N',
3144 'privs' => array('USAGE'),
3147 // for the rights
3148 $db_rights = array();
3150 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
3151 .' ORDER BY `User` ASC, `Host` ASC';
3153 $db_rights_result = $GLOBALS['dbi']->query($db_rights_sql);
3155 while ($db_rights_row = $GLOBALS['dbi']->fetchAssoc($db_rights_result)) {
3156 $db_rights_row = array_merge($user_defaults, $db_rights_row);
3157 $db_rights[$db_rights_row['User']][$db_rights_row['Host']]
3158 = $db_rights_row;
3160 $GLOBALS['dbi']->freeResult($db_rights_result);
3161 ksort($db_rights);
3163 return $db_rights;
3167 * Delete user and get message and sql query for delete user in privileges
3169 * @param string $queries queries
3171 * @return PMA_message
3173 function PMA_deleteUser($queries)
3175 if (empty($queries)) {
3176 $message = PMA_Message::error(__('No users selected for deleting!'));
3177 } else {
3178 if ($_REQUEST['mode'] == 3) {
3179 $queries[] = '# ' . __('Reloading the privileges') . ' …';
3180 $queries[] = 'FLUSH PRIVILEGES;';
3182 $drop_user_error = '';
3183 foreach ($queries as $sql_query) {
3184 if ($sql_query{0} != '#') {
3185 if (! $GLOBALS['dbi']->tryQuery($sql_query, $GLOBALS['userlink'])) {
3186 $drop_user_error .= $GLOBALS['dbi']->getError() . "\n";
3190 // tracking sets this, causing the deleted db to be shown in navi
3191 unset($GLOBALS['db']);
3193 $sql_query = join("\n", $queries);
3194 if (! empty($drop_user_error)) {
3195 $message = PMA_Message::rawError($drop_user_error);
3196 } else {
3197 $message = PMA_Message::success(
3198 __('The selected users have been deleted successfully.')
3202 return array($sql_query, $message);
3206 * Update the privileges and return the success or error message
3208 * @param string $username username
3209 * @param string $hostname host name
3210 * @param string $tablename table name
3211 * @param string $dbname database name
3213 * @return PMA_message success message or error message for update
3215 function PMA_updatePrivileges($username, $hostname, $tablename, $dbname)
3217 $db_and_table = PMA_wildcardEscapeForGrant($dbname, $tablename);
3219 $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
3220 . ' FROM \'' . PMA_Util::sqlAddSlashes($username)
3221 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
3223 if (! isset($_POST['Grant_priv']) || $_POST['Grant_priv'] != 'Y') {
3224 $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
3225 . ' FROM \'' . PMA_Util::sqlAddSlashes($username) . '\'@\''
3226 . PMA_Util::sqlAddSlashes($hostname) . '\';';
3227 } else {
3228 $sql_query1 = '';
3231 // Should not do a GRANT USAGE for a table-specific privilege, it
3232 // causes problems later (cannot revoke it)
3233 if (! (strlen($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
3234 $sql_query2 = 'GRANT ' . join(', ', PMA_extractPrivInfo())
3235 . ' ON ' . $db_and_table
3236 . ' TO \'' . PMA_Util::sqlAddSlashes($username) . '\'@\''
3237 . PMA_Util::sqlAddSlashes($hostname) . '\'';
3239 if ((isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y')
3240 || (! strlen($dbname)
3241 && (isset($_POST['max_questions']) || isset($_POST['max_connections'])
3242 || isset($_POST['max_updates'])
3243 || isset($_POST['max_user_connections'])))
3245 $sql_query2 .= PMA_getWithClauseForAddUserAndUpdatePrivs();
3247 $sql_query2 .= ';';
3249 if (! $GLOBALS['dbi']->tryQuery($sql_query0)) {
3250 // This might fail when the executing user does not have
3251 // ALL PRIVILEGES himself.
3252 // See https://sourceforge.net/p/phpmyadmin/bugs/3270/
3253 $sql_query0 = '';
3255 if (! empty($sql_query1) && ! $GLOBALS['dbi']->tryQuery($sql_query1)) {
3256 // this one may fail, too...
3257 $sql_query1 = '';
3259 if (! empty($sql_query2)) {
3260 $GLOBALS['dbi']->query($sql_query2);
3261 } else {
3262 $sql_query2 = '';
3264 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
3265 $message = PMA_Message::success(__('You have updated the privileges for %s.'));
3266 $message->addParam(
3267 '\'' . htmlspecialchars($username)
3268 . '\'@\'' . htmlspecialchars($hostname) . '\''
3271 return array($sql_query, $message);
3275 * Get List of information: Changes / copies a user
3277 * @return array()
3279 function PMA_getDataForChangeOrCopyUser()
3281 $row = null;
3282 $queries = null;
3283 $password = null;
3285 if (isset($_REQUEST['change_copy'])) {
3286 $user_host_condition = ' WHERE `User` = '
3287 . "'". PMA_Util::sqlAddSlashes($_REQUEST['old_username']) . "'"
3288 . ' AND `Host` = '
3289 . "'" . PMA_Util::sqlAddSlashes($_REQUEST['old_hostname']) . "';";
3290 $row = $GLOBALS['dbi']->fetchSingleRow(
3291 'SELECT * FROM `mysql`.`user` ' . $user_host_condition
3293 if (! $row) {
3294 $response = PMA_Response::getInstance();
3295 $response->addHTML(
3296 PMA_Message::notice(__('No user found.'))->getDisplay()
3298 unset($_REQUEST['change_copy']);
3299 } else {
3300 extract($row, EXTR_OVERWRITE);
3301 // Recent MySQL versions have the field "Password" in mysql.user,
3302 // so the previous extract creates $Password but this script
3303 // uses $password
3304 if (! isset($password) && isset($Password)) {
3305 $password = $Password;
3307 $queries = array();
3311 return array($queries, $password);
3315 * Update Data for information: Deletes users
3317 * @param array $queries queries array
3319 * @return array
3321 function PMA_getDataForDeleteUsers($queries)
3323 if (isset($_REQUEST['change_copy'])) {
3324 $selected_usr = array(
3325 $_REQUEST['old_username'] . '&amp;#27;' . $_REQUEST['old_hostname']
3327 } else {
3328 $selected_usr = $_REQUEST['selected_usr'];
3329 $queries = array();
3331 foreach ($selected_usr as $each_user) {
3332 list($this_user, $this_host) = explode('&amp;#27;', $each_user);
3333 $queries[] = '# '
3334 . sprintf(
3335 __('Deleting %s'),
3336 '\'' . $this_user . '\'@\'' . $this_host . '\''
3338 . ' ...';
3339 $queries[] = 'DROP USER \''
3340 . PMA_Util::sqlAddSlashes($this_user)
3341 . '\'@\'' . PMA_Util::sqlAddSlashes($this_host) . '\';';
3343 if (isset($_REQUEST['drop_users_db'])) {
3344 $queries[] = 'DROP DATABASE IF EXISTS '
3345 . PMA_Util::backquote($this_user) . ';';
3346 $GLOBALS['reload'] = true;
3349 return $queries;
3353 * update Message For Reload
3355 * @return array
3357 function PMA_updateMessageForReload()
3359 $message = null;
3360 if (isset($_REQUEST['flush_privileges'])) {
3361 $sql_query = 'FLUSH PRIVILEGES;';
3362 $GLOBALS['dbi']->query($sql_query);
3363 $message = PMA_Message::success(
3364 __('The privileges were reloaded successfully.')
3368 if (isset($_REQUEST['validate_username'])) {
3369 $message = PMA_Message::success();
3372 return $message;
3376 * update Data For Queries from queries_for_display
3378 * @param array $queries queries array
3379 * @param array $queries_for_display queries arry for display
3381 * @return null
3383 function PMA_getDataForQueries($queries, $queries_for_display)
3385 $tmp_count = 0;
3386 foreach ($queries as $sql_query) {
3387 if ($sql_query{0} != '#') {
3388 $GLOBALS['dbi']->query($sql_query);
3390 // when there is a query containing a hidden password, take it
3391 // instead of the real query sent
3392 if (isset($queries_for_display[$tmp_count])) {
3393 $queries[$tmp_count] = $queries_for_display[$tmp_count];
3395 $tmp_count++;
3398 return $queries;
3402 * update Data for information: Adds a user
3404 * @param string $dbname db name
3405 * @param string $username user name
3406 * @param string $hostname host name
3407 * @param string $password password
3408 * @param bool $is_menuwork is_menuwork set?
3410 * @return array
3412 function PMA_addUser(
3413 $dbname, $username, $hostname,
3414 $password, $is_menuwork
3416 $_add_user_error = false;
3417 $message = null;
3418 $queries = null;
3419 $queries_for_display = null;
3420 $sql_query = null;
3421 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
3422 $sql_query = '';
3423 if ($_POST['pred_username'] == 'any') {
3424 $username = '';
3426 switch ($_POST['pred_hostname']) {
3427 case 'any':
3428 $hostname = '%';
3429 break;
3430 case 'localhost':
3431 $hostname = 'localhost';
3432 break;
3433 case 'hosttable':
3434 $hostname = '';
3435 break;
3436 case 'thishost':
3437 $_user_name = $GLOBALS['dbi']->fetchValue('SELECT USER()');
3438 $hostname = substr($_user_name, (strrpos($_user_name, '@') + 1));
3439 unset($_user_name);
3440 break;
3442 $sql = "SELECT '1' FROM `mysql`.`user`"
3443 . " WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
3444 . " AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "';";
3445 if ($GLOBALS['dbi']->fetchValue($sql) == 1) {
3446 $message = PMA_Message::error(__('The user %s already exists!'));
3447 $message->addParam(
3448 '[em]\'' . $username . '\'@\'' . $hostname . '\'[/em]'
3450 $_REQUEST['adduser'] = true;
3451 $_add_user_error = true;
3452 } else {
3453 list($create_user_real, $create_user_show, $real_sql_query, $sql_query)
3454 = PMA_getSqlQueriesForDisplayAndAddUser(
3455 $username, $hostname, (isset ($password) ? $password : '')
3458 if (empty($_REQUEST['change_copy'])) {
3459 $_error = false;
3461 if (isset($create_user_real)) {
3462 if (! $GLOBALS['dbi']->tryQuery($create_user_real)) {
3463 $_error = true;
3465 $sql_query = $create_user_show . $sql_query;
3467 list($sql_query, $message) = PMA_addUserAndCreateDatabase(
3468 $_error, $real_sql_query, $sql_query, $username, $hostname,
3469 isset($dbname) ? $dbname : null
3471 if (! empty($_REQUEST['userGroup']) && $is_menuwork) {
3472 PMA_setUserGroup($GLOBALS['username'], $_REQUEST['userGroup']);
3475 } else {
3476 if (isset($create_user_real)) {
3477 $queries[] = $create_user_real;
3479 $queries[] = $real_sql_query;
3480 // we put the query containing the hidden password in
3481 // $queries_for_display, at the same position occupied
3482 // by the real query in $queries
3483 $tmp_count = count($queries);
3484 if (isset($create_user_real)) {
3485 $queries_for_display[$tmp_count - 2] = $create_user_show;
3487 $queries_for_display[$tmp_count - 1] = $sql_query;
3489 unset($res, $real_sql_query);
3493 return array(
3494 $message, $queries, $queries_for_display, $sql_query, $_add_user_error
3499 * Update DB information: DB, Table, isWildcard
3501 * @return array
3503 function PMA_getDataForDBInfo()
3505 $username = null;
3506 $hostname = null;
3507 $dbname = null;
3508 $tablename = null;
3509 $db_and_table = null;
3510 $dbname_is_wildcard = null;
3512 if (isset ($_REQUEST['username'])) {
3513 $username = $_REQUEST['username'];
3515 if (isset ($_REQUEST['hostname'])) {
3516 $hostname = $_REQUEST['hostname'];
3519 * Checks if a dropdown box has been used for selecting a database / table
3521 if (PMA_isValid($_REQUEST['pred_tablename'])) {
3522 $tablename = $_REQUEST['pred_tablename'];
3523 } elseif (PMA_isValid($_REQUEST['tablename'])) {
3524 $tablename = $_REQUEST['tablename'];
3525 } else {
3526 unset($tablename);
3529 if (PMA_isValid($_REQUEST['pred_dbname'])) {
3530 $dbname = $_REQUEST['pred_dbname'];
3531 unset($pred_dbname);
3532 } elseif (PMA_isValid($_REQUEST['dbname'])) {
3533 $dbname = $_REQUEST['dbname'];
3534 } else {
3535 unset($dbname);
3536 unset($tablename);
3539 if (isset($dbname)) {
3540 $unescaped_db = PMA_Util::unescapeMysqlWildcards($dbname);
3541 $db_and_table = PMA_Util::backquote($unescaped_db) . '.';
3542 if (isset($tablename)) {
3543 $db_and_table .= PMA_Util::backquote($tablename);
3544 } else {
3545 $db_and_table .= '*';
3547 } else {
3548 $db_and_table = '*.*';
3551 // check if given $dbname is a wildcard or not
3552 if (isset($dbname)) {
3553 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
3554 if (preg_match('/(?<!\\\\)(?:_|%)/i', $dbname)) {
3555 $dbname_is_wildcard = true;
3556 } else {
3557 $dbname_is_wildcard = false;
3561 return array(
3562 $username, $hostname,
3563 isset($dbname)? $dbname : null,
3564 isset($tablename)? $tablename : null,
3565 $db_and_table,
3566 $dbname_is_wildcard,
3571 * Get title and textarea for export user definition in Privileges
3573 * @param string $username username
3574 * @param string $hostname host name
3576 * @return array ($title, $export)
3578 function PMA_getListForExportUserDefinition($username, $hostname)
3580 $export = '<textarea class="export" cols="' . $GLOBALS['cfg']['TextareaCols']
3581 . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
3583 if (isset($_REQUEST['selected_usr'])) {
3584 // export privileges for selected users
3585 $title = __('Privileges');
3586 foreach ($_REQUEST['selected_usr'] as $export_user) {
3587 $export_username = substr($export_user, 0, strpos($export_user, '&'));
3588 $export_hostname = substr($export_user, strrpos($export_user, ';') + 1);
3589 $export .= '# '
3590 . sprintf(
3591 __('Privileges for %s'),
3592 '`' . htmlspecialchars($export_username)
3593 . '`@`' . htmlspecialchars($export_hostname) . '`'
3595 . "\n\n";
3596 $export .= PMA_getGrants($export_username, $export_hostname) . "\n";
3598 } else {
3599 // export privileges for a single user
3600 $title = __('User') . ' `' . htmlspecialchars($username)
3601 . '`@`' . htmlspecialchars($hostname) . '`';
3602 $export .= PMA_getGrants($username, $hostname);
3604 // remove trailing whitespace
3605 $export = trim($export);
3607 $export .= '</textarea>';
3609 return array($title, $export);
3613 * Get HTML for display Add userfieldset
3615 * @return string html output
3617 function PMA_getAddUserHtmlFieldset()
3619 return '<fieldset id="fieldset_add_user">' . "\n"
3620 . '<a href="server_privileges.php'
3621 . PMA_URL_getCommon(array('adduser' => 1))
3622 . '" class="ajax">' . "\n"
3623 . PMA_Util::getIcon('b_usradd.png')
3624 . ' ' . __('Add user') . '</a>' . "\n"
3625 . '</fieldset>' . "\n";
3629 * Get HTML header for display User's properties
3631 * @param boolean $dbname_is_wildcard whether database name is wildcard or not
3632 * @param string $url_dbname url database name that urlencode() string
3633 * @param string $dbname database name
3634 * @param string $username username
3635 * @param string $hostname host name
3636 * @param string $tablename table name
3638 * @return string $html_output
3640 function PMA_getHtmlHeaderForDisplayUserProperties(
3641 $dbname_is_wildcard, $url_dbname, $dbname, $username, $hostname, $tablename
3643 $html_output = '<h2>' . "\n"
3644 . PMA_Util::getIcon('b_usredit.png')
3645 . __('Edit Privileges:') . ' '
3646 . __('User');
3648 if (! empty($dbname)) {
3649 $html_output .= ' <i><a href="server_privileges.php'
3650 . PMA_URL_getCommon(
3651 array(
3652 'username' => $username,
3653 'hostname' => $hostname,
3654 'dbname' => '',
3655 'tablename' => '',
3658 . '">\'' . htmlspecialchars($username)
3659 . '\'@\'' . htmlspecialchars($hostname)
3660 . '\'</a></i>' . "\n";
3662 $html_output .= ' - ';
3663 $html_output .= $dbname_is_wildcard ? __('Databases') : __('Database');
3664 if (! empty($_REQUEST['tablename'])) {
3665 $html_output .= ' <i><a href="server_privileges.php'
3666 . PMA_URL_getCommon(
3667 array(
3668 'username' => $username,
3669 'hostname' => $hostname,
3670 'dbname' => $url_dbname,
3671 'tablename' => '',
3674 . '">' . htmlspecialchars($dbname)
3675 . '</a></i>';
3677 $html_output .= ' - ' . __('Table')
3678 . ' <i>' . htmlspecialchars($tablename) . '</i>';
3679 } else {
3680 $html_output .= ' <i>' . htmlspecialchars($dbname) . '</i>';
3683 } else {
3684 $html_output .= ' <i>\'' . htmlspecialchars($username)
3685 . '\'@\'' . htmlspecialchars($hostname)
3686 . '\'</i>' . "\n";
3689 $html_output .= '</h2>' . "\n";
3691 return $html_output;
3695 * Get HTML snippet for display user overview page
3697 * @param string $pmaThemeImage a image source link
3698 * @param string $text_dir text directory
3700 * @return string $html_output
3702 function PMA_getHtmlForDisplayUserOverviewPage($pmaThemeImage, $text_dir)
3704 $html_output = '<h2>' . "\n"
3705 . PMA_Util::getIcon('b_usrlist.png')
3706 . __('Users overview') . "\n"
3707 . '</h2>' . "\n";
3709 $sql_query = 'SELECT *,' .
3710 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
3711 ' FROM `mysql`.`user`';
3713 $sql_query .= (isset($_REQUEST['initial'])
3714 ? PMA_rangeOfUsers($_REQUEST['initial'])
3715 : '');
3717 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
3718 $res = $GLOBALS['dbi']->tryQuery(
3719 $sql_query, null, PMA_DatabaseInterface::QUERY_STORE
3722 if (! $res) {
3723 // the query failed! This may have two reasons:
3724 // - the user does not have enough privileges
3725 // - the privilege tables use a structure of an earlier version.
3726 // so let's try a more simple query
3728 $sql_query = 'SELECT * FROM `mysql`.`user`';
3729 $res = $GLOBALS['dbi']->tryQuery(
3730 $sql_query, null, PMA_DatabaseInterface::QUERY_STORE
3733 if (! $res) {
3734 $html_output .= PMA_Message::error(__('No Privileges'))->getDisplay();
3735 $GLOBALS['dbi']->freeResult($res);
3736 unset($res);
3737 } else {
3738 // This message is hardcoded because I will replace it by
3739 // a automatic repair feature soon.
3740 $raw = 'Your privilege table structure seems to be older than'
3741 . ' this MySQL version!<br />'
3742 . 'Please run the <code>mysql_upgrade</code> command'
3743 . '(<code>mysql_fix_privilege_tables</code> on older systems)'
3744 . ' that should be included in your MySQL server distribution'
3745 . ' to solve this problem!';
3746 $html_output .= PMA_Message::rawError($raw)->getDisplay();
3748 } else {
3749 $db_rights = PMA_getDbRightsForUserOverview();
3750 // for all initials, even non A-Z
3751 $array_initials = array();
3754 * Displays the initials
3755 * Also not necassary if there is less than 20 privileges
3757 if ($GLOBALS['dbi']->numRows($res) > 20 ) {
3758 $html_output .= PMA_getHtmlForDisplayTheInitials($array_initials);
3762 * Display the user overview
3763 * (if less than 50 users, display them immediately)
3765 if (isset($_REQUEST['initial'])
3766 || isset($_REQUEST['showall'])
3767 || $GLOBALS['dbi']->numRows($res) < 50
3769 $html_output .= PMA_getUsersOverview(
3770 $res, $db_rights, $pmaThemeImage, $text_dir
3772 } else {
3773 $html_output .= PMA_getAddUserHtmlFieldset();
3774 } // end if (display overview)
3776 if (! $GLOBALS['is_ajax_request']
3777 || ! empty($_REQUEST['ajax_page_request'])
3779 $flushnote = new PMA_Message(
3781 'Note: phpMyAdmin gets the users\' privileges directly '
3782 . 'from MySQL\'s privilege tables. The content of these tables '
3783 . 'may differ from the privileges the server uses, '
3784 . 'if they have been changed manually. In this case, '
3785 . 'you should %sreload the privileges%s before you continue.'
3787 PMA_Message::NOTICE
3789 $flushLink = '<a href="server_privileges.php'
3790 . PMA_URL_getCommon(array('flush_privileges' => 1))
3791 . '" id="reload_privileges_anchor">';
3792 $flushnote->addParam(
3793 $flushLink,
3794 false
3796 $flushnote->addParam('</a>', false);
3797 $html_output .= $flushnote->getDisplay();
3801 return $html_output;
3805 * Get HTML snippet for display user properties
3807 * @param boolean $dbname_is_wildcard whether database name is wildcard or not
3808 * @param type $url_dbname url database name that urlencode() string
3809 * @param string $username username
3810 * @param string $hostname host name
3811 * @param string $dbname database name
3812 * @param string $tablename table name
3814 * @return string $html_output
3816 function PMA_getHtmlForDisplayUserProperties($dbname_is_wildcard,$url_dbname,
3817 $username, $hostname, $dbname, $tablename
3819 $html_output = PMA_getHtmlHeaderForDisplayUserProperties(
3820 $dbname_is_wildcard, $url_dbname, $dbname, $username, $hostname, $tablename
3823 $sql = "SELECT '1' FROM `mysql`.`user`"
3824 . " WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
3825 . " AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "';";
3827 $user_does_not_exists = (bool) ! $GLOBALS['dbi']->fetchValue($sql);
3829 if ($user_does_not_exists) {
3830 $html_output .= PMA_Message::error(
3831 __('The selected user was not found in the privilege table.')
3832 )->getDisplay();
3833 $html_output .= PMA_getHtmlForDisplayLoginInformationFields();
3834 //exit;
3837 $class = ' class="ajax"';
3838 $_params = array(
3839 'username' => $username,
3840 'hostname' => $hostname,
3842 if (strlen($dbname)) {
3843 $_params['dbname'] = $dbname;
3844 if (strlen($tablename)) {
3845 $_params['tablename'] = $tablename;
3849 $html_output .= '<form' . $class . ' name="usersForm" id="addUsersForm"'
3850 . ' action="server_privileges.php" method="post">' . "\n";
3851 $html_output .= PMA_URL_getHiddenInputs($_params);
3852 $html_output .= PMA_getHtmlToDisplayPrivilegesTable(
3853 PMA_ifSetOr($dbname, '*', 'length'),
3854 PMA_ifSetOr($tablename, '*', 'length')
3857 $html_output .= '</form>' . "\n";
3859 if (! strlen($tablename) && empty($dbname_is_wildcard)) {
3861 // no table name was given, display all table specific rights
3862 // but only if $dbname contains no wildcards
3864 $html_output .= '<form action="server_privileges.php" '
3865 . 'id="db_or_table_specific_priv" method="post">' . "\n";
3867 // unescape wildcards in dbname at table level
3868 $unescaped_db = PMA_Util::unescapeMysqlWildcards($dbname);
3869 list($html_rightsTable, $found_rows)
3870 = PMA_getTableForDisplayAllTableSpecificRights(
3871 $username, $hostname, $unescaped_db
3873 $html_output .= $html_rightsTable;
3875 if (! strlen($dbname)) {
3876 // no database name was given, display select db
3877 $html_output .= PMA_getHtmlForDisplaySelectDbInEditPrivs($found_rows);
3879 } else {
3880 $html_output .= PMA_displayTablesInEditPrivs($dbname, $found_rows);
3882 $html_output .= '</fieldset>' . "\n";
3884 $html_output .= '<fieldset class="tblFooters">' . "\n"
3885 . ' <input type="submit" value="' . __('Go') . '" />'
3886 . '</fieldset>' . "\n"
3887 . '</form>' . "\n";
3890 // Provide a line with links to the relevant database and table
3891 if (strlen($dbname) && empty($dbname_is_wildcard)) {
3892 $html_output .= PMA_getLinkToDbAndTable($url_dbname, $dbname, $tablename);
3896 if (! strlen($dbname) && ! $user_does_not_exists) {
3897 //change login information
3898 $html_output .= PMA_getHtmlForChangePassword($username, $hostname);
3899 $html_output .= PMA_getChangeLoginInformationHtmlForm($username, $hostname);
3902 return $html_output;
3906 * Get queries for Table privileges to change or copy user
3908 * @param string $user_host_condition user host condition to
3909 select relevent table privileges
3910 * @param array $queries queries array
3911 * @param string $username username
3912 * @param string $hostname host name
3914 * @return array $queries
3916 function PMA_getTablePrivsQueriesForChangeOrCopyUser($user_host_condition,
3917 $queries, $username, $hostname
3919 $res = $GLOBALS['dbi']->query(
3920 'SELECT `Db`, `Table_name`, `Table_priv` FROM `mysql`.`tables_priv`'
3921 . $user_host_condition,
3922 $GLOBALS['userlink'],
3923 PMA_DatabaseInterface::QUERY_STORE
3925 while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
3927 $res2 = $GLOBALS['dbi']->query(
3928 'SELECT `Column_name`, `Column_priv`'
3929 .' FROM `mysql`.`columns_priv`'
3930 .' WHERE `User`'
3931 .' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_username']) . "'"
3932 .' AND `Host`'
3933 .' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_username']) . '\''
3934 .' AND `Db`'
3935 .' = \'' . PMA_Util::sqlAddSlashes($row['Db']) . "'"
3936 .' AND `Table_name`'
3937 .' = \'' . PMA_Util::sqlAddSlashes($row['Table_name']) . "'"
3938 .';',
3939 null,
3940 PMA_DatabaseInterface::QUERY_STORE
3943 $tmp_privs1 = PMA_extractPrivInfo($row);
3944 $tmp_privs2 = array(
3945 'Select' => array(),
3946 'Insert' => array(),
3947 'Update' => array(),
3948 'References' => array()
3951 while ($row2 = $GLOBALS['dbi']->fetchAssoc($res2)) {
3952 $tmp_array = explode(',', $row2['Column_priv']);
3953 if (in_array('Select', $tmp_array)) {
3954 $tmp_privs2['Select'][] = $row2['Column_name'];
3956 if (in_array('Insert', $tmp_array)) {
3957 $tmp_privs2['Insert'][] = $row2['Column_name'];
3959 if (in_array('Update', $tmp_array)) {
3960 $tmp_privs2['Update'][] = $row2['Column_name'];
3962 if (in_array('References', $tmp_array)) {
3963 $tmp_privs2['References'][] = $row2['Column_name'];
3966 if (count($tmp_privs2['Select']) > 0 && ! in_array('SELECT', $tmp_privs1)) {
3967 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
3969 if (count($tmp_privs2['Insert']) > 0 && ! in_array('INSERT', $tmp_privs1)) {
3970 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
3972 if (count($tmp_privs2['Update']) > 0 && ! in_array('UPDATE', $tmp_privs1)) {
3973 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
3975 if (count($tmp_privs2['References']) > 0
3976 && ! in_array('REFERENCES', $tmp_privs1)
3978 $tmp_privs1[]
3979 = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
3982 $queries[] = 'GRANT ' . join(', ', $tmp_privs1)
3983 . ' ON ' . PMA_Util::backquote($row['Db']) . '.'
3984 . PMA_Util::backquote($row['Table_name'])
3985 . ' TO \'' . PMA_Util::sqlAddSlashes($username)
3986 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\''
3987 . (in_array('Grant', explode(',', $row['Table_priv']))
3988 ? ' WITH GRANT OPTION;'
3989 : ';');
3991 return $queries;
3995 * Get queries for database specific privileges for change or copy user
3997 * @param array $queries queries array with string
3998 * @param string $username username
3999 * @param string $hostname host name
4001 * @return array $queries
4003 function PMA_getDbSpecificPrivsQueriesForChangeOrCopyUser(
4004 $queries, $username, $hostname
4006 $user_host_condition = ' WHERE `User`'
4007 .' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_username']) . "'"
4008 .' AND `Host`'
4009 .' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_hostname']) . '\';';
4011 $res = $GLOBALS['dbi']->query(
4012 'SELECT * FROM `mysql`.`db`' . $user_host_condition
4015 while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
4016 $queries[] = 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
4017 .' ON ' . PMA_Util::backquote($row['Db']) . '.*'
4018 .' TO \'' . PMA_Util::sqlAddSlashes($username)
4019 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\''
4020 . ($row['Grant_priv'] == 'Y' ? ' WITH GRANT OPTION;' : ';');
4022 $GLOBALS['dbi']->freeResult($res);
4024 $queries = PMA_getTablePrivsQueriesForChangeOrCopyUser(
4025 $user_host_condition, $queries, $username, $hostname
4028 return $queries;
4032 * Prepares queries for adding users and
4033 * also create database and return query and message
4035 * @param boolean $_error whether user create or not
4036 * @param string $real_sql_query SQL query for add a user
4037 * @param string $sql_query SQL query to be displayed
4038 * @param string $username username
4039 * @param string $hostname host name
4040 * @param string $dbname database name
4042 * @return array $sql_query, $message
4044 function PMA_addUserAndCreateDatabase($_error, $real_sql_query, $sql_query,
4045 $username, $hostname, $dbname
4047 if ($_error || ! $GLOBALS['dbi']->tryQuery($real_sql_query)) {
4048 $_REQUEST['createdb-1'] = $_REQUEST['createdb-2']
4049 = $_REQUEST['createdb-3'] = false;
4050 $message = PMA_Message::rawError($GLOBALS['dbi']->getError());
4051 } else {
4052 $message = PMA_Message::success(__('You have added a new user.'));
4055 if (isset($_REQUEST['createdb-1'])) {
4056 // Create database with same name and grant all privileges
4057 $q = 'CREATE DATABASE IF NOT EXISTS '
4058 . PMA_Util::backquote(
4059 PMA_Util::sqlAddSlashes($username)
4060 ) . ';';
4061 $sql_query .= $q;
4062 if (! $GLOBALS['dbi']->tryQuery($q)) {
4063 $message = PMA_Message::rawError($GLOBALS['dbi']->getError());
4067 * Reload the navigation
4069 $GLOBALS['reload'] = true;
4070 $GLOBALS['db'] = $username;
4072 $q = 'GRANT ALL PRIVILEGES ON '
4073 . PMA_Util::backquote(
4074 PMA_Util::escapeMysqlWildcards(
4075 PMA_Util::sqlAddSlashes($username)
4077 ) . '.* TO \''
4078 . PMA_Util::sqlAddSlashes($username)
4079 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
4080 $sql_query .= $q;
4081 if (! $GLOBALS['dbi']->tryQuery($q)) {
4082 $message = PMA_Message::rawError($GLOBALS['dbi']->getError());
4086 if (isset($_REQUEST['createdb-2'])) {
4087 // Grant all privileges on wildcard name (username\_%)
4088 $q = 'GRANT ALL PRIVILEGES ON '
4089 . PMA_Util::backquote(
4090 PMA_Util::sqlAddSlashes($username) . '\_%'
4091 ) . '.* TO \''
4092 . PMA_Util::sqlAddSlashes($username)
4093 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
4094 $sql_query .= $q;
4095 if (! $GLOBALS['dbi']->tryQuery($q)) {
4096 $message = PMA_Message::rawError($GLOBALS['dbi']->getError());
4100 if (isset($_REQUEST['createdb-3'])) {
4101 // Grant all privileges on the specified database to the new user
4102 $q = 'GRANT ALL PRIVILEGES ON '
4103 . PMA_Util::backquote(
4104 PMA_Util::sqlAddSlashes($dbname)
4105 ) . '.* TO \''
4106 . PMA_Util::sqlAddSlashes($username)
4107 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
4108 $sql_query .= $q;
4109 if (! $GLOBALS['dbi']->tryQuery($q)) {
4110 $message = PMA_Message::rawError($GLOBALS['dbi']->getError());
4113 return array($sql_query, $message);
4117 * Get SQL queries for Display and Add user
4119 * @param string $username usernam
4120 * @param string $hostname host name
4121 * @param string $password password
4123 * @return array ($create_user_real, $create_user_show,$real_sql_query, $sql_query)
4125 function PMA_getSqlQueriesForDisplayAndAddUser($username, $hostname, $password)
4127 $sql_query = '';
4128 $create_user_real = 'CREATE USER \''
4129 . PMA_Util::sqlAddSlashes($username) . '\'@\''
4130 . PMA_Util::sqlAddSlashes($hostname) . '\'';
4132 $real_sql_query = 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
4133 . PMA_Util::sqlAddSlashes($username) . '\'@\''
4134 . PMA_Util::sqlAddSlashes($hostname) . '\'';
4136 if ($_POST['pred_password'] != 'none' && $_POST['pred_password'] != 'keep') {
4137 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
4138 $real_sql_query .= ' IDENTIFIED BY \''
4139 . PMA_Util::sqlAddSlashes($_POST['pma_pw']) . '\'';
4140 if (isset($create_user_real)) {
4141 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
4142 $create_user_real .= ' IDENTIFIED BY \''
4143 . PMA_Util::sqlAddSlashes($_POST['pma_pw']) . '\'';
4145 } else {
4146 if ($_POST['pred_password'] == 'keep' && ! empty($password)) {
4147 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
4148 if (isset($create_user_real)) {
4149 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
4152 $sql_query = $real_sql_query;
4153 if (isset($create_user_real)) {
4154 $create_user_show = $create_user_real;
4158 if ((isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y')
4159 || (isset($_POST['max_questions']) || isset($_POST['max_connections'])
4160 || isset($_POST['max_updates']) || isset($_POST['max_user_connections']))
4162 $with_clause = PMA_getWithClauseForAddUserAndUpdatePrivs();
4163 $real_sql_query .= ' ' . $with_clause;
4164 $sql_query .= ' ' . $with_clause;
4167 if (isset($create_user_real)) {
4168 $create_user_real .= ';';
4169 $create_user_show .= ';';
4171 $real_sql_query .= ';';
4172 $sql_query .= ';';
4174 return array($create_user_real,
4175 $create_user_show,
4176 $real_sql_query,
4177 $sql_query