[ Index ] |
|
Code source de phpMyAdmin 2.10.3 |
1 <?php 2 /** 3 * holds the PMA_List_Database class 4 * 5 */ 6 7 /** 8 * the list base class 9 */ 10 require_once './libraries/PMA_List.class.php'; 11 12 /** 13 * handles database lists 14 * 15 * <code> 16 * $PMA_List_Database = new PMA_List_Database($userlink, $controllink); 17 * </code> 18 * 19 * @todo this object should be attached to the PMA_Server object 20 * @todo ? make use of INFORMATION_SCHEMA 21 * @todo ? support --skip-showdatabases and user has only global rights 22 * @access public 23 * @since phpMyAdmin 2.9.10 24 */ 25 /*public*/ class PMA_List_Database extends PMA_List 26 { 27 /** 28 * @var mixed database link resource|object to be used 29 * @access protected 30 */ 31 var $_db_link = null; 32 33 /** 34 * @var mixed user database link resource|object 35 * @access protected 36 */ 37 var $_db_link_user = null; 38 39 /** 40 * @var mixed controluser database link resource|object 41 * @access protected 42 */ 43 var $_db_link_control = null; 44 45 /** 46 * @var boolean whether SHOW DATABASES is disabled or not 47 * @access protected 48 */ 49 var $_show_databases_disabled = false; 50 51 /** 52 * Constructor 53 * 54 * @uses PMA_List_Database::$_db_link 55 * @uses PMA_List_Database::$_db_link_user 56 * @uses PMA_List_Database::$_db_link_control 57 * @uses PMA_List_Database::build() 58 * @param mixed $db_link_user user database link resource|object 59 * @param mixed $db_link_control control database link resource|object 60 */ 61 function __construct($db_link_user = null, $db_link_control = null) { 62 $this->_db_link = $db_link_user; 63 $this->_db_link_user = $db_link_user; 64 $this->_db_link_control = $db_link_control; 65 66 $this->build(); 67 } 68 69 /** 70 * old PHP 4 style constructor 71 * 72 * @see PMA_List_Database::__construct() 73 */ 74 function PMA_List_Database($db_link_user = null, $db_link_control = null) { 75 $this->__construct($db_link_user, $db_link_control); 76 } 77 78 /** 79 * removes all databases not accessible by current user from list 80 * 81 * @access protected 82 * @uses PMA_List_Database::$items 83 * @uses PMA_List_Database::$_db_link_user 84 * @uses PMA_List_Database::$_need_to_reindex to set it if reuqired 85 * @uses PMA_DBI_select_db() 86 */ 87 function _checkAccess() 88 { 89 foreach ($this->items as $key => $db) { 90 if (! @PMA_DBI_select_db($db, $this->_db_link_user)) { 91 unset($this->items[$key]); 92 } 93 } 94 95 // re-index values 96 $this->_need_to_reindex = true; 97 } 98 99 /** 100 * checks if the configuration wants to hide some databases 101 * 102 * @todo temporaly use this docblock to test how to doc $GLOBALS 103 * @access protected 104 * @uses PMA_List_Database::$items 105 * @uses PMA_List_Database::$_need_to_reindex to set it if reuqired 106 * @uses preg_match() 107 * @uses $GLOBALS['cfg'] 108 * @uses $GLOBALS['cfg']['Server'] 109 * @uses $GLOBALS['cfg']['Server']['hide_db'] 110 * @global array $GLOBALS['cfg'] 111 * @global array $cfg 112 */ 113 function _checkHideDatabase() 114 { 115 if (empty($GLOBALS['cfg']['Server']['hide_db'])) { 116 return; 117 } 118 119 foreach ($this->items as $key => $db) { 120 if (preg_match('/' . $GLOBALS['cfg']['Server']['hide_db'] . '/', $db)) { 121 unset($this->items[$key]); 122 } 123 } 124 // re-index values 125 $this->_need_to_reindex = true; 126 } 127 128 /** 129 * retrieves database list from server 130 * 131 * @todo we could also search mysql tables if all fail? 132 * @access protected 133 * @uses PMA_List_Database::$_show_databases_disabled for not retrying if SHOW DATABASES is disabled 134 * @uses PMA_List_Database::$_db_link 135 * @uses PMA_List_Database::$_db_link_control in case of SHOW DATABASES is disabled for userlink 136 * @uses PMA_DBI_fetch_result() 137 * @uses PMA_DBI_getError() 138 * @global boolean $error_showdatabases to alert not allowed SHOW DATABASE 139 * @global integer $errno from PMA_DBI_getError() 140 * @param string $like_db_name usally a db_name containing wildcards 141 */ 142 function _retrieve($like_db_name = '') 143 { 144 if ($this->_show_databases_disabled) { 145 return array(); 146 } 147 148 if (! empty($like_db_name)) { 149 $like = " LIKE '" . $like_db_name . "';"; 150 } else { 151 $like = ";"; 152 } 153 154 $database_list = PMA_DBI_fetch_result('SHOW DATABASES' . $like, null, null, $this->_db_link); 155 PMA_DBI_getError(); 156 157 if ($GLOBALS['errno'] !== 0) { 158 // failed to get database list, try the control user 159 // (hopefully there is one and he has SHOW DATABASES right) 160 $this->_db_link = $this->_db_link_control; 161 $database_list = PMA_DBI_fetch_result('SHOW DATABASES' . $like, null, null, $this->_db_link); 162 163 PMA_DBI_getError(); 164 165 if ($GLOBALS['errno'] !== 0) { 166 // failed! we will display a warning that phpMyAdmin could not safely 167 // retrieve database list, the admin has to setup a control user or 168 // allow SHOW DATABASES 169 $GLOBALS['error_showdatabases'] = true; 170 $this->_show_databases_disabled = true; 171 } 172 } 173 174 return $database_list; 175 } 176 177 /** 178 * builds up the list 179 * 180 * @uses PMA_List_Database::$items to initialize it 181 * @uses PMA_List_Database::$_need_to_reindex 182 * @uses PMA_List_Database::_checkOnlyDatabase() 183 * @uses PMA_List_Database::_retrieve() 184 * @uses PMA_List_Database::_checkHideDatabase() 185 * @uses PMA_List_Database::_checkAccess() 186 * @uses PMA_MYSQL_INT_VERSION 187 * @uses array_values() 188 * @uses natsort() 189 * @global array $cfg 190 */ 191 function build() 192 { 193 $this->items = array(); 194 195 if (! $this->_checkOnlyDatabase()) { 196 $this->items = $this->_retrieve(); 197 198 if ($GLOBALS['cfg']['NaturalOrder']) { 199 natsort($this->items); 200 $this->_need_to_reindex = true; 201 } 202 } 203 204 $this->_checkHideDatabase(); 205 206 // Before MySQL 4.0.2, SHOW DATABASES could send the 207 // whole list, so check if we really have access: 208 if (PMA_MYSQL_INT_VERSION < 40002) { 209 $this->_checkAccess(); 210 } 211 212 if ($this->_need_to_reindex) { 213 $this->items = array_values($this->items); 214 } 215 } 216 217 /** 218 * checks the only_db configuration 219 * 220 * @uses PMA_List_Database::$_show_databases_disabled 221 * @uses PMA_List_Database::$items 222 * @uses PMA_List_Database::_retrieve() 223 * @uses PMA_unescape_mysql_wildcards() 224 * @uses preg_match() 225 * @uses array_diff() 226 * @uses array_merge() 227 * @uses is_array() 228 * @uses strlen() 229 * @uses is_string() 230 * @global array $cfg 231 * @return boolean false if there is no only_db, otherwise true 232 */ 233 function _checkOnlyDatabase() 234 { 235 if (is_string($GLOBALS['cfg']['Server']['only_db']) 236 && strlen($GLOBALS['cfg']['Server']['only_db'])) { 237 $GLOBALS['cfg']['Server']['only_db'] = array( 238 $GLOBALS['cfg']['Server']['only_db'] 239 ); 240 } 241 242 if (! is_array($GLOBALS['cfg']['Server']['only_db'])) { 243 return false; 244 } 245 246 foreach ($GLOBALS['cfg']['Server']['only_db'] as $each_only_db) { 247 if ($each_only_db === '*' && ! $this->_show_databases_disabled) { 248 // append all not already listed dbs to the list 249 $this->items = array_merge($this->items, 250 array_diff($this->_retrieve(), $this->items)); 251 // there can only be one '*', and this can only be last 252 break; 253 } 254 255 // check if the db name contains wildcard, 256 // thus containing not escaped _ or % 257 if (! preg_match('/(^|[^\\\\])(_|%)/', $each_only_db)) { 258 // ... not contains wildcard 259 $this->items[] = PMA_unescape_mysql_wildcards($each_only_db); 260 continue; 261 } 262 263 if (! $this->_show_databases_disabled) { 264 $this->items = array_merge($this->items, $this->_retrieve($each_only_db)); 265 continue; 266 } 267 268 // @todo induce error, about not using wildcards with SHOW DATABASE disabled? 269 } 270 271 return true; 272 } 273 274 /** 275 * returns default item 276 * 277 * @uses PMA_List::getEmpty() 278 * @uses strlen() 279 * @global string $db 280 * @return string default item 281 */ 282 function getDefault() 283 { 284 if (strlen($GLOBALS['db'])) { 285 return $GLOBALS['db']; 286 } 287 288 return $this->getEmpty(); 289 } 290 291 /** 292 * returns array with dbs grouped with extended infos 293 * 294 * @uses $GLOBALS['PMA_List_Database'] 295 * @uses $GLOBALS['cfgRelation']['commwork'] 296 * @uses $GLOBALS['cfg']['ShowTooltip'] 297 * @uses $GLOBALS['cfg']['LeftFrameDBTree'] 298 * @uses $GLOBALS['cfg']['LeftFrameDBSeparator'] 299 * @uses $GLOBALS['cfg']['ShowTooltipAliasDB'] 300 * @uses PMA_getTableCount() 301 * @uses PMA_getComments() 302 * @uses is_array() 303 * @uses implode() 304 * @uses strstr() 305 * @uses explode() 306 * @return array db list 307 */ 308 function getGroupedDetails() 309 { 310 $dbgroups = array(); 311 $parts = array(); 312 foreach ($this->items as $key => $db) { 313 // garvin: Get comments from PMA comments table 314 $db_tooltip = ''; 315 if ($GLOBALS['cfg']['ShowTooltip'] 316 && $GLOBALS['cfgRelation']['commwork']) { 317 $_db_tooltip = PMA_getComments($db); 318 if (is_array($_db_tooltip)) { 319 $db_tooltip = implode(' ', $_db_tooltip); 320 } 321 } 322 323 if ($GLOBALS['cfg']['LeftFrameDBTree'] 324 && $GLOBALS['cfg']['LeftFrameDBSeparator'] 325 && strstr($db, $GLOBALS['cfg']['LeftFrameDBSeparator'])) 326 { 327 // use strpos instead of strrpos; it seems more common to 328 // have the db name, the separator, then the rest which 329 // might contain a separator 330 // like dbname_the_rest 331 $pos = strpos($db, $GLOBALS['cfg']['LeftFrameDBSeparator']); 332 $group = substr($db, 0, $pos); 333 $disp_name_cut = substr($db, $pos); 334 } else { 335 $group = $db; 336 $disp_name_cut = $db; 337 } 338 339 $disp_name = $db; 340 if ($db_tooltip && $GLOBALS['cfg']['ShowTooltipAliasDB']) { 341 $disp_name = $db_tooltip; 342 $disp_name_cut = $db_tooltip; 343 $db_tooltip = $db; 344 } 345 346 $dbgroups[$group][$db] = array( 347 'name' => $db, 348 'disp_name_cut' => $disp_name_cut, 349 'disp_name' => $disp_name, 350 'comment' => $db_tooltip, 351 'num_tables' => PMA_getTableCount($db), 352 ); 353 } // end foreach ($GLOBALS['PMA_List_Database']->items as $db) 354 return $dbgroups; 355 } 356 357 /** 358 * returns html code for list with dbs 359 * 360 * @return string html code list 361 */ 362 function getHtmlListGrouped($selected = '') 363 { 364 if (true === $selected) { 365 $selected = $this->getDefault(); 366 } 367 368 $return = '<ul id="databaseList" xml:lang="en" dir="ltr">' . "\n"; 369 foreach ($this->getGroupedDetails() as $group => $dbs) { 370 if (count($dbs) > 1) { 371 $return .= '<li>' . $group . '<ul>' . "\n"; 372 // wether display db_name cuted by the group part 373 $cut = true; 374 } else { 375 // .. or full 376 $cut = false; 377 } 378 foreach ($dbs as $db) { 379 $return .= '<li'; 380 if ($db['name'] == $selected) { 381 $return .= ' class="selected"'; 382 } 383 $return .= '><a' . (! empty($db['comment']) ? ' title="' . $db['comment'] . '"' : '') . ' href="index.php?' . PMA_generate_common_url($db['name']) . '" target="_parent">'; 384 $return .= ($cut ? $db['disp_name_cut'] : $db['disp_name']) 385 .' (' . $db['num_tables'] . ')'; 386 $return .= '</a></li>' . "\n"; 387 } 388 if (count($dbs) > 1) { 389 $return .= '</ul></li>' . "\n"; 390 } 391 } 392 $return .= '</ul>'; 393 394 return $return; 395 } 396 397 /** 398 * returns html code for select form element with dbs 399 * 400 * @todo IE can not handle different text directions in select boxes so, 401 * as mostly names will be in english, we set the whole selectbox to LTR 402 * and EN 403 * 404 * @return string html code select 405 */ 406 function getHtmlSelectGrouped($selected = '') 407 { 408 if (true === $selected) { 409 $selected = $this->getDefault(); 410 } 411 412 $return = '<select name="db" id="lightm_db" xml:lang="en" dir="ltr"' 413 . ' onchange="if (this.value != \'\') window.parent.openDb(this.value);">' . "\n" 414 . '<option value="" dir="' . $GLOBALS['text_dir'] . '">' 415 . '(' . $GLOBALS['strDatabases'] . ') ...</option>' . "\n"; 416 foreach ($this->getGroupedDetails() as $group => $dbs) { 417 if (count($dbs) > 1) { 418 $return .= '<optgroup label="' . htmlspecialchars($group) 419 . '">' . "\n"; 420 // wether display db_name cuted by the group part 421 $cut = true; 422 } else { 423 // .. or full 424 $cut = false; 425 } 426 foreach ($dbs as $db) { 427 $return .= '<option value="' . htmlspecialchars($db['name']) . '"' 428 .' title="' . htmlspecialchars($db['comment']) . '"'; 429 if ($db['name'] == $selected) { 430 $return .= ' selected="selected"'; 431 } 432 $return .= '>' . htmlspecialchars($cut ? $db['disp_name_cut'] : $db['disp_name']) 433 .' (' . $db['num_tables'] . ')</option>' . "\n"; 434 } 435 if (count($dbs) > 1) { 436 $return .= '</optgroup>' . "\n"; 437 } 438 } 439 $return .= '</select>'; 440 441 return $return; 442 } 443 444 /** 445 * this is just a backup, if all is fine this can be deleted later 446 * 447 * @deprecated 448 * @access protected 449 */ 450 function _checkAgainstPrivTables() 451 { 452 // 1. get allowed dbs from the "mysql.db" table 453 // lem9: User can be blank (anonymous user) 454 $local_query = " 455 SELECT DISTINCT `Db` FROM `mysql`.`db` 456 WHERE `Select_priv` = 'Y' 457 AND `User` 458 IN ('" . PMA_sqlAddslashes($GLOBALS['cfg']['Server']['user']) . "', '')"; 459 $tmp_mydbs = PMA_DBI_fetch_result($local_query, null, null, 460 $GLOBALS['controllink']); 461 if ($tmp_mydbs) { 462 // Will use as associative array of the following 2 code 463 // lines: 464 // the 1st is the only line intact from before 465 // correction, 466 // the 2nd replaces $dblist[] = $row['Db']; 467 468 // Code following those 2 lines in correction continues 469 // populating $dblist[], as previous code did. But it is 470 // now populated with actual database names instead of 471 // with regular expressions. 472 var_dump($tmp_mydbs); 473 $tmp_alldbs = PMA_DBI_query('SHOW DATABASES;', $GLOBALS['controllink']); 474 // loic1: all databases cases - part 2 475 if (isset($tmp_mydbs['%'])) { 476 while ($tmp_row = PMA_DBI_fetch_row($tmp_alldbs)) { 477 $dblist[] = $tmp_row[0]; 478 } // end while 479 } else { 480 while ($tmp_row = PMA_DBI_fetch_row($tmp_alldbs)) { 481 $tmp_db = $tmp_row[0]; 482 if (isset($tmp_mydbs[$tmp_db]) && $tmp_mydbs[$tmp_db] == 1) { 483 $dblist[] = $tmp_db; 484 $tmp_mydbs[$tmp_db] = 0; 485 } elseif (!isset($dblist[$tmp_db])) { 486 foreach ($tmp_mydbs as $tmp_matchpattern => $tmp_value) { 487 // loic1: fixed bad regexp 488 // TODO: db names may contain characters 489 // that are regexp instructions 490 $re = '(^|(\\\\\\\\)+|[^\])'; 491 $tmp_regex = ereg_replace($re . '%', '\\1.*', ereg_replace($re . '_', '\\1.{1}', $tmp_matchpattern)); 492 // Fixed db name matching 493 // 2000-08-28 -- Benjamin Gandon 494 if (ereg('^' . $tmp_regex . '$', $tmp_db)) { 495 $dblist[] = $tmp_db; 496 break; 497 } 498 } // end while 499 } // end if ... elseif ... 500 } // end while 501 } // end else 502 PMA_DBI_free_result($tmp_alldbs); 503 unset($tmp_mydbs); 504 } // end if 505 506 // 2. get allowed dbs from the "mysql.tables_priv" table 507 $local_query = 'SELECT DISTINCT Db FROM mysql.tables_priv WHERE Table_priv LIKE \'%Select%\' AND User = \'' . PMA_sqlAddslashes($GLOBALS['cfg']['Server']['user']) . '\''; 508 $rs = PMA_DBI_try_query($local_query, $GLOBALS['controllink']); 509 if ($rs && @PMA_DBI_num_rows($rs)) { 510 while ($row = PMA_DBI_fetch_assoc($rs)) { 511 if (!in_array($row['Db'], $dblist)) { 512 $dblist[] = $row['Db']; 513 } 514 } // end while 515 PMA_DBI_free_result($rs); 516 } // end if 517 } 518 } 519 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Mon Nov 26 15:18:20 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |