Upgraded phpmyadmin to 4.0.4 (All Languages) - No modifications yet
[openemr.git] / phpmyadmin / libraries / server_privileges.lib.php
blob44e16d37b26d941ce07dd923efffca40ad992dda
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;
12 /**
13 * Escapes wildcard in a database+table specification
14 * before using it in a GRANT statement.
16 * Escaping a wildcard character in a GRANT is only accepted at the global
17 * or database level, not at table level; this is why I remove
18 * the escaping character. Internally, in mysql.tables_priv.Db there are
19 * no escaping (for example test_db) but in mysql.db you'll see test\_db
20 * for a db-specific privilege.
22 * @param string $dbname Database name
23 * @param string $tablename Table name
25 * @return string the escaped (if necessary) database.table
27 function PMA_wildcardEscapeForGrant($dbname, $tablename)
29 if (! strlen($dbname)) {
30 $db_and_table = '*.*';
31 } else {
32 if (strlen($tablename)) {
33 $db_and_table = PMA_Util::backquote(
34 PMA_Util::unescapeMysqlWildcards($dbname)
36 . '.' . PMA_Util::backquote($tablename);
37 } else {
38 $db_and_table = PMA_Util::backquote($dbname) . '.*';
41 return $db_and_table;
44 /**
45 * Generates a condition on the user name
47 * @param string $initial the user's initial
49 * @return string the generated condition
51 function PMA_rangeOfUsers($initial = '')
53 // strtolower() is used because the User field
54 // might be BINARY, so LIKE would be case sensitive
55 if (! empty($initial)) {
56 $ret = " WHERE `User` LIKE '"
57 . PMA_Util::sqlAddSlashes($initial, true) . "%'"
58 . " OR `User` LIKE '"
59 . PMA_Util::sqlAddSlashes(strtolower($initial), true) . "%'";
60 } else {
61 $ret = '';
63 return $ret;
64 } // end function
66 /**
67 * Extracts the privilege information of a priv table row
69 * @param array $row the row
70 * @param boolean $enableHTML add <dfn> tag with tooltips
72 * @global resource $user_link the database connection
74 * @return array
76 function PMA_extractPrivInfo($row = '', $enableHTML = false)
78 $grants = PMA_getGrantsArray();
80 if (! empty($row) && isset($row['Table_priv'])) {
81 $row1 = PMA_DBI_fetch_single_row(
82 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
83 'ASSOC', $GLOBALS['userlink']
85 $av_grants = explode(
86 '\',\'',
87 substr($row1['Type'], 5, strlen($row1['Type']) - 7)
89 unset($row1);
90 $users_grants = explode(',', $row['Table_priv']);
91 foreach ($av_grants as $current_grant) {
92 $row[$current_grant . '_priv']
93 = in_array($current_grant, $users_grants) ? 'Y' : 'N';
95 unset($current_grant);
98 $privs = array();
99 $allPrivileges = true;
100 foreach ($grants as $current_grant) {
101 if ((! empty($row) && isset($row[$current_grant[0]]))
102 || (empty($row) && isset($GLOBALS[$current_grant[0]]))
104 if ((! empty($row) && $row[$current_grant[0]] == 'Y')
105 || (empty($row)
106 && ($GLOBALS[$current_grant[0]] == 'Y'
107 || (is_array($GLOBALS[$current_grant[0]])
108 && count($GLOBALS[$current_grant[0]]) == $_REQUEST['column_count']
109 && empty($GLOBALS[$current_grant[0] . '_none']))))
111 if ($enableHTML) {
112 $privs[] = '<dfn title="' . $current_grant[2] . '">'
113 . $current_grant[1] . '</dfn>';
114 } else {
115 $privs[] = $current_grant[1];
117 } elseif (! empty($GLOBALS[$current_grant[0]])
118 && is_array($GLOBALS[$current_grant[0]])
119 && empty($GLOBALS[$current_grant[0] . '_none'])) {
120 if ($enableHTML) {
121 $priv_string = '<dfn title="' . $current_grant[2] . '">'
122 . $current_grant[1] . '</dfn>';
123 } else {
124 $priv_string = $current_grant[1];
126 $privs[] = $priv_string . ' (`'
127 . join('`, `', $GLOBALS[$current_grant[0]]) . '`)';
128 } else {
129 $allPrivileges = false;
133 if (empty($privs)) {
134 if ($enableHTML) {
135 $privs[] = '<dfn title="' . __('No privileges.') . '">USAGE</dfn>';
136 } else {
137 $privs[] = 'USAGE';
139 } elseif ($allPrivileges
140 && (! isset($_POST['grant_count'])
141 || count($privs) == $_POST['grant_count'])
143 if ($enableHTML) {
144 $privs = array('<dfn title="'
145 . __('Includes all privileges except GRANT.')
146 . '">ALL PRIVILEGES</dfn>'
148 } else {
149 $privs = array('ALL PRIVILEGES');
152 return $privs;
153 } // end of the 'PMA_extractPrivInfo()' function
156 * Get the grants array which contains all the privilege types
157 * and relevent grant messages
159 * @return array
161 function PMA_getGrantsArray()
163 return array(
164 array(
165 'Select_priv',
166 'SELECT',
167 __('Allows reading data.')),
168 array(
169 'Insert_priv',
170 'INSERT',
171 __('Allows inserting and replacing data.')),
172 array(
173 'Update_priv',
174 'UPDATE',
175 __('Allows changing data.')),
176 array(
177 'Delete_priv',
178 'DELETE',
179 __('Allows deleting data.')),
180 array(
181 'Create_priv',
182 'CREATE',
183 __('Allows creating new databases and tables.')),
184 array(
185 'Drop_priv',
186 'DROP',
187 __('Allows dropping databases and tables.')),
188 array(
189 'Reload_priv',
190 'RELOAD',
191 __('Allows reloading server settings and flushing the server\'s caches.')),
192 array(
193 'Shutdown_priv',
194 'SHUTDOWN',
195 __('Allows shutting down the server.')),
196 array(
197 'Process_priv',
198 'PROCESS',
199 __('Allows viewing processes of all users')),
200 array(
201 'File_priv',
202 'FILE',
203 __('Allows importing data from and exporting data into files.')),
204 array(
205 'References_priv',
206 'REFERENCES',
207 __('Has no effect in this MySQL version.')),
208 array(
209 'Index_priv',
210 'INDEX',
211 __('Allows creating and dropping indexes.')),
212 array(
213 'Alter_priv',
214 'ALTER',
215 __('Allows altering the structure of existing tables.')),
216 array(
217 'Show_db_priv',
218 'SHOW DATABASES',
219 __('Gives access to the complete list of databases.')),
220 array(
221 'Super_priv',
222 'SUPER',
223 __('Allows connecting, even if maximum number of connections is reached; required for most administrative operations like setting global variables or killing threads of other users.')),
224 array(
225 'Create_tmp_table_priv',
226 'CREATE TEMPORARY TABLES',
227 __('Allows creating temporary tables.')),
228 array(
229 'Lock_tables_priv',
230 'LOCK TABLES',
231 __('Allows locking tables for the current thread.')),
232 array(
233 'Repl_slave_priv',
234 'REPLICATION SLAVE',
235 __('Needed for the replication slaves.')),
236 array(
237 'Repl_client_priv',
238 'REPLICATION CLIENT',
239 __('Allows the user to ask where the slaves / masters are.')),
240 array(
241 'Create_view_priv',
242 'CREATE VIEW',
243 __('Allows creating new views.')),
244 array(
245 'Event_priv',
246 'EVENT',
247 __('Allows to set up events for the event scheduler')),
248 array(
249 'Trigger_priv',
250 'TRIGGER',
251 __('Allows creating and dropping triggers')),
252 // for table privs:
253 array(
254 'Create View_priv',
255 'CREATE VIEW',
256 __('Allows creating new views.')),
257 array(
258 'Show_view_priv',
259 'SHOW VIEW',
260 __('Allows performing SHOW CREATE VIEW queries.')),
261 // for table privs:
262 array(
263 'Show view_priv',
264 'SHOW VIEW',
265 __('Allows performing SHOW CREATE VIEW queries.')),
266 array(
267 'Create_routine_priv',
268 'CREATE ROUTINE',
269 __('Allows creating stored routines.')),
270 array(
271 'Alter_routine_priv',
272 'ALTER ROUTINE',
273 __('Allows altering and dropping stored routines.')),
274 array(
275 'Create_user_priv',
276 'CREATE USER',
277 __('Allows creating, dropping and renaming user accounts.')),
278 array(
279 'Execute_priv',
280 'EXECUTE',
281 __('Allows executing stored routines.')),
286 * Displays on which column(s) a table-specific privilege is granted
288 * @param array $columns columns array
289 * @param array $row first row from result or boolean false
290 * @param string $name_for_select privilege types - Select_priv, Insert_priv
291 * Update_priv, References_priv
292 * @param string $priv_for_header privilege for header
293 * @param string $name privilege name: insert, select, update, references
294 * @param string $name_for_dfn name for dfn
295 * @param string $name_for_current name for current
297 * @return $html_output html snippet
299 function PMA_getHtmlForDisplayColumnPrivileges($columns, $row, $name_for_select,
300 $priv_for_header, $name, $name_for_dfn, $name_for_current
302 $html_output = '<div class="item" id="div_item_' . $name . '">' . "\n"
303 . '<label for="select_' . $name . '_priv">' . "\n"
304 . '<code><dfn title="' . $name_for_dfn . '">'
305 . $priv_for_header . '</dfn></code>' . "\n"
306 . '</label><br />' . "\n"
307 . '<select id="select_' . $name . '_priv" name="'
308 . $name_for_select . '[]" multiple="multiple" size="8">' . "\n";
310 foreach ($columns as $current_column => $current_column_privileges) {
311 $html_output .= '<option '
312 . 'value="' . htmlspecialchars($current_column) . '"';
313 if ($row[$name_for_select] == 'Y'
314 || $current_column_privileges[$name_for_current]
316 $html_output .= ' selected="selected"';
318 $html_output .= '>'
319 . htmlspecialchars($current_column) . '</option>' . "\n";
322 $html_output .= '</select>' . "\n"
323 . '<i>' . __('Or') . '</i>' . "\n"
324 . '<label for="checkbox_' . $name_for_select
325 . '_none"><input type="checkbox"'
326 . ' name="' . $name_for_select . '_none" id="checkbox_'
327 . $name_for_select . '_none" title="'
328 . _pgettext('None privileges', 'None') . '" />'
329 . _pgettext('None privileges', 'None') . '</label>' . "\n"
330 . '</div>' . "\n";
331 return $html_output;
332 } // end function
335 * Get sql query for display privileges table
337 * @param string $db the database
338 * @param string $table the table
339 * @param string $username username for database connection
340 * @param string $hostname hostname for database connection
342 * @return string sql query
344 function PMA_getSqlQueryForDisplayPrivTable($db, $table, $username, $hostname)
346 if ($db == '*') {
347 return "SELECT * FROM `mysql`.`user`"
348 ." WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
349 ." AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "';";
350 } elseif ($table == '*') {
351 return "SELECT * FROM `mysql`.`db`"
352 ." WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
353 ." AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "'"
354 ." AND '" . PMA_Util::unescapeMysqlWildcards($db) . "'"
355 ." LIKE `Db`;";
357 return "SELECT `Table_priv`"
358 ." FROM `mysql`.`tables_priv`"
359 ." WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
360 ." AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "'"
361 ." AND `Db` = '" . PMA_Util::unescapeMysqlWildcards($db) . "'"
362 ." AND `Table_name` = '" . PMA_Util::sqlAddSlashes($table) . "';";
365 * Displays the privileges form table
367 * @param string $db the database
368 * @param string $table the table
369 * @param boolean $submit wheather to display the submit button or not
371 * @global array $cfg the phpMyAdmin configuration
372 * @global ressource $user_link the database connection
374 * @return string html snippet
376 function PMA_getHtmlToDisplayPrivilegesTable($db = '*',
377 $table = '*', $submit = true
379 $html_output = '';
381 if ($db == '*') {
382 $table = '*';
385 if (isset($GLOBALS['username'])) {
386 $username = $GLOBALS['username'];
387 $hostname = $GLOBALS['hostname'];
388 $sql_query = PMA_getSqlQueryForDisplayPrivTable(
389 $db, $table, $username, $hostname
391 $row = PMA_DBI_fetch_single_row($sql_query);
393 if (empty($row)) {
394 if ($table == '*') {
395 if ($db == '*') {
396 $sql_query = 'SHOW COLUMNS FROM `mysql`.`user`;';
397 } elseif ($table == '*') {
398 $sql_query = 'SHOW COLUMNS FROM `mysql`.`db`;';
400 $res = PMA_DBI_query($sql_query);
401 while ($row1 = PMA_DBI_fetch_row($res)) {
402 if (substr($row1[0], 0, 4) == 'max_') {
403 $row[$row1[0]] = 0;
404 } else {
405 $row[$row1[0]] = 'N';
408 PMA_DBI_free_result($res);
409 } else {
410 $row = array('Table_priv' => '');
413 if (isset($row['Table_priv'])) {
414 $row1 = PMA_DBI_fetch_single_row(
415 'SHOW COLUMNS FROM `mysql`.`tables_priv` LIKE \'Table_priv\';',
416 'ASSOC', $GLOBALS['userlink']
418 // note: in MySQL 5.0.3 we get "Create View', 'Show view';
419 // the View for Create is spelled with uppercase V
420 // the view for Show is spelled with lowercase v
421 // and there is a space between the words
423 $av_grants = explode(
424 '\',\'',
425 substr(
426 $row1['Type'],
427 strpos($row1['Type'], '(') + 2,
428 strpos($row1['Type'], ')') - strpos($row1['Type'], '(') - 3
431 unset($row1);
432 $users_grants = explode(',', $row['Table_priv']);
434 foreach ($av_grants as $current_grant) {
435 $row[$current_grant . '_priv']
436 = in_array($current_grant, $users_grants) ? 'Y' : 'N';
438 unset($row['Table_priv'], $current_grant, $av_grants, $users_grants);
440 // get columns
441 $res = PMA_DBI_try_query(
442 'SHOW COLUMNS FROM '
443 . PMA_Util::backquote(
444 PMA_Util::unescapeMysqlWildcards($db)
446 . '.' . PMA_Util::backquote($table) . ';'
448 $columns = array();
449 if ($res) {
450 while ($row1 = PMA_DBI_fetch_row($res)) {
451 $columns[$row1[0]] = array(
452 'Select' => false,
453 'Insert' => false,
454 'Update' => false,
455 'References' => false
458 PMA_DBI_free_result($res);
460 unset($res, $row1);
462 // t a b l e - s p e c i f i c p r i v i l e g e s
463 if (! empty($columns)) {
464 $html_output .= PMA_getHtmlForTableSpecificPrivileges(
465 $username, $hostname, $db, $table, $columns, $row
467 } else {
468 // g l o b a l o r d b - s p e c i f i c
469 $html_output .= PMA_getHtmlForGlobalOrDbSpecificPrivs($db, $table, $row);
471 $html_output .= '</fieldset>' . "\n";
472 if ($submit) {
473 $html_output .= '<fieldset id="fieldset_user_privtable_footer" '
474 . 'class="tblFooters">' . "\n"
475 . '<input type="submit" name="update_privs" '
476 . 'value="' . __('Go') . '" />' . "\n"
477 . '</fieldset>' . "\n";
479 return $html_output;
480 } // end of the 'PMA_displayPrivTable()' function
483 * Get HTML for "Resource limits"
485 * @param array $row first row from result or boolean false
487 * @return string html snippet
489 function PMA_getHtmlForDisplayResourceLimits($row)
491 $html_output = '<fieldset>' . "\n"
492 . '<legend>' . __('Resource limits') . '</legend>' . "\n"
493 . '<p><small>'
494 . '<i>' . __('Note: Setting these options to 0 (zero) removes the limit.')
495 . '</i></small></p>' . "\n";
497 $html_output .= '<div class="item">' . "\n"
498 . '<label for="text_max_questions">'
499 . '<code><dfn title="'
500 . __('Limits the number of queries the user may send to the server per hour.')
501 . '">'
502 . 'MAX QUERIES PER HOUR'
503 . '</dfn></code></label>' . "\n"
504 . '<input type="text" name="max_questions" id="text_max_questions" '
505 . 'value="' . $row['max_questions'] . '" '
506 . 'size="11" maxlength="11" '
507 . 'title="'
508 . __('Limits the number of queries the user may send to the server per hour.')
509 . '" />' . "\n"
510 . '</div>' . "\n";
512 $html_output .= '<div class="item">' . "\n"
513 . '<label for="text_max_updates">'
514 . '<code><dfn title="'
515 . __('Limits the number of commands that change any table or database the user may execute per hour.') . '">'
516 . 'MAX UPDATES PER HOUR'
517 . '</dfn></code></label>' . "\n"
518 . '<input type="text" name="max_updates" id="text_max_updates" '
519 . 'value="' . $row['max_updates'] . '" size="11" maxlength="11" '
520 . 'title="'
521 . __('Limits the number of commands that change any table or database the user may execute per hour.')
522 . '" />' . "\n"
523 . '</div>' . "\n";
525 $html_output .= '<div class="item">' . "\n"
526 . '<label for="text_max_connections">'
527 . '<code><dfn title="'
528 . __('Limits the number of new connections the user may open per hour.') . '">'
529 . 'MAX CONNECTIONS PER HOUR'
530 . '</dfn></code></label>' . "\n"
531 . '<input type="text" name="max_connections" id="text_max_connections" '
532 . 'value="' . $row['max_connections'] . '" size="11" maxlength="11" '
533 . 'title="' . __('Limits the number of new connections the user may open per hour.')
534 . '" />' . "\n"
535 . '</div>' . "\n";
537 $html_output .= '<div class="item">' . "\n"
538 . '<label for="text_max_user_connections">'
539 . '<code><dfn title="'
540 . __('Limits the number of simultaneous connections the user may have.')
541 . '">'
542 . 'MAX USER_CONNECTIONS'
543 . '</dfn></code></label>' . "\n"
544 . '<input type="text" name="max_user_connections" '
545 . 'id="text_max_user_connections" '
546 . 'value="' . $row['max_user_connections'] . '" size="11" maxlength="11" '
547 . 'title="'
548 . __('Limits the number of simultaneous connections the user may have.')
549 . '" />' . "\n"
550 . '</div>' . "\n";
552 $html_output .= '</fieldset>' . "\n";
554 return $html_output;
558 * Get the HTML snippet for table specific privileges
560 * @param string $username username for database connection
561 * @param string $hostname hostname for database connection
562 * @param string $db the database
563 * @param string $table the table
564 * @param boolean $columns columns array
565 * @param $row
567 * @return string $html_output
569 function PMA_getHtmlForTableSpecificPrivileges($username, $hostname, $db,
570 $table, $columns, $row
572 $res = PMA_DBI_query(
573 'SELECT `Column_name`, `Column_priv`'
574 .' FROM `mysql`.`columns_priv`'
575 .' WHERE `User`'
576 .' = \'' . PMA_Util::sqlAddSlashes($username) . "'"
577 .' AND `Host`'
578 .' = \'' . PMA_Util::sqlAddSlashes($hostname) . "'"
579 .' AND `Db`'
580 .' = \'' . PMA_Util::sqlAddSlashes(
581 PMA_Util::unescapeMysqlWildcards($db)
582 ) . "'"
583 .' AND `Table_name`'
584 .' = \'' . PMA_Util::sqlAddSlashes($table) . '\';'
587 while ($row1 = PMA_DBI_fetch_row($res)) {
588 $row1[1] = explode(',', $row1[1]);
589 foreach ($row1[1] as $current) {
590 $columns[$row1[0]][$current] = true;
593 PMA_DBI_free_result($res);
594 unset($res, $row1, $current);
596 $html_output = '<input type="hidden" name="grant_count" '
597 . 'value="' . count($row) . '" />' . "\n"
598 . '<input type="hidden" name="column_count" '
599 . 'value="' . count($columns) . '" />' . "\n"
600 . '<fieldset id="fieldset_user_priv">' . "\n"
601 . '<legend>' . __('Table-specific privileges')
602 . PMA_Util::showHint(
603 __('Note: MySQL privilege names are expressed in English')
605 . '</legend>' . "\n";
607 // privs that are attached to a specific column
608 $html_output .= PMA_getHtmlForAttachedPrivilegesToTableSpecificColumn(
609 $columns, $row
612 // privs that are not attached to a specific column
613 $html_output .= '<div class="item">' . "\n"
614 . PMA_getHtmlForNotAttachedPrivilegesToTableSpecificColumn($row)
615 . '</div>' . "\n";
617 // for Safari 2.0.2
618 $html_output .= '<div class="clearfloat"></div>' . "\n";
620 return $html_output;
624 * Get HTML snippet for privileges that are attached to a specific column
626 * @param string $columns olumns array
627 * @param array $row first row from result or boolean false
629 * @return string $html_output
631 function PMA_getHtmlForAttachedPrivilegesToTableSpecificColumn($columns, $row)
633 $html_output = PMA_getHtmlForDisplayColumnPrivileges(
634 $columns, $row, 'Select_priv', 'SELECT',
635 'select', __('Allows reading data.'), 'Select'
638 $html_output .= PMA_getHtmlForDisplayColumnPrivileges(
639 $columns, $row, 'Insert_priv', 'INSERT',
640 'insert', __('Allows inserting and replacing data.'), 'Insert'
643 $html_output .= PMA_getHtmlForDisplayColumnPrivileges(
644 $columns, $row, 'Update_priv', 'UPDATE',
645 'update', __('Allows changing data.'), 'Update'
648 $html_output .= PMA_getHtmlForDisplayColumnPrivileges(
649 $columns, $row, 'References_priv', 'REFERENCES', 'references',
650 __('Has no effect in this MySQL version.'), 'References'
652 return $html_output;
656 * Get HTML for privileges that are not attached to a specific column
658 * @param array $row first row from result or boolean false
660 * @return string $html_output
662 function PMA_getHtmlForNotAttachedPrivilegesToTableSpecificColumn($row)
664 $html_output = '';
665 foreach ($row as $current_grant => $current_grant_value) {
666 $grant_type = substr($current_grant, 0, (strlen($current_grant) - 5));
667 if (in_array($grant_type, array('Select', 'Insert', 'Update', 'References'))) {
668 continue;
670 // make a substitution to match the messages variables;
671 // also we must substitute the grant we get, because we can't generate
672 // a form variable containing blanks (those would get changed to
673 // an underscore when receiving the POST)
674 if ($current_grant == 'Create View_priv') {
675 $tmp_current_grant = 'CreateView_priv';
676 $current_grant = 'Create_view_priv';
677 } elseif ($current_grant == 'Show view_priv') {
678 $tmp_current_grant = 'ShowView_priv';
679 $current_grant = 'Show_view_priv';
680 } else {
681 $tmp_current_grant = $current_grant;
684 $html_output .= '<div class="item">' . "\n"
685 . '<input type="checkbox"'
686 . ' name="' . $current_grant . '" id="checkbox_' . $current_grant
687 . '" value="Y" '
688 . ($current_grant_value == 'Y' ? 'checked="checked" ' : '')
689 . 'title="';
691 $html_output .= (isset($GLOBALS[
692 'strPrivDesc' . substr(
693 $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
696 ? $GLOBALS[
697 'strPrivDesc' . substr(
698 $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
701 : $GLOBALS[
702 'strPrivDesc' . substr(
703 $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
704 ) . 'Tbl'
707 . '"/>' . "\n";
709 $html_output .= '<label for="checkbox_' . $current_grant
710 . '"><code><dfn title="'
711 . (isset($GLOBALS[
712 'strPrivDesc' . substr(
713 $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
716 ? $GLOBALS[
717 'strPrivDesc' . substr(
718 $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
721 : $GLOBALS[
722 'strPrivDesc' . substr(
723 $tmp_current_grant, 0, (strlen($tmp_current_grant) - 5)
724 ) . 'Tbl'
727 . '">'
728 . strtoupper(
729 substr($current_grant, 0, strlen($current_grant) - 5)
731 . '</dfn></code></label>' . "\n"
732 . '</div>' . "\n";
733 } // end foreach ()
734 return $html_output;
738 * Get HTML for global or database specific privileges
740 * @param string $db the database
741 * @param string $table the table
742 * @param string $row first row from result or boolean false
744 * @return string $html_output
746 function PMA_getHtmlForGlobalOrDbSpecificPrivs($db, $table, $row)
748 $privTable_names = array(0 => __('Data'),
749 1 => __('Structure'),
750 2 => __('Administration')
752 $privTable = array();
753 // d a t a
754 $privTable[0] = PMA_getDataPrivilegeTable($db);
756 // s t r u c t u r e
757 $privTable[1] = PMA_getStructurePrivilegeTable($table, $row);
759 // a d m i n i s t r a t i o n
760 $privTable[2] = PMA_getAdministrationPrivilegeTable($db);
762 $html_output = '<input type="hidden" name="grant_count" value="'
763 . (count($privTable[0])
764 + count($privTable[1])
765 + count($privTable[2])
766 - (isset($row['Grant_priv']) ? 1 : 0)
768 . '" />';
769 $html_output .= '<fieldset id="fieldset_user_global_rights"><legend>';
770 if ($db == '*') {
771 $html_output .= __('Global privileges');
772 } else if ($table == '*') {
773 $html_output .= __('Database-specific privileges');
774 } else {
775 $html_output .= __('Table-specific privileges');
777 $html_output .= ' (<a href="#" '
778 . 'onclick="setCheckboxes(\'fieldset_user_global_rights\', true); '
779 . 'return false;">' . __('Check All') . '</a> /'
780 . '<a href="#" '
781 . 'onclick="setCheckboxes(\'fieldset_user_global_rights\', false); '
782 . 'return false;">' . __('Uncheck All') . '</a>)';
783 $html_output .= '</legend>';
784 $html_output .= '<p><small><i>'
785 . __('Note: MySQL privilege names are expressed in English')
786 . '</i></small></p>';
788 // Output the Global privilege tables with checkboxes
789 $html_output .= PMA_getHtmlForGlobalPrivTableWithCheckboxes(
790 $privTable, $privTable_names, $row
793 // The "Resource limits" box is not displayed for db-specific privs
794 if ($db == '*') {
795 $html_output .= PMA_getHtmlForDisplayResourceLimits($row);
797 // for Safari 2.0.2
798 $html_output .= '<div class="clearfloat"></div>';
800 return $html_output;
804 * Get data privilege table as an array
806 * @param string $db the database
808 * @return string data privilege table
810 function PMA_getDataPrivilegeTable($db)
812 $data_privTable = array(
813 array('Select', 'SELECT', __('Allows reading data.')),
814 array('Insert', 'INSERT', __('Allows inserting and replacing data.')),
815 array('Update', 'UPDATE', __('Allows changing data.')),
816 array('Delete', 'DELETE', __('Allows deleting data.'))
818 if ($db == '*') {
819 $data_privTable[]
820 = array('File',
821 'FILE',
822 __('Allows importing data from and exporting data into files.')
825 return $data_privTable;
829 * Get structure privilege table as an array
831 * @param string $table the table
832 * @param array $row first row from result or boolean false
834 * @return string structure privilege table
836 function PMA_getStructurePrivilegeTable($table, $row)
838 $structure_privTable = array(
839 array('Create',
840 'CREATE',
841 ($table == '*'
842 ? __('Allows creating new databases and tables.')
843 : __('Allows creating new tables.')
846 array('Alter',
847 'ALTER',
848 __('Allows altering the structure of existing tables.')
850 array('Index', 'INDEX', __('Allows creating and dropping indexes.')),
851 array('Drop',
852 'DROP',
853 ($table == '*'
854 ? __('Allows dropping databases and tables.')
855 : __('Allows dropping tables.')
858 array('Create_tmp_table',
859 'CREATE TEMPORARY TABLES',
860 __('Allows creating temporary tables.')
862 array('Show_view',
863 'SHOW VIEW',
864 __('Allows performing SHOW CREATE VIEW queries.')
866 array('Create_routine',
867 'CREATE ROUTINE',
868 __('Allows creating stored routines.')
870 array('Alter_routine',
871 'ALTER ROUTINE',
872 __('Allows altering and dropping stored routines.')
874 array('Execute', 'EXECUTE', __('Allows executing stored routines.')),
876 // this one is for a db-specific priv: Create_view_priv
877 if (isset($row['Create_view_priv'])) {
878 $structure_privTable[] = array('Create_view',
879 'CREATE VIEW',
880 __('Allows creating new views.')
883 // this one is for a table-specific priv: Create View_priv
884 if (isset($row['Create View_priv'])) {
885 $structure_privTable[] = array('Create View',
886 'CREATE VIEW',
887 __('Allows creating new views.')
890 if (isset($row['Event_priv'])) {
891 // MySQL 5.1.6
892 $structure_privTable[] = array('Event',
893 'EVENT',
894 __('Allows to set up events for the event scheduler')
896 $structure_privTable[] = array('Trigger',
897 'TRIGGER',
898 __('Allows creating and dropping triggers')
901 return $structure_privTable;
905 * Get administration privilege table as an array
907 * @param string $db the table
909 * @return string administration privilege table
911 function PMA_getAdministrationPrivilegeTable($db)
913 $administration_privTable = array(
914 array('Grant',
915 'GRANT',
916 __('Allows adding users and privileges without reloading the privilege tables.')
919 if ($db == '*') {
920 $administration_privTable[] = array('Super',
921 'SUPER',
922 __('Allows connecting, even if maximum number of connections is reached; required for most administrative operations like setting global variables or killing threads of other users.')
924 $administration_privTable[] = array('Process',
925 'PROCESS',
926 __('Allows viewing processes of all users')
928 $administration_privTable[] = array('Reload',
929 'RELOAD',
930 __('Allows reloading server settings and flushing the server\'s caches.')
932 $administration_privTable[] = array('Shutdown',
933 'SHUTDOWN',
934 __('Allows shutting down the server.')
936 $administration_privTable[] = array('Show_db',
937 'SHOW DATABASES',
938 __('Gives access to the complete list of databases.')
941 $administration_privTable[] = array('Lock_tables',
942 'LOCK TABLES',
943 __('Allows locking tables for the current thread.')
945 $administration_privTable[] = array('References',
946 'REFERENCES',
947 __('Has no effect in this MySQL version.')
949 if ($db == '*') {
950 $administration_privTable[] = array('Repl_client',
951 'REPLICATION CLIENT',
952 __('Allows the user to ask where the slaves / masters are.')
954 $administration_privTable[] = array('Repl_slave',
955 'REPLICATION SLAVE',
956 __('Needed for the replication slaves.')
958 $administration_privTable[] = array('Create_user',
959 'CREATE USER',
960 __('Allows creating, dropping and renaming user accounts.')
963 return $administration_privTable;
967 * Get HTML snippet for global privileges table with check boxes
969 * @param array $privTable privileges table array
970 * @param array $privTable_names names of the privilege tables
971 * (Data, Structure, Administration)
972 * @param array $row first row from result or boolean false
974 * @return string $html_output
976 function PMA_getHtmlForGlobalPrivTableWithCheckboxes(
977 $privTable, $privTable_names, $row
979 $html_output = '';
980 foreach ($privTable as $i => $table) {
981 $html_output .= '<fieldset>' . "\n"
982 . '<legend>' . $privTable_names[$i] . '</legend>' . "\n";
983 foreach ($table as $priv) {
984 $html_output .= '<div class="item">' . "\n"
985 . '<input type="checkbox"'
986 . ' name="' . $priv[0] . '_priv" '
987 . 'id="checkbox_' . $priv[0] . '_priv"'
988 . ' value="Y" title="' . $priv[2] . '"'
989 . (($row[$priv[0] . '_priv'] == 'Y')
990 ? ' checked="checked"'
991 : ''
993 . '/>' . "\n"
994 . '<label for="checkbox_' . $priv[0] . '_priv">'
995 . '<code><dfn title="' . $priv[2] . '">'
996 . $priv[1] . '</dfn></code></label>' . "\n"
997 . '</div>' . "\n";
999 $html_output .= '</fieldset>' . "\n";
1001 return $html_output;
1005 * Displays the fields used by the "new user" form as well as the
1006 * "change login information / copy user" form.
1008 * @param string $mode are we creating a new user or are we just
1009 * changing one? (allowed values: 'new', 'change')
1011 * @global array $cfg the phpMyAdmin configuration
1012 * @global ressource $user_link the database connection
1014 * @return string $html_output a HTML snippet
1016 function PMA_getHtmlForDisplayLoginInformationFields($mode = 'new')
1018 list($username_length, $hostname_length) = PMA_getUsernameAndHostnameLength();
1020 if (isset($GLOBALS['username']) && strlen($GLOBALS['username']) === 0) {
1021 $GLOBALS['pred_username'] = 'any';
1023 $html_output = '<fieldset id="fieldset_add_user_login">' . "\n"
1024 . '<legend>' . __('Login Information') . '</legend>' . "\n"
1025 . '<div class="item">' . "\n"
1026 . '<label for="select_pred_username">' . "\n"
1027 . ' ' . __('User name') . ':' . "\n"
1028 . '</label>' . "\n"
1029 . '<span class="options">' . "\n";
1031 $html_output .= '<select name="pred_username" id="select_pred_username" '
1032 . 'title="' . __('User name') . '"' . "\n";
1035 $html_output .= ' onchange="'
1036 . 'if (this.value == \'any\') {'
1037 . ' username.value = \'\'; '
1038 . '} else if (this.value == \'userdefined\') {'
1039 . ' username.focus(); username.select(); '
1040 . '}">' . "\n";
1042 $html_output .= '<option value="any"'
1043 . ((isset($GLOBALS['pred_username']) && $GLOBALS['pred_username'] == 'any')
1044 ? ' selected="selected"'
1045 : '') . '>'
1046 . __('Any user')
1047 . '</option>' . "\n";
1049 $html_output .= '<option value="userdefined"'
1050 . ((! isset($GLOBALS['pred_username'])
1051 || $GLOBALS['pred_username'] == 'userdefined'
1053 ? ' selected="selected"'
1054 : '') . '>'
1055 . __('Use text field')
1056 . ':</option>' . "\n";
1058 $html_output .= '</select>' . "\n"
1059 . '</span>' . "\n";
1061 $html_output .= '<input type="text" name="username" class="autofocus"'
1062 . ' maxlength="' . $username_length . '" title="' . __('User name') . '"'
1063 . (empty($GLOBALS['username'])
1064 ? ''
1065 : ' value="' . htmlspecialchars(
1066 isset($GLOBALS['new_username'])
1067 ? $GLOBALS['new_username']
1068 : $GLOBALS['username']
1069 ) . '"'
1071 . ' onchange="pred_username.value = \'userdefined\';" />' . "\n"
1072 . '</div>' . "\n";
1074 $html_output .= '<div class="item">' . "\n"
1075 . '<label for="select_pred_hostname">' . "\n"
1076 . ' ' . __('Host') . ':' . "\n"
1077 . '</label>' . "\n";
1079 $html_output .= '<span class="options">' . "\n"
1080 . ' <select name="pred_hostname" id="select_pred_hostname" '
1081 . 'title="' . __('Host') . '"' . "\n";
1082 $_current_user = PMA_DBI_fetch_value('SELECT USER();');
1083 if (! empty($_current_user)) {
1084 $thishost = str_replace(
1085 "'",
1087 substr($_current_user, (strrpos($_current_user, '@') + 1))
1089 if ($thishost == 'localhost' || $thishost == '127.0.0.1') {
1090 unset($thishost);
1093 $html_output .= ' onchange="'
1094 . 'if (this.value == \'any\') { '
1095 . ' hostname.value = \'%\'; '
1096 . '} else if (this.value == \'localhost\') { '
1097 . ' hostname.value = \'localhost\'; '
1098 . '} '
1099 . (empty($thishost)
1100 ? ''
1101 : 'else if (this.value == \'thishost\') { '
1102 . ' hostname.value = \'' . addslashes(htmlspecialchars($thishost))
1103 . '\'; '
1104 . '} '
1106 . 'else if (this.value == \'hosttable\') { '
1107 . ' hostname.value = \'\'; '
1108 . '} else if (this.value == \'userdefined\') {'
1109 . ' hostname.focus(); hostname.select(); '
1110 . '}">' . "\n";
1111 unset($_current_user);
1113 // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
1114 if (! isset($GLOBALS['pred_hostname']) && isset($GLOBALS['hostname'])) {
1115 switch (strtolower($GLOBALS['hostname'])) {
1116 case 'localhost':
1117 case '127.0.0.1':
1118 $GLOBALS['pred_hostname'] = 'localhost';
1119 break;
1120 case '%':
1121 $GLOBALS['pred_hostname'] = 'any';
1122 break;
1123 default:
1124 $GLOBALS['pred_hostname'] = 'userdefined';
1125 break;
1128 $html_output .= '<option value="any"'
1129 . ((isset($GLOBALS['pred_hostname'])
1130 && $GLOBALS['pred_hostname'] == 'any'
1132 ? ' selected="selected"'
1133 : '') . '>'
1134 . __('Any host')
1135 . '</option>' . "\n"
1136 . '<option value="localhost"'
1137 . ((isset($GLOBALS['pred_hostname'])
1138 && $GLOBALS['pred_hostname'] == 'localhost'
1140 ? ' selected="selected"'
1141 : '') . '>'
1142 . __('Local')
1143 . '</option>' . "\n";
1144 if (! empty($thishost)) {
1145 $html_output .= '<option value="thishost"'
1146 . ((isset($GLOBALS['pred_hostname'])
1147 && $GLOBALS['pred_hostname'] == 'thishost'
1149 ? ' selected="selected"'
1150 : '') . '>'
1151 . __('This Host')
1152 . '</option>' . "\n";
1154 unset($thishost);
1155 $html_output .= '<option value="hosttable"'
1156 . ((isset($GLOBALS['pred_hostname'])
1157 && $GLOBALS['pred_hostname'] == 'hosttable'
1159 ? ' selected="selected"'
1160 : '') . '>'
1161 . __('Use Host Table')
1162 . '</option>' . "\n";
1164 $html_output .= '<option value="userdefined"'
1165 . ((isset($GLOBALS['pred_hostname'])
1166 && $GLOBALS['pred_hostname'] == 'userdefined'
1168 ? ' selected="selected"'
1169 : '') . '>'
1170 . __('Use text field') . ':</option>' . "\n"
1171 . '</select>' . "\n"
1172 . '</span>' . "\n";
1174 $html_output .= '<input type="text" name="hostname" maxlength="'
1175 . $hostname_length . '" value="'
1176 . htmlspecialchars(isset($GLOBALS['hostname']) ? $GLOBALS['hostname'] : '')
1177 . '" title="' . __('Host')
1178 . '" onchange="pred_hostname.value = \'userdefined\';" />' . "\n"
1179 . PMA_Util::showHint(
1180 __('When Host table is used, this field is ignored and values stored in Host table are used instead.')
1182 . '</div>' . "\n";
1184 $html_output .= '<div class="item">' . "\n"
1185 . '<label for="select_pred_password">' . "\n"
1186 . ' ' . __('Password') . ':' . "\n"
1187 . '</label>' . "\n"
1188 . '<span class="options">' . "\n"
1189 . '<select name="pred_password" id="select_pred_password" title="'
1190 . __('Password') . '"' . "\n";
1192 $html_output .= ' onchange="'
1193 . 'if (this.value == \'none\') { '
1194 . ' pma_pw.value = \'\'; pma_pw2.value = \'\'; '
1195 . '} else if (this.value == \'userdefined\') { '
1196 . ' pma_pw.focus(); pma_pw.select(); '
1197 . '}">' . "\n"
1198 . ($mode == 'change' ? '<option value="keep" selected="selected">'
1199 . __('Do not change the password')
1200 . '</option>' . "\n" : '')
1201 . '<option value="none"';
1203 if (isset($GLOBALS['username']) && $mode != 'change') {
1204 $html_output .= ' selected="selected"';
1206 $html_output .= '>' . __('No Password') . '</option>' . "\n"
1207 . '<option value="userdefined"'
1208 . (isset($GLOBALS['username']) ? '' : ' selected="selected"') . '>'
1209 . __('Use text field')
1210 . ':</option>' . "\n"
1211 . '</select>' . "\n"
1212 . '</span>' . "\n"
1213 . '<input type="password" id="text_pma_pw" name="pma_pw" '
1214 . 'title="' . __('Password') . '" '
1215 . 'onchange="pred_password.value = \'userdefined\';" />' . "\n"
1216 . '</div>' . "\n";
1218 $html_output .= '<div class="item" '
1219 . 'id="div_element_before_generate_password">' . "\n"
1220 . '<label for="text_pma_pw2">' . "\n"
1221 . ' ' . __('Re-type') . ':' . "\n"
1222 . '</label>' . "\n"
1223 . '<span class="options">&nbsp;</span>' . "\n"
1224 . '<input type="password" name="pma_pw2" id="text_pma_pw2" '
1225 . 'title="' . __('Re-type') . '" '
1226 . 'onchange="pred_password.value = \'userdefined\';" />' . "\n"
1227 . '</div>' . "\n"
1228 // Generate password added here via jQuery
1229 . '</fieldset>' . "\n";
1231 return $html_output;
1232 } // end of the 'PMA_displayUserAndHostFields()' function
1235 * Get username and hostname length
1237 * @return array username length and hostname length
1239 function PMA_getUsernameAndHostnameLength()
1241 $fields_info = PMA_DBI_get_columns('mysql', 'user', null, true);
1242 $username_length = 16;
1243 $hostname_length = 41;
1244 foreach ($fields_info as $val) {
1245 if ($val['Field'] == 'User') {
1246 strtok($val['Type'], '()');
1247 $value = strtok('()');
1248 if (is_int($value)) {
1249 $username_length = $value;
1251 } elseif ($val['Field'] == 'Host') {
1252 strtok($val['Type'], '()');
1253 $value = strtok('()');
1254 if (is_int($value)) {
1255 $hostname_length = $value;
1259 return array($username_length, $hostname_length);
1263 * Returns all the grants for a certain user on a certain host
1264 * Used in the export privileges for all users section
1266 * @param string $user User name
1267 * @param string $host Host name
1269 * @return string containing all the grants text
1271 function PMA_getGrants($user, $host)
1273 $grants = PMA_DBI_fetch_result(
1274 "SHOW GRANTS FOR '"
1275 . PMA_Util::sqlAddSlashes($user) . "'@'"
1276 . PMA_Util::sqlAddSlashes($host) . "'"
1278 $response = '';
1279 foreach ($grants as $one_grant) {
1280 $response .= $one_grant . ";\n\n";
1282 return $response;
1283 } // end of the 'PMA_getGrants()' function
1286 * Update password and get message for password updating
1288 * @param string $err_url error url
1289 * @param string $username username
1290 * @param string $hostname hostname
1292 * @return string $message success or error message after updating password
1294 function PMA_getMessageForUpdatePassword($err_url, $username, $hostname)
1296 // similar logic in user_password.php
1297 $message = '';
1299 if (empty($_REQUEST['nopass'])
1300 && isset($_POST['pma_pw'])
1301 && isset($_POST['pma_pw2'])
1303 if ($_POST['pma_pw'] != $_POST['pma_pw2']) {
1304 $message = PMA_Message::error(__('The passwords aren\'t the same!'));
1305 } elseif (empty($_POST['pma_pw']) || empty($_POST['pma_pw2'])) {
1306 $message = PMA_Message::error(__('The password is empty!'));
1310 // here $nopass could be == 1
1311 if (empty($message)) {
1313 $hashing_function
1314 = (! empty($_REQUEST['pw_hash']) && $_REQUEST['pw_hash'] == 'old'
1315 ? 'OLD_'
1316 : ''
1318 . 'PASSWORD';
1320 // in $sql_query which will be displayed, hide the password
1321 $sql_query = 'SET PASSWORD FOR \''
1322 . PMA_Util::sqlAddSlashes($username)
1323 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\' = '
1324 . (($_POST['pma_pw'] == '')
1325 ? '\'\''
1326 : $hashing_function . '(\''
1327 . preg_replace('@.@s', '*', $_POST['pma_pw']) . '\')');
1329 $local_query = 'SET PASSWORD FOR \''
1330 . PMA_Util::sqlAddSlashes($username)
1331 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\' = '
1332 . (($_POST['pma_pw'] == '') ? '\'\'' : $hashing_function
1333 . '(\'' . PMA_Util::sqlAddSlashes($_POST['pma_pw']) . '\')');
1335 PMA_DBI_try_query($local_query)
1336 or PMA_Util::mysqlDie(
1337 PMA_DBI_getError(), $sql_query, false, $err_url
1339 $message = PMA_Message::success(
1340 __('The password for %s was changed successfully.')
1342 $message->addParam(
1343 '\'' . htmlspecialchars($username)
1344 . '\'@\'' . htmlspecialchars($hostname) . '\''
1347 return $message;
1351 * Revokes privileges and get message and SQL query for privileges revokes
1353 * @param string $db_and_table wildcard Escaped database+table specification
1354 * @param string $dbname database name
1355 * @param string $tablename table name
1356 * @param string $username username
1357 * @param string $hostname host name
1359 * @return array ($message, $sql_query)
1361 function PMA_getMessageAndSqlQueryForPrivilegesRevoke($db_and_table, $dbname,
1362 $tablename, $username, $hostname
1364 $db_and_table = PMA_wildcardEscapeForGrant($dbname, $tablename);
1366 $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
1367 . ' FROM \''
1368 . PMA_Util::sqlAddSlashes($username) . '\'@\''
1369 . PMA_Util::sqlAddSlashes($hostname) . '\';';
1371 $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
1372 . ' FROM \'' . PMA_Util::sqlAddSlashes($username) . '\'@\''
1373 . PMA_Util::sqlAddSlashes($hostname) . '\';';
1375 PMA_DBI_query($sql_query0);
1376 if (! PMA_DBI_try_query($sql_query1)) {
1377 // this one may fail, too...
1378 $sql_query1 = '';
1380 $sql_query = $sql_query0 . ' ' . $sql_query1;
1381 $message = PMA_Message::success(
1382 __('You have revoked the privileges for %s')
1384 $message->addParam(
1385 '\'' . htmlspecialchars($username)
1386 . '\'@\'' . htmlspecialchars($hostname) . '\''
1389 return array($message, $sql_query);
1393 * Get a WITH clause for 'update privileges' and 'add user'
1395 * @return string $sql_query
1397 function PMA_getWithClauseForAddUserAndUpdatePrivs()
1399 $sql_query = '';
1400 if (isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y') {
1401 $sql_query .= ' GRANT OPTION';
1403 if (isset($_POST['max_questions'])) {
1404 $max_questions = max(0, (int)$_POST['max_questions']);
1405 $sql_query .= ' MAX_QUERIES_PER_HOUR ' . $max_questions;
1407 if (isset($_POST['max_connections'])) {
1408 $max_connections = max(0, (int)$_POST['max_connections']);
1409 $sql_query .= ' MAX_CONNECTIONS_PER_HOUR ' . $max_connections;
1411 if (isset($_POST['max_updates'])) {
1412 $max_updates = max(0, (int)$_POST['max_updates']);
1413 $sql_query .= ' MAX_UPDATES_PER_HOUR ' . $max_updates;
1415 if (isset($_POST['max_user_connections'])) {
1416 $max_user_connections = max(0, (int)$_POST['max_user_connections']);
1417 $sql_query .= ' MAX_USER_CONNECTIONS ' . $max_user_connections;
1419 return ((!empty($sql_query)) ? 'WITH' . $sql_query : '');
1423 * Get HTML for addUsersForm, This function call if isset($_REQUEST['adduser'])
1425 * @param string $dbname
1427 * @return string HTML for addUserForm
1429 function PMA_getHtmlForAddUser($dbname)
1431 $GLOBALS['url_query'] .= '&amp;adduser=1';
1433 $html_output = '<h2>' . "\n"
1434 . PMA_Util::getIcon('b_usradd.png') . __('Add user') . "\n"
1435 . '</h2>' . "\n"
1436 . '<form name="usersForm" class="ajax" id="addUsersForm"'
1437 . ' action="server_privileges.php" method="post">' . "\n"
1438 . PMA_generate_common_hidden_inputs('', '')
1439 . PMA_getHtmlForDisplayLoginInformationFields('new');
1441 $html_output .= '<fieldset id="fieldset_add_user_database">' . "\n"
1442 . '<legend>' . __('Database for user') . '</legend>' . "\n";
1444 $html_output .= PMA_Util::getCheckbox(
1445 'createdb-1',
1446 __('Create database with same name and grant all privileges'),
1447 false, false
1449 $html_output .= '<br />' . "\n";
1450 $html_output .= PMA_Util::getCheckbox(
1451 'createdb-2',
1452 __('Grant all privileges on wildcard name (username\\_%)'),
1453 false, false
1455 $html_output .= '<br />' . "\n";
1457 if (! empty($dbname) ) {
1458 $html_output .= PMA_Util::getCheckbox(
1459 'createdb-3',
1460 sprintf(__('Grant all privileges on database &quot;%s&quot;'), htmlspecialchars($dbname)),
1461 true,
1462 false
1464 $html_output .= '<input type="hidden" name="dbname" value="'
1465 . htmlspecialchars($dbname) . '" />' . "\n";
1466 $html_output .= '<br />' . "\n";
1469 $html_output .= '</fieldset>' . "\n";
1470 $html_output .= PMA_getHtmlToDisplayPrivilegesTable('*', '*', false);
1471 $html_output .= '<fieldset id="fieldset_add_user_footer" class="tblFooters">'
1472 . "\n"
1473 . '<input type="submit" name="adduser_submit" '
1474 . 'value="' . __('Go') . '" />' . "\n"
1475 . '</fieldset>' . "\n"
1476 . '</form>' . "\n";
1478 return $html_output;
1482 * Get the list of privileges and list of compared privileges as strings
1483 * and return a array that contains both strings
1485 * @return array $list_of_privileges, $list_of_compared_privileges
1487 function PMA_getListOfPrivilegesAndComparedPrivileges()
1489 $list_of_privileges
1490 = '`User`, '
1491 . '`Host`, '
1492 . '`Select_priv`, '
1493 . '`Insert_priv`, '
1494 . '`Update_priv`, '
1495 . '`Delete_priv`, '
1496 . '`Create_priv`, '
1497 . '`Drop_priv`, '
1498 . '`Grant_priv`, '
1499 . '`Index_priv`, '
1500 . '`Alter_priv`, '
1501 . '`References_priv`, '
1502 . '`Create_tmp_table_priv`, '
1503 . '`Lock_tables_priv`, '
1504 . '`Create_view_priv`, '
1505 . '`Show_view_priv`, '
1506 . '`Create_routine_priv`, '
1507 . '`Alter_routine_priv`, '
1508 . '`Execute_priv`';
1510 $list_of_compared_privileges
1511 = '`Select_priv` = \'N\''
1512 . ' AND `Insert_priv` = \'N\''
1513 . ' AND `Update_priv` = \'N\''
1514 . ' AND `Delete_priv` = \'N\''
1515 . ' AND `Create_priv` = \'N\''
1516 . ' AND `Drop_priv` = \'N\''
1517 . ' AND `Grant_priv` = \'N\''
1518 . ' AND `References_priv` = \'N\''
1519 . ' AND `Create_tmp_table_priv` = \'N\''
1520 . ' AND `Lock_tables_priv` = \'N\''
1521 . ' AND `Create_view_priv` = \'N\''
1522 . ' AND `Show_view_priv` = \'N\''
1523 . ' AND `Create_routine_priv` = \'N\''
1524 . ' AND `Alter_routine_priv` = \'N\''
1525 . ' AND `Execute_priv` = \'N\'';
1527 if (PMA_MYSQL_INT_VERSION >= 50106) {
1528 $list_of_privileges .=
1529 ', `Event_priv`, '
1530 . '`Trigger_priv`';
1531 $list_of_compared_privileges .=
1532 ' AND `Event_priv` = \'N\''
1533 . ' AND `Trigger_priv` = \'N\'';
1535 return array($list_of_privileges, $list_of_compared_privileges);
1539 * Get the HTML for user form and check the privileges for a particular database.
1541 * @param string $link_edit standard link for edit
1542 * @param string $conditional_class if ajaxable 'Ajax' otherwise ''
1544 * @return string $html_output
1546 function PMA_getHtmlForSpecificDbPrivileges($link_edit, $conditional_class)
1548 // check the privileges for a particular database.
1549 $html_output = '<form id="usersForm" action="server_privileges.php">'
1550 . '<fieldset>' . "\n";
1551 $html_output .= '<legend>' . "\n"
1552 . PMA_Util::getIcon('b_usrcheck.png')
1553 . ' '
1554 . sprintf(
1555 __('Users having access to &quot;%s&quot;'),
1556 '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
1557 . PMA_generate_common_url($_REQUEST['checkprivs']) . '">'
1558 . htmlspecialchars($_REQUEST['checkprivs'])
1559 . '</a>'
1561 . "\n"
1562 . '</legend>' . "\n";
1564 $html_output .= '<table id="dbspecificuserrights" class="data">' . "\n"
1565 . '<thead>' . "\n"
1566 . '<tr><th>' . __('User') . '</th>' . "\n"
1567 . '<th>' . __('Host') . '</th>' . "\n"
1568 . '<th>' . __('Type') . '</th>' . "\n"
1569 . '<th>' . __('Privileges') . '</th>' . "\n"
1570 . '<th>' . __('Grant') . '</th>' . "\n"
1571 . '<th>' . __('Action') . '</th>' . "\n"
1572 . '</tr>' . "\n"
1573 . '</thead>' . "\n";
1574 $odd_row = true;
1575 // now, we build the table...
1576 list($list_of_privileges, $list_of_compared_privileges)
1577 = PMA_getListOfPrivilegesAndComparedPrivileges();
1579 $sql_query = '(SELECT ' . $list_of_privileges . ', `Db`'
1580 .' FROM `mysql`.`db`'
1581 .' WHERE \'' . PMA_Util::sqlAddSlashes($_REQUEST['checkprivs'])
1582 . "'"
1583 .' LIKE `Db`'
1584 .' AND NOT (' . $list_of_compared_privileges. ')) '
1585 .'UNION '
1586 .'(SELECT ' . $list_of_privileges . ', \'*\' AS `Db`'
1587 .' FROM `mysql`.`user` '
1588 .' WHERE NOT (' . $list_of_compared_privileges . ')) '
1589 .' ORDER BY `User` ASC,'
1590 .' `Host` ASC,'
1591 .' `Db` ASC;';
1592 $res = PMA_DBI_query($sql_query);
1593 $row = PMA_DBI_fetch_assoc($res);
1594 if ($row) {
1595 $found = true;
1597 $html_output .= PMA_getHtmlTableBodyForSpecificDbPrivs(
1598 $found, $row, $odd_row, $link_edit, $res
1600 $html_output .= '</table>'
1601 . '</fieldset>'
1602 . '</form>' . "\n";
1604 if ($GLOBALS['is_ajax_request'] == true && empty($_REQUEST['ajax_page_request'])) {
1605 $message = PMA_Message::success(__('User has been added.'));
1606 $response = PMA_Response::getInstance();
1607 $response->addJSON('message', $message);
1608 $response->addJSON('user_form', $html_output);
1609 exit;
1610 } else {
1611 // Offer to create a new user for the current database
1612 $html_output .= '<fieldset id="fieldset_add_user">' . "\n"
1613 . '<legend>' . _pgettext('Create new user', 'New') . '</legend>' . "\n";
1615 $html_output .= '<a href="server_privileges.php?'
1616 . $GLOBALS['url_query'] . '&amp;adduser=1&amp;'
1617 . 'dbname=' . htmlspecialchars($_REQUEST['checkprivs'])
1618 .'" rel="'
1619 .'checkprivs='.htmlspecialchars($_REQUEST['checkprivs'])
1620 . '&amp;'.$GLOBALS['url_query']
1621 . '" class="'.$conditional_class
1622 .'" name="db_specific">' . "\n"
1623 . PMA_Util::getIcon('b_usradd.png')
1624 . ' ' . __('Add user') . '</a>' . "\n";
1626 $html_output .= '</fieldset>' . "\n";
1628 return $html_output;
1632 * Get HTML snippet for table body of specific database privileges
1634 * @param boolean $found whether user found or not
1635 * @param array $row array of rows from mysql,
1636 * db table with list of privileges
1637 * @param boolean $odd_row whether odd or not
1638 * @param string $link_edit standard link for edit
1639 * @param string $res ran sql query
1641 * @return string $html_output
1643 function PMA_getHtmlTableBodyForSpecificDbPrivs($found, $row, $odd_row,
1644 $link_edit, $res
1646 $html_output = '<tbody>' . "\n";
1647 if ($found) {
1648 while (true) {
1649 // prepare the current user
1650 $current_privileges = array();
1651 $current_user = $row['User'];
1652 $current_host = $row['Host'];
1653 while ($row
1654 && $current_user == $row['User']
1655 && $current_host == $row['Host']
1657 $current_privileges[] = $row;
1658 $row = PMA_DBI_fetch_assoc($res);
1660 $html_output .= '<tr '
1661 . 'class="noclick ' . ($odd_row ? 'odd' : 'even')
1662 . '">' . "\n"
1663 . '<td';
1664 if (count($current_privileges) > 1) {
1665 $html_output .= ' rowspan="' . count($current_privileges) . '"';
1667 $html_output .= '>'
1668 . (empty($current_user)
1669 ? '<span style="color: #FF0000">' . __('Any') . '</span>'
1670 : htmlspecialchars($current_user)) . "\n"
1671 . '</td>' . "\n";
1673 $html_output .= '<td';
1674 if (count($current_privileges) > 1) {
1675 $html_output .= ' rowspan="' . count($current_privileges) . '"';
1677 $html_output .= '>'
1678 . htmlspecialchars($current_host) . '</td>' . "\n";
1679 for ($i = 0; $i < count($current_privileges); $i++) {
1680 $current = $current_privileges[$i];
1681 $html_output .= '<td>' . "\n"
1682 . ' ';
1683 if (! isset($current['Db']) || $current['Db'] == '*') {
1684 $html_output .= __('global');
1685 } elseif (
1686 $current['Db'] == PMA_Util::escapeMysqlWildcards(
1687 $_REQUEST['checkprivs']
1690 $html_output .= __('database-specific');
1691 } else {
1692 $html_output .= __('wildcard'). ': '
1693 . '<code>' . htmlspecialchars($current['Db']) . '</code>';
1695 $html_output .= "\n"
1696 . '</td>' . "\n";
1698 $html_output .='<td>' . "\n"
1699 . '<code>' . "\n"
1700 . ''
1701 . join(
1702 ',' . "\n" . ' ',
1703 PMA_extractPrivInfo($current, true)
1705 . "\n"
1706 . '</code>' . "\n"
1707 . '</td>' . "\n";
1709 $html_output .= '<td>' . "\n"
1710 . '' . ($current['Grant_priv'] == 'Y' ? __('Yes') : __('No'))
1711 . "\n"
1712 . '</td>' . "\n"
1713 . '<td>' . "\n";
1714 $html_output .= sprintf(
1715 $link_edit,
1716 urlencode($current_user),
1717 urlencode($current_host),
1718 urlencode(
1719 ! (isset($current['Db']) || $current['Db'] == '*') ? '' : $current['Db']
1723 $html_output .= '</td>' . "\n"
1724 . ' </tr>' . "\n";
1725 if (($i + 1) < count($current_privileges)) {
1726 $html_output .= '<tr '
1727 . 'class="noclick ' . ($odd_row ? 'odd' : 'even') . '">'
1728 . "\n";
1731 if (empty($row)) {
1732 break;
1734 $odd_row = ! $odd_row;
1736 } else {
1737 $html_output .= '<tr class="odd">' . "\n"
1738 . '<td colspan="6">' . "\n"
1739 . ' ' . __('No user found.') . "\n"
1740 . '</td>' . "\n"
1741 . '</tr>' . "\n";
1743 $html_output .= '</tbody>' . "\n";
1745 return $html_output;
1749 * Define some standard links
1750 * $link_edit, $link_revoke, $link_export
1752 * @param string $conditional_class if ajaxable 'Ajax' otherwise ''
1754 * @return array with some standard links
1756 function PMA_getStandardLinks($conditional_class)
1758 $link_edit = '<a class="edit_user_anchor ' . $conditional_class . '"'
1759 . ' href="server_privileges.php?'
1760 . str_replace('%', '%%', $GLOBALS['url_query'])
1761 . '&amp;username=%s'
1762 . '&amp;hostname=%s'
1763 . '&amp;dbname=%s'
1764 . '&amp;tablename=%s">'
1765 . PMA_Util::getIcon('b_usredit.png', __('Edit Privileges'))
1766 . '</a>';
1768 $link_revoke = '<a href='
1769 .'"server_privileges.php?'
1770 . str_replace('%', '%%', $GLOBALS['url_query'])
1771 . '&amp;username=%s'
1772 . '&amp;hostname=%s'
1773 . '&amp;dbname=%s'
1774 . '&amp;tablename=%s'
1775 . '&amp;revokeall=1">'
1776 . PMA_Util::getIcon('b_usrdrop.png', __('Revoke'))
1777 . '</a>';
1779 $link_export = '<a class="export_user_anchor ' . $conditional_class . '"'
1780 . ' href="server_privileges.php?'
1781 . str_replace('%', '%%', $GLOBALS['url_query'])
1782 . '&amp;username=%s'
1783 . '&amp;hostname=%s'
1784 . '&amp;initial=%s'
1785 . '&amp;export=1">'
1786 . PMA_Util::getIcon('b_tblexport.png', __('Export'))
1787 . '</a>';
1789 return array($link_edit, $link_revoke, $link_export);
1793 * This function return the extra data array for the ajax behavior
1795 * @param string $password password
1796 * @param string $link_export export link
1797 * @param string $sql_query sql query
1798 * @param string $link_edit standard link for edit
1799 * @param string $hostname hostname
1800 * @param string $username username
1802 * @return array $extra_data
1804 function PMA_getExtraDataForAjaxBehavior($password, $link_export, $sql_query,
1805 $link_edit, $hostname, $username
1807 if (isset($GLOBALS['dbname'])) {
1808 //if (preg_match('/\\\\(?:_|%)/i', $dbname)) {
1809 if (preg_match('/(?<!\\\\)(?:_|%)/i', $GLOBALS['dbname'])) {
1810 $dbname_is_wildcard = true;
1811 } else {
1812 $dbname_is_wildcard = false;
1816 $extra_data = array();
1817 if (strlen($sql_query)) {
1818 $extra_data['sql_query']
1819 = PMA_Util::getMessage(null, $sql_query);
1822 if (isset($_REQUEST['adduser_submit']) || isset($_REQUEST['change_copy'])) {
1824 * generate html on the fly for the new user that was just created.
1826 $new_user_string = '<tr>'."\n"
1827 . '<td> <input type="checkbox" name="selected_usr[]" '
1828 . 'id="checkbox_sel_users_"'
1829 . 'value="'
1830 . htmlspecialchars($username)
1831 . '&amp;#27;' . htmlspecialchars($hostname) . '" />'
1832 . '</td>' . "\n"
1833 . '<td><label for="checkbox_sel_users_">'
1834 . (empty($_REQUEST['username'])
1835 ? '<span style="color: #FF0000">' . __('Any') . '</span>'
1836 : htmlspecialchars($username) ) . '</label></td>' . "\n"
1837 . '<td>' . htmlspecialchars($hostname) . '</td>' . "\n";
1839 $new_user_string .= '<td>';
1841 if (! empty($password) || isset($_POST['pma_pw'])) {
1842 $new_user_string .= __('Yes');
1843 } else {
1844 $new_user_string .= '<span style="color: #FF0000">'
1845 . __('No')
1846 . '</span>';
1849 $new_user_string .= '</td>'."\n";
1850 $new_user_string .= '<td>'
1851 . '<code>' . join(', ', PMA_extractPrivInfo('', true)) . '</code>'
1852 . '</td>'; //Fill in privileges here
1853 $new_user_string .= '<td>';
1855 if ((isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y')) {
1856 $new_user_string .= __('Yes');
1857 } else {
1858 $new_user_string .= __('No');
1861 $new_user_string .='</td>';
1863 $new_user_string .= '<td>'
1864 . sprintf(
1865 $link_edit,
1866 urlencode($username),
1867 urlencode($hostname),
1871 . '</td>' . "\n";
1872 $new_user_string .= '<td>'
1873 . sprintf(
1874 $link_export,
1875 urlencode($username),
1876 urlencode($hostname),
1877 (isset($_GET['initial']) ? $_GET['initial'] : '')
1879 . '</td>' . "\n";
1881 $new_user_string .= '</tr>';
1883 $extra_data['new_user_string'] = $new_user_string;
1886 * Generate the string for this alphabet's initial, to update the user
1887 * pagination
1889 $new_user_initial = strtoupper(substr($username, 0, 1));
1890 $new_user_initial_string = '<a href="server_privileges.php?'
1891 . $GLOBALS['url_query'] . '&initial=' . $new_user_initial .'">'
1892 . $new_user_initial . '</a>';
1893 $extra_data['new_user_initial'] = $new_user_initial;
1894 $extra_data['new_user_initial_string'] = $new_user_initial_string;
1897 if (isset($_POST['update_privs'])) {
1898 $extra_data['db_specific_privs'] = false;
1899 $extra_data['db_wildcard_privs'] = false;
1900 if (isset($dbname_is_wildcard)) {
1901 $extra_data['db_specific_privs'] = ! $dbname_is_wildcard;
1902 $extra_data['db_wildcard_privs'] = $dbname_is_wildcard;
1904 $new_privileges = join(', ', PMA_extractPrivInfo('', true));
1906 $extra_data['new_privileges'] = $new_privileges;
1908 return $extra_data;
1912 * Get the HTML snippet for change user login information
1914 * @param string $username username
1915 * @param string $hostname host name
1917 * @return string HTML snippet
1919 function PMA_getChangeLoginInformationHtmlForm($username, $hostname)
1921 $choices = array(
1922 '4' => __('… keep the old one.'),
1923 '1' => __('… delete the old one from the user tables.'),
1924 '2' => __('… revoke all active privileges from the old one and delete it afterwards.'),
1925 '3' => __('… delete the old one from the user tables and reload the privileges afterwards.'));
1927 $class = ' ajax';
1928 $html_output = '<form action="server_privileges.php" '
1929 . 'method="post" class="copyUserForm' . $class .'">' . "\n"
1930 . PMA_generate_common_hidden_inputs('', '')
1931 . '<input type="hidden" name="old_username" '
1932 . 'value="' . htmlspecialchars($username) . '" />' . "\n"
1933 . '<input type="hidden" name="old_hostname" '
1934 . 'value="' . htmlspecialchars($hostname) . '" />' . "\n"
1935 . '<fieldset id="fieldset_change_copy_user">' . "\n"
1936 . '<legend>' . __('Change Login Information / Copy User')
1937 . '</legend>' . "\n"
1938 . PMA_getHtmlForDisplayLoginInformationFields('change');
1940 $html_output .= '<fieldset id="fieldset_mode">' . "\n"
1941 . ' <legend>'
1942 . __('Create a new user with the same privileges and …')
1943 . '</legend>' . "\n";
1944 $html_output .= PMA_Util::getRadioFields(
1945 'mode', $choices, '4', true
1947 $html_output .= '</fieldset>' . "\n"
1948 . '</fieldset>' . "\n";
1950 $html_output .= '<fieldset id="fieldset_change_copy_user_footer" '
1951 . 'class="tblFooters">' . "\n"
1952 . '<input type="submit" name="change_copy" '
1953 . 'value="' . __('Go') . '" />' . "\n"
1954 . '</fieldset>' . "\n"
1955 . '</form>' . "\n";
1957 return $html_output;
1961 * Provide a line with links to the relevant database and table
1963 * @param string $url_dbname url database name that urlencode() string
1964 * @param string $dbname database name
1965 * @param string $tablename table name
1967 * @return string HTML snippet
1969 function PMA_getLinkToDbAndTable($url_dbname, $dbname, $tablename)
1971 $html_output = '[ ' . __('Database')
1972 . ' <a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?'
1973 . $GLOBALS['url_query'] . '&amp;db=' . $url_dbname . '&amp;reload=1">'
1974 . htmlspecialchars($dbname) . ': '
1975 . PMA_Util::getTitleForTarget(
1976 $GLOBALS['cfg']['DefaultTabDatabase']
1978 . "</a> ]\n";
1980 if (strlen($tablename)) {
1981 $html_output .= ' [ ' . __('Table') . ' <a href="'
1982 . $GLOBALS['cfg']['DefaultTabTable'] . '?' . $GLOBALS['url_query']
1983 . '&amp;db=' . $url_dbname
1984 . '&amp;table=' . htmlspecialchars(urlencode($tablename))
1985 . '&amp;reload=1">' . htmlspecialchars($tablename) . ': '
1986 . PMA_Util::getTitleForTarget(
1987 $GLOBALS['cfg']['DefaultTabTable']
1989 . "</a> ]\n";
1991 return $html_output;
1995 * no db name given, so we want all privs for the given user
1996 * db name was given, so we want all user specific rights for this db
1997 * So this function returns user rights as an array
1999 * @param array $tables tables
2000 * @param string $user_host_condition a where clause that containd user's host condition
2001 * @param string $dbname database name
2003 * @return array $db_rights database rights
2005 function PMA_getUserSpecificRights($tables, $user_host_condition, $dbname)
2007 if (! strlen($dbname)) {
2008 $tables_to_search_for_users = array(
2009 'tables_priv', 'columns_priv',
2011 $dbOrTableName = 'Db';
2012 } else {
2013 $user_host_condition .=
2014 ' AND `Db`'
2015 .' LIKE \''
2016 . PMA_Util::sqlAddSlashes($dbname, true) . "'";
2017 $tables_to_search_for_users = array('columns_priv',);
2018 $dbOrTableName = 'Table_name';
2021 $db_rights_sqls = array();
2022 foreach ($tables_to_search_for_users as $table_search_in) {
2023 if (in_array($table_search_in, $tables)) {
2024 $db_rights_sqls[] = '
2025 SELECT DISTINCT `' . $dbOrTableName .'`
2026 FROM `mysql`.' . PMA_Util::backquote($table_search_in)
2027 . $user_host_condition;
2031 $user_defaults = array(
2032 $dbOrTableName => '',
2033 'Grant_priv' => 'N',
2034 'privs' => array('USAGE'),
2035 'Column_priv' => true,
2038 // for the rights
2039 $db_rights = array();
2041 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
2042 .' ORDER BY `' . $dbOrTableName .'` ASC';
2044 $db_rights_result = PMA_DBI_query($db_rights_sql);
2046 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
2047 $db_rights_row = array_merge($user_defaults, $db_rights_row);
2048 if (! strlen($dbname)) {
2049 // only Db names in the table `mysql`.`db` uses wildcards
2050 // as we are in the db specific rights display we want
2051 // all db names escaped, also from other sources
2052 $db_rights_row['Db'] = PMA_Util::escapeMysqlWildcards(
2053 $db_rights_row['Db']
2056 $db_rights[$db_rights_row[$dbOrTableName]] = $db_rights_row;
2059 PMA_DBI_free_result($db_rights_result);
2061 if (! strlen($dbname)) {
2062 $sql_query = 'SELECT * FROM `mysql`.`db`'
2063 . $user_host_condition . ' ORDER BY `Db` ASC';
2064 } else {
2065 $sql_query = 'SELECT `Table_name`,'
2066 .' `Table_priv`,'
2067 .' IF(`Column_priv` = _latin1 \'\', 0, 1)'
2068 .' AS \'Column_priv\''
2069 .' FROM `mysql`.`tables_priv`'
2070 . $user_host_condition
2071 .' ORDER BY `Table_name` ASC;';
2074 $result = PMA_DBI_query($sql_query);
2075 $sql_query = '';
2077 while ($row = PMA_DBI_fetch_assoc($result)) {
2078 if (isset($db_rights[$row[$dbOrTableName]])) {
2079 $db_rights[$row[$dbOrTableName]]
2080 = array_merge($db_rights[$row[$dbOrTableName]], $row);
2081 } else {
2082 $db_rights[$row[$dbOrTableName]] = $row;
2084 if (! strlen($dbname)) {
2085 // there are db specific rights for this user
2086 // so we can drop this db rights
2087 $db_rights[$row['Db']]['can_delete'] = true;
2090 PMA_DBI_free_result($result);
2091 return $db_rights;
2095 * Display user rights in table rows(Table specific or database specific privs)
2097 * @param array $db_rights user's database rights array
2098 * @param string $link_edit standard link to edit privileges
2099 * @param string $dbname database name
2100 * @param string $link_revoke standard link to revoke
2101 * @param string $hostname host name
2102 * @param string $username username
2104 * @return array $found_rows, $html_output
2106 function PMA_getHtmlForDisplayUserRightsInRows($db_rights, $link_edit, $dbname,
2107 $link_revoke, $hostname, $username
2109 $html_output = '';
2110 $found_rows = array();
2111 // display rows
2112 if (count($db_rights) < 1) {
2113 $html_output .= '<tr class="odd">' . "\n"
2114 . '<td colspan="6"><center><i>' . __('None') . '</i></center></td>' . "\n"
2115 . '</tr>' . "\n";
2116 } else {
2117 $odd_row = true;
2118 //while ($row = PMA_DBI_fetch_assoc($res)) {
2119 foreach ($db_rights as $row) {
2120 $found_rows[] = (! strlen($dbname)) ? $row['Db'] : $row['Table_name'];
2122 $html_output .= '<tr class="' . ($odd_row ? 'odd' : 'even') . '">' . "\n"
2123 . '<td>'
2124 . htmlspecialchars(
2125 (! strlen($dbname)) ? $row['Db'] : $row['Table_name']
2127 . '</td>' . "\n"
2128 . '<td><code>' . "\n"
2129 . ' '
2130 . join(
2131 ',' . "\n" . ' ',
2132 PMA_extractPrivInfo($row, true)
2133 ) . "\n"
2134 . '</code></td>' . "\n"
2135 . '<td>'
2136 . ((((! strlen($dbname)) && $row['Grant_priv'] == 'Y')
2137 || (strlen($dbname) && in_array('Grant', explode(',', $row['Table_priv']))))
2138 ? __('Yes')
2139 : __('No'))
2140 . '</td>' . "\n"
2141 . '<td>';
2142 if (! empty($row['Table_privs']) || ! empty ($row['Column_priv'])) {
2143 $html_output .= __('Yes');
2144 } else {
2145 $html_output .= __('No');
2147 $html_output .= '</td>' . "\n"
2148 . '<td>';
2149 $html_output .= sprintf(
2150 $link_edit,
2151 htmlspecialchars(urlencode($username)),
2152 urlencode(htmlspecialchars($hostname)),
2153 urlencode(
2154 (! strlen($dbname)) ? $row['Db'] : htmlspecialchars($dbname)
2156 urlencode((! strlen($dbname)) ? '' : $row['Table_name'])
2158 $html_output .= '</td>' . "\n"
2159 . ' <td>';
2160 if (! empty($row['can_delete'])
2161 || isset($row['Table_name'])
2162 && strlen($row['Table_name'])
2164 $html_output .= sprintf(
2165 $link_revoke,
2166 htmlspecialchars(urlencode($username)),
2167 urlencode(htmlspecialchars($hostname)),
2168 urlencode(
2169 (! strlen($dbname)) ? $row['Db'] : htmlspecialchars($dbname)
2171 urlencode((! strlen($dbname)) ? '' : $row['Table_name'])
2174 $html_output .= '</td>' . "\n"
2175 . '</tr>' . "\n";
2176 $odd_row = ! $odd_row;
2177 } // end while
2178 } //end if
2179 return array($found_rows, $html_output);
2183 * Get a HTML table for display user's tabel specific or database specific rights
2185 * @param string $username username
2186 * @param string $hostname host name
2187 * @param string $link_edit standard link to edit privileges
2188 * @param string $link_revoke standard link to revoke
2189 * @param string $dbname database name
2191 * @return array $html_output, $found_rows
2193 function PMA_getTableForDisplayAllTableSpecificRights($username, $hostname
2194 , $link_edit, $link_revoke, $dbname
2196 // table header
2197 $html_output = PMA_generate_common_hidden_inputs('', '')
2198 . '<input type="hidden" name="username" '
2199 . 'value="' . htmlspecialchars($username) . '" />' . "\n"
2200 . '<input type="hidden" name="hostname" '
2201 . 'value="' . htmlspecialchars($hostname) . '" />' . "\n"
2202 . '<fieldset>' . "\n"
2203 . '<legend>'
2204 . (! strlen($dbname)
2205 ? __('Database-specific privileges')
2206 : __('Table-specific privileges')
2208 . '</legend>' . "\n"
2209 . '<table class="data">' . "\n"
2210 . '<thead>' . "\n"
2211 . '<tr><th>'
2212 . (! strlen($dbname) ? __('Database') : __('Table'))
2213 . '</th>' . "\n"
2214 . '<th>' . __('Privileges') . '</th>' . "\n"
2215 . '<th>' . __('Grant') . '</th>' . "\n"
2216 . '<th>'
2217 . (! strlen($dbname)
2218 ? __('Table-specific privileges')
2219 : __('Column-specific privileges')
2221 . '</th>' . "\n"
2222 . '<th colspan="2">' . __('Action') . '</th>' . "\n"
2223 . '</tr>' . "\n"
2224 . '</thead>' . "\n";
2226 $user_host_condition = ' WHERE `User`'
2227 . ' = \'' . PMA_Util::sqlAddSlashes($username) . "'"
2228 . ' AND `Host`'
2229 . ' = \'' . PMA_Util::sqlAddSlashes($hostname) . "'";
2231 // table body
2232 // get data
2234 // we also want privielgs for this user not in table `db` but in other table
2235 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
2238 * no db name given, so we want all privs for the given user
2239 * db name was given, so we want all user specific rights for this db
2241 $db_rights = PMA_getUserSpecificRights($tables, $user_host_condition, $dbname);
2243 ksort($db_rights);
2245 $html_output .= '<tbody>' . "\n";
2246 // display rows
2247 list ($found_rows, $html_out) = PMA_getHtmlForDisplayUserRightsInRows(
2248 $db_rights, $link_edit, $dbname, $link_revoke, $hostname, $username
2251 $html_output .= $html_out;
2252 $html_output .= '</tbody>' . "\n";
2253 $html_output .='</table>' . "\n";
2255 return array($html_output, $found_rows);
2259 * Get HTML for display select db
2261 * @param array $found_rows isset($dbname)) ? $row['Db'] : $row['Table_name']
2263 * @return string HTML snippet
2265 function PMA_getHtmlForDisplaySelectDbInEditPrivs($found_rows)
2267 $pred_db_array = PMA_DBI_fetch_result('SHOW DATABASES;');
2269 $html_output = '<label for="text_dbname">'
2270 . __('Add privileges on the following database') . ':</label>' . "\n";
2271 if (! empty($pred_db_array)) {
2272 $html_output .= '<select name="pred_dbname" class="autosubmit">' . "\n"
2273 . '<option value="" selected="selected">'
2274 . __('Use text field') . ':</option>' . "\n";
2275 foreach ($pred_db_array as $current_db) {
2276 $current_db_show = $current_db;
2277 $current_db = PMA_Util::escapeMysqlWildcards($current_db);
2278 // cannot use array_diff() once, outside of the loop,
2279 // because the list of databases has special characters
2280 // already escaped in $found_rows,
2281 // contrary to the output of SHOW DATABASES
2282 if (empty($found_rows) || ! in_array($current_db, $found_rows)) {
2283 $html_output .= '<option value="' . htmlspecialchars($current_db) . '">'
2284 . htmlspecialchars($current_db_show) . '</option>' . "\n";
2287 $html_output .= '</select>' . "\n";
2289 $html_output .= '<input type="text" id="text_dbname" name="dbname" />' . "\n"
2290 . PMA_Util::showHint(
2291 __('Wildcards % and _ should be escaped with a \ to use them literally')
2293 return $html_output;
2297 * Get HTML for display table in edit privilege
2299 * @param string $dbname database naame
2300 * @param array $found_rows isset($dbname)) ? $row['Db'] : $row['Table_name']
2302 * @return string HTML snippet
2304 function PMA_displayTablesInEditPrivs($dbname, $found_rows)
2306 $html_output = '<input type="hidden" name="dbname"
2307 '. 'value="' . htmlspecialchars($dbname) . '"/>' . "\n";
2308 $html_output .= '<label for="text_tablename">'
2309 . __('Add privileges on the following table') . ':</label>' . "\n";
2311 $result = @PMA_DBI_try_query(
2312 'SHOW TABLES FROM ' . PMA_Util::backquote(
2313 PMA_Util::unescapeMysqlWildcards($dbname)
2314 ) . ';',
2315 null,
2316 PMA_DBI_QUERY_STORE
2319 if ($result) {
2320 $pred_tbl_array = array();
2321 while ($row = PMA_DBI_fetch_row($result)) {
2322 if (! isset($found_rows) || ! in_array($row[0], $found_rows)) {
2323 $pred_tbl_array[] = $row[0];
2326 PMA_DBI_free_result($result);
2328 if (! empty($pred_tbl_array)) {
2329 $html_output .= '<select name="pred_tablename" '
2330 . 'class="autosubmit">' . "\n"
2331 . '<option value="" selected="selected">' . __('Use text field')
2332 . ':</option>' . "\n";
2333 foreach ($pred_tbl_array as $current_table) {
2334 $html_output .= '<option '
2335 . 'value="' . htmlspecialchars($current_table) . '">'
2336 . htmlspecialchars($current_table)
2337 . '</option>' . "\n";
2339 $html_output .= '</select>' . "\n";
2342 $html_output .= '<input type="text" id="text_tablename" name="tablename" />'
2343 . "\n";
2345 return $html_output;
2349 * Get HTML for display the users overview
2350 * (if less than 50 users, display them immediately)
2352 * @param array $result ran sql query
2353 * @param array $db_rights user's database rights array
2354 * @param string $link_edit standard link to edit privileges
2355 * @param string $pmaThemeImage a image source link
2356 * @param string $text_dir text directory
2357 * @param string $conditional_class if ajaxable 'Ajax' otherwise ''
2358 * @param string $link_export standard link to export privileges
2360 * @return string HTML snippet
2362 function PMA_getUsersOverview($result, $db_rights, $link_edit, $pmaThemeImage,
2363 $text_dir, $conditional_class, $link_export
2365 while ($row = PMA_DBI_fetch_assoc($result)) {
2366 $row['privs'] = PMA_extractPrivInfo($row, true);
2367 $db_rights[$row['User']][$row['Host']] = $row;
2369 @PMA_DBI_free_result($result);
2371 $html_output
2372 = '<form name="usersForm" id="usersForm" action="server_privileges.php" '
2373 . 'method="post">' . "\n"
2374 . PMA_generate_common_hidden_inputs('', '')
2375 . '<table id="tableuserrights" class="data">' . "\n"
2376 . '<thead>' . "\n"
2377 . '<tr><th></th>' . "\n"
2378 . '<th>' . __('User') . '</th>' . "\n"
2379 . '<th>' . __('Host') . '</th>' . "\n"
2380 . '<th>' . __('Password') . '</th>' . "\n"
2381 . '<th>' . __('Global privileges') . ' '
2382 . PMA_Util::showHint(
2383 __('Note: MySQL privilege names are expressed in English')
2385 . '</th>' . "\n"
2386 . '<th>' . __('Grant') . '</th>' . "\n"
2387 . '<th colspan="2">' . __('Action') . '</th>' . "\n"
2388 . '</tr>' . "\n"
2389 . '</thead>' . "\n";
2391 $html_output .= '<tbody>' . "\n";
2392 $html_output .= PMA_getTableBodyForUserRightsTable(
2393 $db_rights, $link_edit, $link_export
2395 $html_output .= '</tbody>'
2396 . '</table>' . "\n";
2398 $html_output .= '<div style="float:left;">'
2399 .'<img class="selectallarrow"'
2400 .' src="' . $pmaThemeImage . 'arrow_' . $text_dir . '.png"'
2401 .' width="38" height="22"'
2402 .' alt="' . __('With selected:') . '" />' . "\n"
2403 .'<input type="checkbox" id="checkall" title="' . __('Check All') . '" /> '
2404 .'<label for="checkall">' . __('Check All') . '</label> '
2405 .'<i style="margin-left: 2em">' . __('With selected:') . '</i>' . "\n";
2407 $html_output .= PMA_Util::getButtonOrImage(
2408 'submit_mult', 'mult_submit', 'submit_mult_export',
2409 __('Export'), 'b_tblexport.png', 'export'
2411 $html_output .= '<input type="hidden" name="initial" '
2412 . 'value="' . (isset($_GET['initial']) ? $_GET['initial'] : '') . '" />';
2413 $html_output .= '</div>'
2414 . '<div class="clear_both" style="clear:both"></div>';
2416 // add/delete user fieldset
2417 $html_output .= PMA_getFieldsetForAddDeleteUser($conditional_class);
2418 $html_output .= '</form>' . "\n";
2420 return $html_output;
2424 * Get table body for 'tableuserrights' table in userform
2426 * @param array $db_rights user's database rights array
2427 * @param string $link_edit standard link to edit privileges
2428 * @param string $link_export Link for export all users
2430 * @return string HTML snippet
2432 function PMA_getTableBodyForUserRightsTable($db_rights, $link_edit, $link_export)
2434 $odd_row = true;
2435 $index_checkbox = -1;
2436 $html_output = '';
2437 foreach ($db_rights as $user) {
2438 $index_checkbox++;
2439 ksort($user);
2440 foreach ($user as $host) {
2441 $index_checkbox++;
2442 $html_output .= '<tr class="' . ($odd_row ? 'odd' : 'even') . '">'
2443 . "\n";
2444 $html_output .= '<td>'
2445 . '<input type="checkbox" class="checkall" name="selected_usr[]" '
2446 . 'id="checkbox_sel_users_'
2447 . $index_checkbox . '" value="'
2448 . htmlspecialchars($host['User'] . '&amp;#27;' . $host['Host'])
2449 . '"'
2450 . ' /></td>' . "\n";
2452 $html_output .= '<td><label '
2453 . 'for="checkbox_sel_users_' . $index_checkbox . '">'
2454 . (empty($host['User'])
2455 ? '<span style="color: #FF0000">' . __('Any') . '</span>'
2456 : htmlspecialchars($host['User'])) . '</label></td>' . "\n"
2457 . '<td>' . htmlspecialchars($host['Host']) . '</td>' . "\n";
2459 $html_output .= '<td>';
2460 switch ($host['Password']) {
2461 case 'Y':
2462 $html_output .= __('Yes');
2463 break;
2464 case 'N':
2465 $html_output .= '<span style="color: #FF0000">' . __('No')
2466 . '</span>';
2467 break;
2468 // this happens if this is a definition not coming from mysql.user
2469 default:
2470 $html_output .= '--'; // in future version, replace by "not present"
2471 break;
2472 } // end switch
2473 $html_output .= '</td>' . "\n";
2475 $html_output .= '<td><code>' . "\n"
2476 . '' . implode(',' . "\n" . ' ', $host['privs']) . "\n"
2477 . '</code></td>' . "\n"
2478 . '<td>'
2479 . ($host['Grant_priv'] == 'Y' ? __('Yes') : __('No'))
2480 . '</td>' . "\n"
2481 . '<td class="center">'
2482 . sprintf(
2483 $link_edit,
2484 urlencode($host['User']),
2485 urlencode($host['Host']),
2489 $html_output .= '</td>';
2491 $html_output .= '<td class="center">';
2492 $html_output .= sprintf(
2493 $link_export,
2494 urlencode($host['User']),
2495 urlencode($host['Host']),
2496 (isset($_GET['initial']) ? $_GET['initial'] : '')
2498 $html_output .= '</td>';
2499 $html_output .= '</tr>';
2500 $odd_row = ! $odd_row;
2503 return $html_output;
2507 * Get HTML fieldset for Add/Delete user
2509 * @param string $conditional_class if ajaxable 'Ajax' otherwise ''
2511 * @return string HTML snippet
2513 function PMA_getFieldsetForAddDeleteUser($conditional_class)
2515 $html_output = '<fieldset id="fieldset_add_user">' . "\n";
2516 $html_output .= '<a href="server_privileges.php?'
2517 . $GLOBALS['url_query'] . '&amp;adduser=1"'
2518 . 'class="' . $conditional_class . '">' . "\n"
2519 . PMA_Util::getIcon('b_usradd.png')
2520 . ' ' . __('Add user') . '</a>' . "\n";
2521 $html_output .= '</fieldset>' . "\n";
2523 $html_output .= '<fieldset id="fieldset_delete_user">'
2524 . '<legend>' . "\n"
2525 . PMA_Util::getIcon('b_usrdrop.png')
2526 . ' ' . __('Remove selected users') . '' . "\n"
2527 . '</legend>' . "\n";
2529 $html_output .= '<input type="hidden" name="mode" value="2" />' . "\n"
2530 . '(' . __('Revoke all active privileges from the users and delete them afterwards.') . ')'
2531 . '<br />' . "\n";
2533 $html_output .= '<input type="checkbox" '
2534 . 'title="' . __('Drop the databases that have the same names as the users.') . '" '
2535 . 'name="drop_users_db" id="checkbox_drop_users_db" />' . "\n";
2537 $html_output .= '<label for="checkbox_drop_users_db" '
2538 . 'title="' . __('Drop the databases that have the same names as the users.') . '">' . "\n"
2539 . ' ' . __('Drop the databases that have the same names as the users.') . "\n"
2540 . '</label>' . "\n"
2541 . '</fieldset>' . "\n";
2543 $html_output .= '<fieldset id="fieldset_delete_user_footer" class="tblFooters">' . "\n";
2544 $html_output .= '<input type="submit" name="delete" '
2545 . 'value="' . __('Go') . '" id="buttonGo" '
2546 . 'class="' . $conditional_class . '"/>' . "\n";
2548 $html_output .= '</fieldset>' . "\n";
2550 return $html_output;
2554 * Get HTML for Displays the initials
2556 * @param array $array_initials array for all initials, even non A-Z
2557 * @param string $conditional_class if ajaxable 'Ajax' otherwise ''
2559 * @return string HTML snippet
2561 function PMA_getHtmlForDisplayTheInitials($array_initials, $conditional_class)
2563 // initialize to false the letters A-Z
2564 for ($letter_counter = 1; $letter_counter < 27; $letter_counter++) {
2565 if (! isset($array_initials[chr($letter_counter + 64)])) {
2566 $array_initials[chr($letter_counter + 64)] = false;
2570 $initials = PMA_DBI_try_query(
2571 'SELECT DISTINCT UPPER(LEFT(`User`,1)) FROM `user` ORDER BY `User` ASC',
2572 null,
2573 PMA_DBI_QUERY_STORE
2575 while (list($tmp_initial) = PMA_DBI_fetch_row($initials)) {
2576 $array_initials[$tmp_initial] = true;
2579 // Display the initials, which can be any characters, not
2580 // just letters. For letters A-Z, we add the non-used letters
2581 // as greyed out.
2583 uksort($array_initials, "strnatcasecmp");
2585 $html_output = '<table id="initials_table" <cellspacing="5">'
2586 . '<tr>';
2587 foreach ($array_initials as $tmp_initial => $initial_was_found) {
2588 if (! empty($tmp_initial)) {
2589 if ($initial_was_found) {
2590 $html_output .= '<td>'
2591 . '<a class="' . $conditional_class . '"'
2592 . ' href="server_privileges.php?'
2593 . $GLOBALS['url_query'] . '&amp;'
2594 . 'initial=' . urlencode($tmp_initial) . '">' . $tmp_initial
2595 . '</a>'
2596 . '</td>' . "\n";
2597 } else {
2598 $html_output .= '<td>' . $tmp_initial . '</td>';
2602 $html_output .= '<td>'
2603 . '<a href="server_privileges.php?' . $GLOBALS['url_query']
2604 . '&amp;showall=1" '
2605 . 'class="nowrap">[' . __('Show all') . ']</a></td>' . "\n";
2606 $html_output .= '</tr></table>';
2608 return $html_output;
2612 * Get the database rigths array for Display user overview
2614 * @return array $db_rights database rights array
2616 function PMA_getDbRightsForUserOverview()
2618 // we also want users not in table `user` but in other table
2619 $tables = PMA_DBI_fetch_result('SHOW TABLES FROM `mysql`;');
2621 $tables_to_search_for_users = array(
2622 'user', 'db', 'tables_priv', 'columns_priv', 'procs_priv',
2625 $db_rights_sqls = array();
2626 foreach ($tables_to_search_for_users as $table_search_in) {
2627 if (in_array($table_search_in, $tables)) {
2628 $db_rights_sqls[] = 'SELECT DISTINCT `User`, `Host` FROM `mysql`.`'
2629 . $table_search_in . '` '
2630 . (isset($_GET['initial']) ? PMA_rangeOfUsers($_GET['initial']) : '');
2633 $user_defaults = array(
2634 'User' => '',
2635 'Host' => '%',
2636 'Password' => '?',
2637 'Grant_priv' => 'N',
2638 'privs' => array('USAGE'),
2641 // for the rights
2642 $db_rights = array();
2644 $db_rights_sql = '(' . implode(') UNION (', $db_rights_sqls) . ')'
2645 .' ORDER BY `User` ASC, `Host` ASC';
2647 $db_rights_result = PMA_DBI_query($db_rights_sql);
2649 while ($db_rights_row = PMA_DBI_fetch_assoc($db_rights_result)) {
2650 $db_rights_row = array_merge($user_defaults, $db_rights_row);
2651 $db_rights[$db_rights_row['User']][$db_rights_row['Host']]
2652 = $db_rights_row;
2654 PMA_DBI_free_result($db_rights_result);
2655 ksort($db_rights);
2657 return $db_rights;
2661 * Delete user and get message and sql query for delete user in privileges
2663 * @param string $queries queries
2665 * @return PMA_message
2667 function PMA_deleteUser($queries)
2669 if (empty($queries)) {
2670 $message = PMA_Message::error(__('No users selected for deleting!'));
2671 } else {
2672 if ($_REQUEST['mode'] == 3) {
2673 $queries[] = '# ' . __('Reloading the privileges') . ' …';
2674 $queries[] = 'FLUSH PRIVILEGES;';
2676 $drop_user_error = '';
2677 foreach ($queries as $sql_query) {
2678 if ($sql_query{0} != '#') {
2679 if (! PMA_DBI_try_query($sql_query, $GLOBALS['userlink'])) {
2680 $drop_user_error .= PMA_DBI_getError() . "\n";
2684 // tracking sets this, causing the deleted db to be shown in navi
2685 unset($GLOBALS['db']);
2687 $sql_query = join("\n", $queries);
2688 if (! empty($drop_user_error)) {
2689 $message = PMA_Message::rawError($drop_user_error);
2690 } else {
2691 $message = PMA_Message::success(
2692 __('The selected users have been deleted successfully.')
2696 return array($sql_query, $message);
2700 * Update the privileges and return the success or error message
2702 * @param string $username username
2703 * @param string $hostname host name
2704 * @param string $tablename table name
2705 * @param string $dbname database name
2707 * @return PMA_message success message or error message for update
2709 function PMA_updatePrivileges($username, $hostname, $tablename, $dbname)
2711 $db_and_table = PMA_wildcardEscapeForGrant($dbname, $tablename);
2713 $sql_query0 = 'REVOKE ALL PRIVILEGES ON ' . $db_and_table
2714 . ' FROM \'' . PMA_Util::sqlAddSlashes($username)
2715 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
2717 if (! isset($_POST['Grant_priv']) || $_POST['Grant_priv'] != 'Y') {
2718 $sql_query1 = 'REVOKE GRANT OPTION ON ' . $db_and_table
2719 . ' FROM \'' . PMA_Util::sqlAddSlashes($username) . '\'@\''
2720 . PMA_Util::sqlAddSlashes($hostname) . '\';';
2721 } else {
2722 $sql_query1 = '';
2725 // Should not do a GRANT USAGE for a table-specific privilege, it
2726 // causes problems later (cannot revoke it)
2727 if (! (strlen($tablename) && 'USAGE' == implode('', PMA_extractPrivInfo()))) {
2728 $sql_query2 = 'GRANT ' . join(', ', PMA_extractPrivInfo())
2729 . ' ON ' . $db_and_table
2730 . ' TO \'' . PMA_Util::sqlAddSlashes($username) . '\'@\''
2731 . PMA_Util::sqlAddSlashes($hostname) . '\'';
2733 if ((isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y')
2734 || (! strlen($dbname)
2735 && (isset($_POST['max_questions']) || isset($_POST['max_connections'])
2736 || isset($_POST['max_updates']) || isset($_POST['max_user_connections'])))
2738 $sql_query2 .= PMA_getWithClauseForAddUserAndUpdatePrivs();
2740 $sql_query2 .= ';';
2742 if (! PMA_DBI_try_query($sql_query0)) {
2743 // This might fail when the executing user does not have
2744 // ALL PRIVILEGES himself.
2745 // See https://sourceforge.net/p/phpmyadmin/bugs/3270/
2746 $sql_query0 = '';
2748 if (isset($sql_query1) && ! PMA_DBI_try_query($sql_query1)) {
2749 // this one may fail, too...
2750 $sql_query1 = '';
2752 if (isset($sql_query2)) {
2753 PMA_DBI_query($sql_query2);
2754 } else {
2755 $sql_query2 = '';
2757 $sql_query = $sql_query0 . ' ' . $sql_query1 . ' ' . $sql_query2;
2758 $message = PMA_Message::success(__('You have updated the privileges for %s.'));
2759 $message->addParam(
2760 '\'' . htmlspecialchars($username) . '\'@\'' . htmlspecialchars($hostname) . '\''
2763 return array($sql_query, $message);
2767 * Get title and textarea for export user definition in Privileges
2769 * @param string $username username
2770 * @param string $hostname host name
2772 * @return array ($title, $export)
2774 function PMA_getHtmlForExportUserDefinition($username, $hostname)
2776 $export = '<textarea class="export" cols="' . $GLOBALS['cfg']['TextareaCols']
2777 . '" rows="' . $GLOBALS['cfg']['TextareaRows'] . '">';
2779 if (isset($_REQUEST['selected_usr'])) {
2780 // export privileges for selected users
2781 $title = __('Privileges');
2782 foreach ($_REQUEST['selected_usr'] as $export_user) {
2783 $export_username = substr($export_user, 0, strpos($export_user, '&'));
2784 $export_hostname = substr($export_user, strrpos($export_user, ';') + 1);
2785 $export .= '# '
2786 . sprintf(
2787 __('Privileges for %s'),
2788 '`' . htmlspecialchars($export_username)
2789 . '`@`' . htmlspecialchars($export_hostname) . '`'
2791 . "\n\n";
2792 $export .= PMA_getGrants($export_username, $export_hostname) . "\n";
2794 } else {
2795 // export privileges for a single user
2796 $title = __('User') . ' `' . htmlspecialchars($username)
2797 . '`@`' . htmlspecialchars($hostname) . '`';
2798 $export .= PMA_getGrants($username, $hostname);
2800 // remove trailing whitespace
2801 $export = trim($export);
2803 $export .= '</textarea>';
2805 return array($title, $export);
2809 * Get HTML for display Add userfieldset
2811 * @param string $conditional_class if ajaxable 'Ajax' otherwise ''
2813 * @return string html output
2815 function PMA_getAddUserHtmlFieldset($conditional_class)
2817 return '<fieldset id="fieldset_add_user">' . "\n"
2818 . '<a href="server_privileges.php?' . $GLOBALS['url_query']
2819 . '&amp;adduser=1" '
2820 . 'class="' . $conditional_class . '">' . "\n"
2821 . PMA_Util::getIcon('b_usradd.png')
2822 . ' ' . __('Add user') . '</a>' . "\n"
2823 . '</fieldset>' . "\n";
2827 * Get HTML header for display User's properties
2829 * @param boolean $dbname_is_wildcard whether database name is wildcard or not
2830 * @param string $url_dbname url database name that urlencode() string
2831 * @param string $dbname database name
2832 * @param string $username username
2833 * @param string $hostname host name
2834 * @param string $tablename table name
2836 * @return string $html_output
2838 function PMA_getHtmlHeaderForDisplayUserProperties(
2839 $dbname_is_wildcard, $url_dbname, $dbname, $username, $hostname, $tablename
2841 $html_output = '<h2>' . "\n"
2842 . PMA_Util::getIcon('b_usredit.png')
2843 . __('Edit Privileges') . ': '
2844 . __('User');
2846 if (isset($dbname)) {
2847 $html_output .= ' <i><a href="server_privileges.php?'
2848 . $GLOBALS['url_query']
2849 . '&amp;username=' . htmlspecialchars(urlencode($username))
2850 . '&amp;hostname=' . htmlspecialchars(urlencode($hostname))
2851 . '&amp;dbname=&amp;tablename=">\'' . htmlspecialchars($username)
2852 . '\'@\'' . htmlspecialchars($hostname)
2853 . '\'</a></i>' . "\n";
2855 $html_output .= ' - ' . ($dbname_is_wildcard ? __('Databases') : __('Database') );
2856 if (isset($_REQUEST['tablename'])) {
2857 $html_output .= ' <i><a href="server_privileges.php?' . $GLOBALS['url_query']
2858 . '&amp;username=' . htmlspecialchars(urlencode($username))
2859 . '&amp;hostname=' . htmlspecialchars(urlencode($hostname))
2860 . '&amp;dbname=' . htmlspecialchars($url_dbname)
2861 . '&amp;tablename=">' . htmlspecialchars($dbname)
2862 . '</a></i>';
2864 $html_output .= ' - ' . __('Table')
2865 . ' <i>' . htmlspecialchars($tablename) . '</i>';
2866 } else {
2867 $html_output .= ' <i>' . htmlspecialchars($dbname) . '</i>';
2870 } else {
2871 $html_output .= ' <i>\'' . htmlspecialchars($username)
2872 . '\'@\'' . htmlspecialchars($hostname)
2873 . '\'</i>' . "\n";
2876 $html_output .= '</h2>' . "\n";
2878 return $html_output;
2882 * Get HTML snippet for display user overview page
2884 * @param string $link_edit standard link to edit privileges
2885 * @param string $pmaThemeImage a image source link
2886 * @param string $text_dir text directory
2887 * @param string $conditional_class if ajaxable 'Ajax' otherwise ''
2888 * @param string $link_export standard link to export privileges
2890 * @return string $html_output
2892 function PMA_getHtmlForDisplayUserOverviewPage($link_edit, $pmaThemeImage,
2893 $text_dir, $conditional_class, $link_export
2895 $html_output = '<h2>' . "\n"
2896 . PMA_Util::getIcon('b_usrlist.png')
2897 . __('Users overview') . "\n"
2898 . '</h2>' . "\n";
2900 $sql_query = 'SELECT *,' .
2901 " IF(`Password` = _latin1 '', 'N', 'Y') AS 'Password'" .
2902 ' FROM `mysql`.`user`';
2904 $sql_query .= (isset($_REQUEST['initial'])
2905 ? PMA_rangeOfUsers($_REQUEST['initial'])
2906 : '');
2908 $sql_query .= ' ORDER BY `User` ASC, `Host` ASC;';
2909 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
2911 if (! $res) {
2912 // the query failed! This may have two reasons:
2913 // - the user does not have enough privileges
2914 // - the privilege tables use a structure of an earlier version.
2915 // so let's try a more simple query
2917 $sql_query = 'SELECT * FROM `mysql`.`user`';
2918 $res = PMA_DBI_try_query($sql_query, null, PMA_DBI_QUERY_STORE);
2920 if (! $res) {
2921 $html_output .= PMA_Message::error(__('No Privileges'))->getDisplay();
2922 PMA_DBI_free_result($res);
2923 unset($res);
2924 } else {
2925 // This message is hardcoded because I will replace it by
2926 // a automatic repair feature soon.
2927 $raw = 'Your privilege table structure seems to be older than'
2928 . ' this MySQL version!<br />'
2929 . 'Please run the <code>mysql_upgrade</code> command'
2930 . '(<code>mysql_fix_privilege_tables</code> on older systems)'
2931 . ' that should be included in your MySQL server distribution'
2932 . ' to solve this problem!';
2933 $html_output .= PMA_Message::rawError($raw)->getDisplay();
2935 } else {
2936 $db_rights = PMA_getDbRightsForUserOverview();
2937 // for all initials, even non A-Z
2938 $array_initials = array();
2941 * Displays the initials
2942 * Also not necassary if there is less than 20 privileges
2944 if (PMA_DBI_num_rows($res) > 20 ) {
2945 $html_output .= PMA_getHtmlForDisplayTheInitials(
2946 $array_initials, $conditional_class
2951 * Display the user overview
2952 * (if less than 50 users, display them immediately)
2954 if (isset($_REQUEST['initial'])
2955 || isset($_REQUEST['showall'])
2956 || PMA_DBI_num_rows($res) < 50
2958 $html_output .= PMA_getUsersOverview(
2959 $res, $db_rights, $link_edit, $pmaThemeImage,
2960 $text_dir, $conditional_class, $link_export
2962 } else {
2963 $html_output .= PMA_getAddUserHtmlFieldset($conditional_class);
2964 } // end if (display overview)
2966 if (! $GLOBALS['is_ajax_request'] || ! empty($_REQUEST['ajax_page_request'])) {
2967 $flushnote = new PMA_Message(
2968 __('Note: phpMyAdmin gets the users\' privileges directly from MySQL\'s privilege tables. The content of these tables may differ from the privileges the server uses, if they have been changed manually. In this case, you should %sreload the privileges%s before you continue.'),
2969 PMA_Message::NOTICE
2971 $flushLink = '<a href="server_privileges.php?' . $GLOBALS['url_query'] . '&amp;'
2972 . 'flush_privileges=1" id="reload_privileges_anchor" '
2973 . 'class="' . $conditional_class . '">';
2974 $flushnote->addParam(
2975 $flushLink,
2976 false
2978 $flushnote->addParam('</a>', false);
2979 $html_output .= $flushnote->getDisplay();
2981 return $html_output;
2986 * Get HTML snippet for display user properties
2988 * @param boolean $dbname_is_wildcard whether database name is wildcard or not
2989 * @param type $url_dbname url database name that urlencode() string
2990 * @param string $username username
2991 * @param string $hostname host name
2992 * @param string $link_edit standard link to edit privileges
2993 * @param string $link_revoke standard link to revoke
2994 * @param string $dbname database name
2995 * @param string $tablename table name
2997 * @return string $html_output
2999 function PMA_getHtmlForDisplayUserProperties($dbname_is_wildcard,$url_dbname,
3000 $username, $hostname, $link_edit, $link_revoke, $dbname, $tablename
3002 $html_output = PMA_getHtmlHeaderForDisplayUserProperties(
3003 $dbname_is_wildcard, $url_dbname, $dbname, $username, $hostname, $tablename
3006 $sql = "SELECT '1' FROM `mysql`.`user`"
3007 . " WHERE `User` = '" . PMA_Util::sqlAddSlashes($username) . "'"
3008 . " AND `Host` = '" . PMA_Util::sqlAddSlashes($hostname) . "';";
3010 $user_does_not_exists = (bool) ! PMA_DBI_fetch_value($sql);
3012 if ($user_does_not_exists) {
3013 $html_output .= PMA_Message::error(
3014 __('The selected user was not found in the privilege table.')
3015 )->getDisplay();
3016 $html_output .= PMA_getHtmlForDisplayLoginInformationFields();
3017 //exit;
3020 $class = ' class="ajax"';
3021 $html_output .= '<form' . $class . ' name="usersForm" id="addUsersForm"'
3022 . ' action="server_privileges.php" method="post">' . "\n";
3024 $_params = array(
3025 'username' => $username,
3026 'hostname' => $hostname,
3028 if (strlen($dbname)) {
3029 $_params['dbname'] = $dbname;
3030 if (strlen($tablename)) {
3031 $_params['tablename'] = $tablename;
3034 $html_output .= PMA_generate_common_hidden_inputs($_params);
3036 $html_output .= PMA_getHtmlToDisplayPrivilegesTable(
3037 PMA_ifSetOr($dbname, '*', 'length'),
3038 PMA_ifSetOr($tablename, '*', 'length')
3041 $html_output .= '</form>' . "\n";
3043 if (! strlen($tablename) && empty($dbname_is_wildcard)) {
3045 // no table name was given, display all table specific rights
3046 // but only if $dbname contains no wildcards
3048 $html_output .= '<form action="server_privileges.php" '
3049 . 'id="db_or_table_specific_priv" method="post">' . "\n";
3051 // unescape wildcards in dbname at table level
3052 $unescaped_db = PMA_Util::unescapeMysqlWildcards($dbname);
3053 list($html_rightsTable, $found_rows)
3054 = PMA_getTableForDisplayAllTableSpecificRights(
3055 $username, $hostname, $link_edit, $link_revoke, $unescaped_db
3057 $html_output .= $html_rightsTable;
3059 if (! strlen($dbname)) {
3060 // no database name was given, display select db
3061 $html_output .= PMA_getHtmlForDisplaySelectDbInEditPrivs($found_rows);
3063 } else {
3064 $html_output .= PMA_displayTablesInEditPrivs($dbname, $found_rows);
3066 $html_output .= '</fieldset>' . "\n";
3068 $html_output .= '<fieldset class="tblFooters">' . "\n"
3069 . ' <input type="submit" value="' . __('Go') . '" />'
3070 . '</fieldset>' . "\n"
3071 . '</form>' . "\n";
3074 // Provide a line with links to the relevant database and table
3075 if (strlen($dbname) && empty($dbname_is_wildcard)) {
3076 $html_output .= PMA_getLinkToDbAndTable($url_dbname, $dbname, $tablename);
3080 if (! strlen($dbname) && ! $user_does_not_exists) {
3081 //change login information
3082 $html_output .= PMA_getHtmlForChangePassword($username, $hostname);
3083 $html_output .= PMA_getChangeLoginInformationHtmlForm($username, $hostname);
3086 return $html_output;
3090 * Get queries for Table privileges to change or copy user
3092 * @param string $user_host_condition user host condition to select relevent table privileges
3093 * @param array $queries queries array
3094 * @param string $username username
3095 * @param string $hostname host name
3097 * @return array $queries
3099 function PMA_getTablePrivsQueriesForChangeOrCopyUser($user_host_condition,
3100 $queries, $username, $hostname
3102 $res = PMA_DBI_query(
3103 'SELECT `Db`, `Table_name`, `Table_priv` FROM `mysql`.`tables_priv`' . $user_host_condition,
3104 $GLOBALS['userlink'],
3105 PMA_DBI_QUERY_STORE
3107 while ($row = PMA_DBI_fetch_assoc($res)) {
3109 $res2 = PMA_DBI_QUERY(
3110 'SELECT `Column_name`, `Column_priv`'
3111 .' FROM `mysql`.`columns_priv`'
3112 .' WHERE `User`'
3113 .' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_username']) . "'"
3114 .' AND `Host`'
3115 .' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_username']) . '\''
3116 .' AND `Db`'
3117 .' = \'' . PMA_Util::sqlAddSlashes($row['Db']) . "'"
3118 .' AND `Table_name`'
3119 .' = \'' . PMA_Util::sqlAddSlashes($row['Table_name']) . "'"
3120 .';',
3121 null,
3122 PMA_DBI_QUERY_STORE
3125 $tmp_privs1 = PMA_extractPrivInfo($row);
3126 $tmp_privs2 = array(
3127 'Select' => array(),
3128 'Insert' => array(),
3129 'Update' => array(),
3130 'References' => array()
3133 while ($row2 = PMA_DBI_fetch_assoc($res2)) {
3134 $tmp_array = explode(',', $row2['Column_priv']);
3135 if (in_array('Select', $tmp_array)) {
3136 $tmp_privs2['Select'][] = $row2['Column_name'];
3138 if (in_array('Insert', $tmp_array)) {
3139 $tmp_privs2['Insert'][] = $row2['Column_name'];
3141 if (in_array('Update', $tmp_array)) {
3142 $tmp_privs2['Update'][] = $row2['Column_name'];
3144 if (in_array('References', $tmp_array)) {
3145 $tmp_privs2['References'][] = $row2['Column_name'];
3148 if (count($tmp_privs2['Select']) > 0 && ! in_array('SELECT', $tmp_privs1)) {
3149 $tmp_privs1[] = 'SELECT (`' . join('`, `', $tmp_privs2['Select']) . '`)';
3151 if (count($tmp_privs2['Insert']) > 0 && ! in_array('INSERT', $tmp_privs1)) {
3152 $tmp_privs1[] = 'INSERT (`' . join('`, `', $tmp_privs2['Insert']) . '`)';
3154 if (count($tmp_privs2['Update']) > 0 && ! in_array('UPDATE', $tmp_privs1)) {
3155 $tmp_privs1[] = 'UPDATE (`' . join('`, `', $tmp_privs2['Update']) . '`)';
3157 if (count($tmp_privs2['References']) > 0 && ! in_array('REFERENCES', $tmp_privs1)) {
3158 $tmp_privs1[] = 'REFERENCES (`' . join('`, `', $tmp_privs2['References']) . '`)';
3161 $queries[] = 'GRANT ' . join(', ', $tmp_privs1)
3162 . ' ON ' . PMA_Util::backquote($row['Db']) . '.'
3163 . PMA_Util::backquote($row['Table_name'])
3164 . ' TO \'' . PMA_Util::sqlAddSlashes($username)
3165 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\''
3166 . (in_array('Grant', explode(',', $row['Table_priv'])) ? ' WITH GRANT OPTION;' : ';');
3168 return $queries;
3172 * Get queries for database specific privileges for change or copy user
3174 * @param array $queries queries array with string
3175 * @param string $username username
3176 * @param string $hostname host name
3178 * @return array $queries
3180 function PMA_getDbSpecificPrivsQueriesForChangeOrCopyUser(
3181 $queries, $username, $hostname
3183 $user_host_condition = ' WHERE `User`'
3184 .' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_username']) . "'"
3185 .' AND `Host`'
3186 .' = \'' . PMA_Util::sqlAddSlashes($_REQUEST['old_username']) . '\';';
3188 $res = PMA_DBI_query('SELECT * FROM `mysql`.`db`' . $user_host_condition);
3190 while ($row = PMA_DBI_fetch_assoc($res)) {
3191 $queries[] = 'GRANT ' . join(', ', PMA_extractPrivInfo($row))
3192 .' ON ' . PMA_Util::backquote($row['Db']) . '.*'
3193 .' TO \'' . PMA_Util::sqlAddSlashes($username)
3194 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\''
3195 . ($row['Grant_priv'] == 'Y' ? ' WITH GRANT OPTION;' : ';');
3197 PMA_DBI_free_result($res);
3199 $queries = PMA_getTablePrivsQueriesForChangeOrCopyUser(
3200 $user_host_condition, $queries, $username, $hostname
3203 return $queries;
3207 * Prepares queries for adding users and
3208 * also create database and return query and message
3210 * @param boolean $_error whether user create or not
3211 * @param string $real_sql_query SQL query for add a user
3212 * @param string $sql_query SQL query to be displayed
3213 * @param string $username username
3214 * @param string $hostname host name
3215 * @param string $dbname database name
3217 * @return array $sql_query, $message
3219 function PMA_addUserAndCreateDatabase($_error, $real_sql_query, $sql_query,
3220 $username, $hostname, $dbname
3222 if ($_error || ! PMA_DBI_try_query($real_sql_query)) {
3223 $_REQUEST['createdb-1'] = $_REQUEST['createdb-2']
3224 = $_REQUEST['createdb-3'] = false;
3225 $message = PMA_Message::rawError(PMA_DBI_getError());
3226 } else {
3227 $message = PMA_Message::success(__('You have added a new user.'));
3230 if (isset($_REQUEST['createdb-1'])) {
3231 // Create database with same name and grant all privileges
3232 $q = 'CREATE DATABASE IF NOT EXISTS '
3233 . PMA_Util::backquote(
3234 PMA_Util::sqlAddSlashes($username)
3235 ) . ';';
3236 $sql_query .= $q;
3237 if (! PMA_DBI_try_query($q)) {
3238 $message = PMA_Message::rawError(PMA_DBI_getError());
3242 * Reload the navigation
3244 $GLOBALS['reload'] = true;
3245 $GLOBALS['db'] = $username;
3247 $q = 'GRANT ALL PRIVILEGES ON '
3248 . PMA_Util::backquote(
3249 PMA_Util::escapeMysqlWildcards(
3250 PMA_Util::sqlAddSlashes($username)
3252 ) . '.* TO \''
3253 . PMA_Util::sqlAddSlashes($username)
3254 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
3255 $sql_query .= $q;
3256 if (! PMA_DBI_try_query($q)) {
3257 $message = PMA_Message::rawError(PMA_DBI_getError());
3261 if (isset($_REQUEST['createdb-2'])) {
3262 // Grant all privileges on wildcard name (username\_%)
3263 $q = 'GRANT ALL PRIVILEGES ON '
3264 . PMA_Util::backquote(
3265 PMA_Util::sqlAddSlashes($username) . '\_%'
3266 ) . '.* TO \''
3267 . PMA_Util::sqlAddSlashes($username)
3268 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
3269 $sql_query .= $q;
3270 if (! PMA_DBI_try_query($q)) {
3271 $message = PMA_Message::rawError(PMA_DBI_getError());
3275 if (isset($_REQUEST['createdb-3'])) {
3276 // Grant all privileges on the specified database to the new user
3277 $q = 'GRANT ALL PRIVILEGES ON '
3278 . PMA_Util::backquote(
3279 PMA_Util::sqlAddSlashes($dbname)
3280 ) . '.* TO \''
3281 . PMA_Util::sqlAddSlashes($username)
3282 . '\'@\'' . PMA_Util::sqlAddSlashes($hostname) . '\';';
3283 $sql_query .= $q;
3284 if (! PMA_DBI_try_query($q)) {
3285 $message = PMA_Message::rawError(PMA_DBI_getError());
3288 return array($sql_query, $message);
3292 * Get SQL queries for Display and Add user
3294 * @param string $username usernam
3295 * @param string $hostname host name
3296 * @param string $password password
3298 * @return array ($create_user_real, $create_user_show,$real_sql_query, $sql_query)
3300 function PMA_getSqlQueriesForDisplayAndAddUser($username, $hostname, $password)
3302 $sql_query = '';
3303 $create_user_real = 'CREATE USER \''
3304 . PMA_Util::sqlAddSlashes($username) . '\'@\''
3305 . PMA_Util::sqlAddSlashes($hostname) . '\'';
3307 $real_sql_query = 'GRANT ' . join(', ', PMA_extractPrivInfo()) . ' ON *.* TO \''
3308 . PMA_Util::sqlAddSlashes($username) . '\'@\''
3309 . PMA_Util::sqlAddSlashes($hostname) . '\'';
3311 if ($_POST['pred_password'] != 'none' && $_POST['pred_password'] != 'keep') {
3312 $sql_query = $real_sql_query . ' IDENTIFIED BY \'***\'';
3313 $real_sql_query .= ' IDENTIFIED BY \''
3314 . PMA_Util::sqlAddSlashes($_POST['pma_pw']) . '\'';
3315 if (isset($create_user_real)) {
3316 $create_user_show = $create_user_real . ' IDENTIFIED BY \'***\'';
3317 $create_user_real .= ' IDENTIFIED BY \''
3318 . PMA_Util::sqlAddSlashes($_POST['pma_pw']) . '\'';
3320 } else {
3321 if ($_POST['pred_password'] == 'keep' && ! empty($password)) {
3322 $real_sql_query .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
3323 if (isset($create_user_real)) {
3324 $create_user_real .= ' IDENTIFIED BY PASSWORD \'' . $password . '\'';
3327 $sql_query = $real_sql_query;
3328 if (isset($create_user_real)) {
3329 $create_user_show = $create_user_real;
3333 if ((isset($_POST['Grant_priv']) && $_POST['Grant_priv'] == 'Y')
3334 || (isset($_POST['max_questions']) || isset($_POST['max_connections'])
3335 || isset($_POST['max_updates']) || isset($_POST['max_user_connections']))
3337 $with_clause = PMA_getWithClauseForAddUserAndUpdatePrivs();
3338 $real_sql_query .= ' ' . $with_clause;
3339 $sql_query .= ' ' . $with_clause;
3342 if (isset($create_user_real)) {
3343 $create_user_real .= ';';
3344 $create_user_show .= ';';
3346 $real_sql_query .= ';';
3347 $sql_query .= ';';
3349 return array($create_user_real,
3350 $create_user_show,
3351 $real_sql_query,
3352 $sql_query