| [ Index ] |
|
Code source de phpMyAdmin 2.10.3 |
1 <?php 2 /* $Id: common.lib.php 10473 2007-07-05 12:26:42Z lem9 $ */ 3 // vim: expandtab sw=4 ts=4 sts=4: 4 5 /** 6 * Misc stuff and functions used by almost all the scripts. 7 * Among other things, it contains the advanced authentication work. 8 */ 9 10 /** 11 * Order of sections for common.lib.php: 12 * 13 * the include of libraries/defines_mysql.lib.php must be after the connection 14 * to db to get the MySql version 15 * 16 * the authentication libraries must be before the connection to db 17 * 18 * ... so the required order is: 19 * 20 * LABEL_definition_of_functions 21 * - definition of functions 22 * LABEL_variables_init 23 * - init some variables always needed 24 * LABEL_parsing_config_file 25 * - parsing of the config file 26 * LABEL_loading_language_file 27 * - loading language file 28 * LABEL_theme_setup 29 * - setting up themes 30 * 31 * - load of mysql extension (if necessary) label_loading_mysql 32 * - loading of an authentication library label_ 33 * - db connection 34 * - authentication work 35 * - load of the libraries/defines_mysql.lib.php library to get the MySQL 36 * release number 37 */ 38 39 /** 40 * For now, avoid warnings of E_STRICT mode 41 * (this must be done before function definitions) 42 */ 43 44 if (defined('E_STRICT')) { 45 $old_error_reporting = error_reporting(0); 46 if ($old_error_reporting & E_STRICT) { 47 error_reporting($old_error_reporting ^ E_STRICT); 48 } else { 49 error_reporting($old_error_reporting); 50 } 51 unset($old_error_reporting); 52 } 53 54 /** 55 * Avoid object cloning errors 56 */ 57 58 @ini_set('zend.ze1_compatibility_mode',false); 59 60 /** 61 * Avoid problems with magic_quotes_runtime 62 */ 63 64 @ini_set('magic_quotes_runtime',false); 65 66 67 /******************************************************************************/ 68 /* definition of functions LABEL_definition_of_functions */ 69 /** 70 * Removes insecure parts in a path; used before include() or 71 * require() when a part of the path comes from an insecure source 72 * like a cookie or form. 73 * 74 * @param string The path to check 75 * 76 * @return string The secured path 77 * 78 * @access public 79 * @author Marc Delisle (lem9@users.sourceforge.net) 80 */ 81 function PMA_securePath($path) 82 { 83 // change .. to . 84 $path = preg_replace('@\.\.*@', '.', $path); 85 86 return $path; 87 } // end function 88 89 /** 90 * returns count of tables in given db 91 * 92 * @param string $db database to count tables for 93 * @return integer count of tables in $db 94 */ 95 function PMA_getTableCount($db) 96 { 97 $tables = PMA_DBI_try_query( 98 'SHOW TABLES FROM ' . PMA_backquote($db) . ';', 99 null, PMA_DBI_QUERY_STORE); 100 if ($tables) { 101 $num_tables = PMA_DBI_num_rows($tables); 102 PMA_DBI_free_result($tables); 103 } else { 104 $num_tables = 0; 105 } 106 107 return $num_tables; 108 } 109 110 /** 111 * Converts numbers like 10M into bytes 112 * Used with permission from Moodle (http://moodle.org) by Martin Dougiamas 113 * (renamed with PMA prefix to avoid double definition when embedded 114 * in Moodle) 115 * 116 * @param string $size 117 * @return integer $size 118 */ 119 function PMA_get_real_size($size = 0) 120 { 121 if (!$size) { 122 return 0; 123 } 124 $scan['MB'] = 1048576; 125 $scan['Mb'] = 1048576; 126 $scan['M'] = 1048576; 127 $scan['m'] = 1048576; 128 $scan['KB'] = 1024; 129 $scan['Kb'] = 1024; 130 $scan['K'] = 1024; 131 $scan['k'] = 1024; 132 133 while (list($key) = each($scan)) { 134 if ((strlen($size) > strlen($key)) 135 && (substr($size, strlen($size) - strlen($key)) == $key)) { 136 $size = substr($size, 0, strlen($size) - strlen($key)) * $scan[$key]; 137 break; 138 } 139 } 140 return $size; 141 } // end function PMA_get_real_size() 142 143 /** 144 * loads php module 145 * 146 * @uses PHP_OS 147 * @uses extension_loaded() 148 * @uses ini_get() 149 * @uses function_exists() 150 * @uses ob_start() 151 * @uses phpinfo() 152 * @uses strip_tags() 153 * @uses ob_get_contents() 154 * @uses ob_end_clean() 155 * @uses preg_match() 156 * @uses strtoupper() 157 * @uses substr() 158 * @uses dl() 159 * @param string $module name if module to load 160 * @return boolean success loading module 161 */ 162 function PMA_dl($module) 163 { 164 static $dl_allowed = null; 165 166 if (extension_loaded($module)) { 167 return true; 168 } 169 170 if (null === $dl_allowed) { 171 if (!@ini_get('safe_mode') 172 && @ini_get('enable_dl') 173 && @function_exists('dl')) { 174 ob_start(); 175 phpinfo(INFO_GENERAL); /* Only general info */ 176 $a = strip_tags(ob_get_contents()); 177 ob_end_clean(); 178 if (preg_match('@Thread Safety[[:space:]]*enabled@', $a)) { 179 if (preg_match('@Server API[[:space:]]*\(CGI\|CLI\)@', $a)) { 180 $dl_allowed = true; 181 } else { 182 $dl_allowed = false; 183 } 184 } else { 185 $dl_allowed = true; 186 } 187 } else { 188 $dl_allowed = false; 189 } 190 } 191 192 if (!$dl_allowed) { 193 return false; 194 } 195 196 /* Once we require PHP >= 4.3, we might use PHP_SHLIB_SUFFIX here */ 197 if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { 198 $module_file = 'php_' . $module . '.dll'; 199 } elseif (PHP_OS=='HP-UX') { 200 $module_file = $module . '.sl'; 201 } else { 202 $module_file = $module . '.so'; 203 } 204 205 return @dl($module_file); 206 } 207 208 /** 209 * merges array recursive like array_merge_recursive() but keyed-values are 210 * always overwritten. 211 * 212 * array PMA_array_merge_recursive(array $array1[, array $array2[, array ...]]) 213 * 214 * @see http://php.net/array_merge 215 * @see http://php.net/array_merge_recursive 216 * @uses func_num_args() 217 * @uses func_get_arg() 218 * @uses is_array() 219 * @uses call_user_func_array() 220 * @param array array to merge 221 * @param array array to merge 222 * @param array ... 223 * @return array merged array 224 */ 225 function PMA_array_merge_recursive() 226 { 227 switch(func_num_args()) { 228 case 0 : 229 return false; 230 break; 231 case 1 : 232 // when does that happen? 233 return func_get_arg(0); 234 break; 235 case 2 : 236 $args = func_get_args(); 237 if (!is_array($args[0]) || !is_array($args[1])) { 238 return $args[1]; 239 } 240 foreach ($args[1] as $key2 => $value2) { 241 if (isset($args[0][$key2]) && !is_int($key2)) { 242 $args[0][$key2] = PMA_array_merge_recursive($args[0][$key2], 243 $value2); 244 } else { 245 // we erase the parent array, otherwise we cannot override a directive that 246 // contains array elements, like this: 247 // (in config.default.php) $cfg['ForeignKeyDropdownOrder'] = array('id-content','content-id'); 248 // (in config.inc.php) $cfg['ForeignKeyDropdownOrder'] = array('content-id'); 249 if (is_int($key2) && $key2 == 0) { 250 unset($args[0]); 251 } 252 $args[0][$key2] = $value2; 253 } 254 } 255 return $args[0]; 256 break; 257 default : 258 $args = func_get_args(); 259 $args[1] = PMA_array_merge_recursive($args[0], $args[1]); 260 array_shift($args); 261 return call_user_func_array('PMA_array_merge_recursive', $args); 262 break; 263 } 264 } 265 266 /** 267 * calls $function vor every element in $array recursively 268 * 269 * @param array $array array to walk 270 * @param string $function function to call for every array element 271 */ 272 function PMA_arrayWalkRecursive(&$array, $function, $apply_to_keys_also = false) 273 { 274 static $recursive_counter = 0; 275 if (++$recursive_counter > 1000) { 276 die('possible deep recursion attack'); 277 } 278 foreach ($array as $key => $value) { 279 if (is_array($value)) { 280 PMA_arrayWalkRecursive($array[$key], $function, $apply_to_keys_also); 281 } else { 282 $array[$key] = $function($value); 283 } 284 285 if ($apply_to_keys_also && is_string($key)) { 286 $new_key = $function($key); 287 if ($new_key != $key) { 288 $array[$new_key] = $array[$key]; 289 unset($array[$key]); 290 } 291 } 292 } 293 $recursive_counter--; 294 } 295 296 /** 297 * boolean phpMyAdmin.PMA_checkPageValidity(string &$page, array $whitelist) 298 * 299 * checks given given $page against given $whitelist and returns true if valid 300 * it ignores optionaly query paramters in $page (script.php?ignored) 301 * 302 * @uses in_array() 303 * @uses urldecode() 304 * @uses substr() 305 * @uses strpos() 306 * @param string &$page page to check 307 * @param array $whitelist whitelist to check page against 308 * @return boolean whether $page is valid or not (in $whitelist or not) 309 */ 310 function PMA_checkPageValidity(&$page, $whitelist) 311 { 312 if (! isset($page) || !is_string($page)) { 313 return false; 314 } 315 316 if (in_array($page, $whitelist)) { 317 return true; 318 } elseif (in_array(substr($page, 0, strpos($page . '?', '?')), $whitelist)) { 319 return true; 320 } else { 321 $_page = urldecode($page); 322 if (in_array(substr($_page, 0, strpos($_page . '?', '?')), $whitelist)) { 323 return true; 324 } 325 } 326 return false; 327 } 328 329 /** 330 * trys to find the value for the given environment vriable name 331 * 332 * searchs in $_SERVER, $_ENV than trys getenv() and apache_getenv() 333 * in this order 334 * 335 * @param string $var_name variable name 336 * @return string value of $var or empty string 337 */ 338 function PMA_getenv($var_name) { 339 if (isset($_SERVER[$var_name])) { 340 return $_SERVER[$var_name]; 341 } elseif (isset($_ENV[$var_name])) { 342 return $_ENV[$var_name]; 343 } elseif (getenv($var_name)) { 344 return getenv($var_name); 345 } elseif (function_exists('apache_getenv') 346 && apache_getenv($var_name, true)) { 347 return apache_getenv($var_name, true); 348 } 349 350 return ''; 351 } 352 353 /** 354 * removes cookie 355 * 356 * @uses PMA_Config::isHttps() 357 * @uses PMA_Config::getCookiePath() 358 * @uses setcookie() 359 * @uses time() 360 * @param string $cookie name of cookie to remove 361 * @return boolean result of setcookie() 362 */ 363 function PMA_removeCookie($cookie) 364 { 365 return setcookie($cookie, '', time() - 3600, 366 PMA_Config::getCookiePath(), '', PMA_Config::isHttps()); 367 } 368 369 /** 370 * sets cookie if value is different from current cokkie value, 371 * or removes if value is equal to default 372 * 373 * @uses PMA_Config::isHttps() 374 * @uses PMA_Config::getCookiePath() 375 * @uses $_COOKIE 376 * @uses PMA_removeCookie() 377 * @uses setcookie() 378 * @uses time() 379 * @param string $cookie name of cookie to remove 380 * @param mixed $value new cookie value 381 * @param string $default default value 382 * @param int $validity validity of cookie in seconds (default is one month) 383 * @param bool $httponlt whether cookie is only for HTTP (and not for scripts) 384 * @return boolean result of setcookie() 385 */ 386 function PMA_setCookie($cookie, $value, $default = null, $validity = null, $httponly = true) 387 { 388 if ($validity == null) { 389 $validity = 2592000; 390 } 391 if (strlen($value) && null !== $default && $value === $default 392 && isset($_COOKIE[$cookie])) { 393 // remove cookie, default value is used 394 return PMA_removeCookie($cookie); 395 } 396 397 if (! strlen($value) && isset($_COOKIE[$cookie])) { 398 // remove cookie, value is empty 399 return PMA_removeCookie($cookie); 400 } 401 402 if (! isset($_COOKIE[$cookie]) || $_COOKIE[$cookie] !== $value) { 403 // set cookie with new value 404 /* Calculate cookie validity */ 405 if ($validity == 0) { 406 $v = 0; 407 } else { 408 $v = time() + $validity; 409 } 410 /* Use native support for httponly cookies if available */ 411 if (version_compare(PHP_VERSION, '5.2.0', 'ge')) { 412 return setcookie($cookie, $value, $v, 413 PMA_Config::getCookiePath(), '', PMA_Config::isHttps(), $httponly); 414 } else { 415 return setcookie($cookie, $value, $v, 416 PMA_Config::getCookiePath() . ($httponly ? '; HttpOnly' : ''), '', PMA_Config::isHttps()); 417 } 418 } 419 420 // cookie has already $value as value 421 return true; 422 } 423 424 /** 425 * include here only libraries which contain only function definitions 426 * no code im main()! 427 */ 428 /** 429 * Input sanitizing 430 */ 431 require_once './libraries/sanitizing.lib.php'; 432 /** 433 * the PMA_Theme class 434 */ 435 require_once './libraries/Theme.class.php'; 436 /** 437 * the PMA_Theme_Manager class 438 */ 439 require_once './libraries/Theme_Manager.class.php'; 440 /** 441 * the PMA_Config class 442 */ 443 require_once './libraries/Config.class.php'; 444 /** 445 * the PMA_Table class 446 */ 447 require_once './libraries/Table.class.php'; 448 449 450 if (!defined('PMA_MINIMUM_COMMON')) { 451 452 /** 453 * Java script escaping. 454 */ 455 require_once './libraries/js_escape.lib.php'; 456 457 /** 458 * Exponential expression / raise number into power 459 * 460 * @uses function_exists() 461 * @uses bcpow() 462 * @uses gmp_pow() 463 * @uses gmp_strval() 464 * @uses pow() 465 * @param number $base 466 * @param number $exp 467 * @param string pow function use, or false for auto-detect 468 * @return mixed string or float 469 */ 470 function PMA_pow($base, $exp, $use_function = false) 471 { 472 static $pow_function = null; 473 if (null == $pow_function) { 474 if (function_exists('bcpow')) { 475 // BCMath Arbitrary Precision Mathematics Function 476 $pow_function = 'bcpow'; 477 } elseif (function_exists('gmp_pow')) { 478 // GMP Function 479 $pow_function = 'gmp_pow'; 480 } else { 481 // PHP function 482 $pow_function = 'pow'; 483 } 484 } 485 486 if (! $use_function) { 487 $use_function = $pow_function; 488 } 489 490 switch ($use_function) { 491 case 'bcpow' : 492 $pow = bcpow($base, $exp); 493 break; 494 case 'gmp_pow' : 495 $pow = gmp_strval($exp >= 0 ? gmp_pow($base, $exp) : 0); 496 break; 497 case 'pow' : 498 $base = (float) $base; 499 $exp = (int) $exp; 500 if ($exp < 0) { 501 return false; 502 } 503 $pow = pow($base, $exp); 504 break; 505 default: 506 $pow = $use_function($base, $exp); 507 } 508 509 return $pow; 510 } 511 512 /** 513 * string PMA_getIcon(string $icon) 514 * 515 * @uses $GLOBALS['pmaThemeImage'] 516 * @param $icon name of icon 517 * @return html img tag 518 */ 519 function PMA_getIcon($icon, $alternate = '') 520 { 521 if ($GLOBALS['cfg']['PropertiesIconic']) { 522 return '<img src="' . $GLOBALS['pmaThemeImage'] . $icon . '"' 523 . ' title="' . $alternate . '" alt="' . $alternate . '"' 524 . ' class="icon" width="16" height="16" />'; 525 } else { 526 return $alternate; 527 } 528 } 529 530 /** 531 * Displays the maximum size for an upload 532 * 533 * @param integer the size 534 * 535 * @return string the message 536 * 537 * @access public 538 */ 539 function PMA_displayMaximumUploadSize($max_upload_size) 540 { 541 list($max_size, $max_unit) = PMA_formatByteDown($max_upload_size); 542 return '(' . sprintf($GLOBALS['strMaximumSize'], $max_size, $max_unit) . ')'; 543 } 544 545 /** 546 * Generates a hidden field which should indicate to the browser 547 * the maximum size for upload 548 * 549 * @param integer the size 550 * 551 * @return string the INPUT field 552 * 553 * @access public 554 */ 555 function PMA_generateHiddenMaxFileSize($max_size) 556 { 557 return '<input type="hidden" name="MAX_FILE_SIZE" value="' .$max_size . '" />'; 558 } 559 560 /** 561 * Add slashes before "'" and "\" characters so a value containing them can 562 * be used in a sql comparison. 563 * 564 * @param string the string to slash 565 * @param boolean whether the string will be used in a 'LIKE' clause 566 * (it then requires two more escaped sequences) or not 567 * @param boolean whether to treat cr/lfs as escape-worthy entities 568 * (converts \n to \\n, \r to \\r) 569 * 570 * @param boolean whether this function is used as part of the 571 * "Create PHP code" dialog 572 * 573 * @return string the slashed string 574 * 575 * @access public 576 */ 577 function PMA_sqlAddslashes($a_string = '', $is_like = false, $crlf = false, $php_code = false) 578 { 579 if ($is_like) { 580 $a_string = str_replace('\\', '\\\\\\\\', $a_string); 581 } else { 582 $a_string = str_replace('\\', '\\\\', $a_string); 583 } 584 585 if ($crlf) { 586 $a_string = str_replace("\n", '\n', $a_string); 587 $a_string = str_replace("\r", '\r', $a_string); 588 $a_string = str_replace("\t", '\t', $a_string); 589 } 590 591 if ($php_code) { 592 $a_string = str_replace('\'', '\\\'', $a_string); 593 } else { 594 $a_string = str_replace('\'', '\'\'', $a_string); 595 } 596 597 return $a_string; 598 } // end of the 'PMA_sqlAddslashes()' function 599 600 601 /** 602 * Add slashes before "_" and "%" characters for using them in MySQL 603 * database, table and field names. 604 * Note: This function does not escape backslashes! 605 * 606 * @param string the string to escape 607 * 608 * @return string the escaped string 609 * 610 * @access public 611 */ 612 function PMA_escape_mysql_wildcards($name) 613 { 614 $name = str_replace('_', '\\_', $name); 615 $name = str_replace('%', '\\%', $name); 616 617 return $name; 618 } // end of the 'PMA_escape_mysql_wildcards()' function 619 620 /** 621 * removes slashes before "_" and "%" characters 622 * Note: This function does not unescape backslashes! 623 * 624 * @param string $name the string to escape 625 * @return string the escaped string 626 * @access public 627 */ 628 function PMA_unescape_mysql_wildcards($name) 629 { 630 $name = str_replace('\\_', '_', $name); 631 $name = str_replace('\\%', '%', $name); 632 633 return $name; 634 } // end of the 'PMA_unescape_mysql_wildcards()' function 635 636 /** 637 * removes quotes (',",`) from a quoted string 638 * 639 * checks if the sting is quoted and removes this quotes 640 * 641 * @param string $quoted_string string to remove quotes from 642 * @param string $quote type of quote to remove 643 * @return string unqoted string 644 */ 645 function PMA_unQuote($quoted_string, $quote = null) 646 { 647 $quotes = array(); 648 649 if (null === $quote) { 650 $quotes[] = '`'; 651 $quotes[] = '"'; 652 $quotes[] = "'"; 653 } else { 654 $quotes[] = $quote; 655 } 656 657 foreach ($quotes as $quote) { 658 if (substr($quoted_string, 0, 1) === $quote 659 && substr($quoted_string, -1, 1) === $quote ) { 660 $unquoted_string = substr($quoted_string, 1, -1); 661 // replace escaped quotes 662 $unquoted_string = str_replace($quote . $quote, $quote, $unquoted_string); 663 return $unquoted_string; 664 } 665 } 666 667 return $quoted_string; 668 } 669 670 /** 671 * format sql strings 672 * 673 * @param mixed pre-parsed SQL structure 674 * 675 * @return string the formatted sql 676 * 677 * @global array the configuration array 678 * @global boolean whether the current statement is a multiple one or not 679 * 680 * @access public 681 * 682 * @author Robin Johnson <robbat2@users.sourceforge.net> 683 */ 684 function PMA_formatSql($parsed_sql, $unparsed_sql = '') 685 { 686 global $cfg; 687 688 // Check that we actually have a valid set of parsed data 689 // well, not quite 690 // first check for the SQL parser having hit an error 691 if (PMA_SQP_isError()) { 692 return $parsed_sql; 693 } 694 // then check for an array 695 if (!is_array($parsed_sql)) { 696 // We don't so just return the input directly 697 // This is intended to be used for when the SQL Parser is turned off 698 $formatted_sql = '<pre>' . "\n" 699 . (($cfg['SQP']['fmtType'] == 'none' && $unparsed_sql != '') ? $unparsed_sql : $parsed_sql) . "\n" 700 . '</pre>'; 701 return $formatted_sql; 702 } 703 704 $formatted_sql = ''; 705 706 switch ($cfg['SQP']['fmtType']) { 707 case 'none': 708 if ($unparsed_sql != '') { 709 $formatted_sql = "<pre>\n" . PMA_SQP_formatNone(array('raw' => $unparsed_sql)) . "\n</pre>"; 710 } else { 711 $formatted_sql = PMA_SQP_formatNone($parsed_sql); 712 } 713 break; 714 case 'html': 715 $formatted_sql = PMA_SQP_formatHtml($parsed_sql, 'color'); 716 break; 717 case 'text': 718 //$formatted_sql = PMA_SQP_formatText($parsed_sql); 719 $formatted_sql = PMA_SQP_formatHtml($parsed_sql, 'text'); 720 break; 721 default: 722 break; 723 } // end switch 724 725 return $formatted_sql; 726 } // end of the "PMA_formatSql()" function 727 728 729 /** 730 * Displays a link to the official MySQL documentation 731 * 732 * @param string chapter of "HTML, one page per chapter" documentation 733 * @param string contains name of page/anchor that is being linked 734 * @param bool whether to use big icon (like in left frame) 735 * 736 * @return string the html link 737 * 738 * @access public 739 */ 740 function PMA_showMySQLDocu($chapter, $link, $big_icon = false) 741 { 742 global $cfg; 743 744 if ($cfg['MySQLManualType'] == 'none' || empty($cfg['MySQLManualBase'])) { 745 return ''; 746 } 747 748 // Fixup for newly used names: 749 $chapter = str_replace('_', '-', strtolower($chapter)); 750 $link = str_replace('_', '-', strtolower($link)); 751 752 switch ($cfg['MySQLManualType']) { 753 case 'chapters': 754 if (empty($chapter)) { 755 $chapter = 'index'; 756 } 757 $url = $cfg['MySQLManualBase'] . '/' . $chapter . '.html#' . $link; 758 break; 759 case 'big': 760 $url = $cfg['MySQLManualBase'] . '#' . $link; 761 break; 762 case 'searchable': 763 if (empty($link)) { 764 $link = 'index'; 765 } 766 $url = $cfg['MySQLManualBase'] . '/' . $link . '.html'; 767 break; 768 case 'viewable': 769 default: 770 if (empty($link)) { 771 $link = 'index'; 772 } 773 $mysql = '5.0'; 774 $lang = 'en'; 775 if (defined('PMA_MYSQL_INT_VERSION')) { 776 if (PMA_MYSQL_INT_VERSION < 50000) { 777 $mysql = '4.1'; 778 if (!empty($GLOBALS['mysql_4_1_doc_lang'])) { 779 $lang = $GLOBALS['mysql_4_1_doc_lang']; 780 } 781 } elseif (PMA_MYSQL_INT_VERSION >= 50100) { 782 $mysql = '5.1'; 783 if (!empty($GLOBALS['mysql_5_1_doc_lang'])) { 784 $lang = $GLOBALS['mysql_5_1_doc_lang']; 785 } 786 } elseif (PMA_MYSQL_INT_VERSION >= 50000) { 787 $mysql = '5.0'; 788 if (!empty($GLOBALS['mysql_5_0_doc_lang'])) { 789 $lang = $GLOBALS['mysql_5_0_doc_lang']; 790 } 791 } 792 } 793 $url = $cfg['MySQLManualBase'] . '/' . $mysql . '/' . $lang . '/' . $link . '.html'; 794 break; 795 } 796 797 if ($big_icon) { 798 return '<a href="' . $url . '" target="mysql_doc"><img class="icon" src="' . $GLOBALS['pmaThemeImage'] . 'b_sqlhelp.png" width="16" height="16" alt="' . $GLOBALS['strDocu'] . '" title="' . $GLOBALS['strDocu'] . '" /></a>'; 799 } elseif ($GLOBALS['cfg']['ReplaceHelpImg']) { 800 return '<a href="' . $url . '" target="mysql_doc"><img class="icon" src="' . $GLOBALS['pmaThemeImage'] . 'b_help.png" width="11" height="11" alt="' . $GLOBALS['strDocu'] . '" title="' . $GLOBALS['strDocu'] . '" /></a>'; 801 } else { 802 return '[<a href="' . $url . '" target="mysql_doc">' . $GLOBALS['strDocu'] . '</a>]'; 803 } 804 } // end of the 'PMA_showMySQLDocu()' function 805 806 /** 807 * Displays a hint icon, on mouse over show the hint 808 * 809 * @param string the error message 810 * 811 * @access public 812 */ 813 function PMA_showHint($hint_message) 814 { 815 //return '<img class="lightbulb" src="' . $GLOBALS['pmaThemeImage'] . 'b_tipp.png" width="16" height="16" border="0" alt="' . $hint_message . '" title="' . $hint_message . '" align="middle" onclick="alert(\'' . PMA_jsFormat($hint_message, false) . '\');" />'; 816 return '<img class="lightbulb" src="' . $GLOBALS['pmaThemeImage'] . 'b_tipp.png" width="16" height="16" alt="Tip" title="Tip" onmouseover="pmaTooltip(\'' . PMA_jsFormat($hint_message, false) . '\'); return false;" onmouseout="swapTooltip(\'default\'); return false;" />'; 817 } 818 819 /** 820 * Displays a MySQL error message in the right frame. 821 * 822 * @param string the error message 823 * @param string the sql query that failed 824 * @param boolean whether to show a "modify" link or not 825 * @param string the "back" link url (full path is not required) 826 * @param boolean EXIT the page? 827 * 828 * @global array the configuration array 829 * 830 * @access public 831 */ 832 function PMA_mysqlDie($error_message = '', $the_query = '', 833 $is_modify_link = true, $back_url = '', 834 $exit = true) 835 { 836 global $cfg, $table, $db, $sql_query; 837 838 /** 839 * start http output, display html headers 840 */ 841 require_once './libraries/header.inc.php'; 842 843 if (!$error_message) { 844 $error_message = PMA_DBI_getError(); 845 } 846 if (!$the_query && !empty($GLOBALS['sql_query'])) { 847 $the_query = $GLOBALS['sql_query']; 848 } 849 850 // --- Added to solve bug #641765 851 // Robbat2 - 12 January 2003, 9:46PM 852 // Revised, Robbat2 - 13 January 2003, 2:59PM 853 if (!function_exists('PMA_SQP_isError') || PMA_SQP_isError()) { 854 $formatted_sql = htmlspecialchars($the_query); 855 } elseif (empty($the_query) || trim($the_query) == '') { 856 $formatted_sql = ''; 857 } else { 858 $formatted_sql = PMA_formatSql(PMA_SQP_parse($the_query), $the_query); 859 } 860 // --- 861 echo "\n" . '<!-- PMA-SQL-ERROR -->' . "\n"; 862 echo ' <div class="error"><h1>' . $GLOBALS['strError'] . '</h1>' . "\n"; 863 // if the config password is wrong, or the MySQL server does not 864 // respond, do not show the query that would reveal the 865 // username/password 866 if (!empty($the_query) && !strstr($the_query, 'connect')) { 867 // --- Added to solve bug #641765 868 // Robbat2 - 12 January 2003, 9:46PM 869 // Revised, Robbat2 - 13 January 2003, 2:59PM 870 if (function_exists('PMA_SQP_isError') && PMA_SQP_isError()) { 871 echo PMA_SQP_getErrorString() . "\n"; 872 echo '<br />' . "\n"; 873 } 874 // --- 875 // modified to show me the help on sql errors (Michael Keck) 876 echo ' <p><strong>' . $GLOBALS['strSQLQuery'] . ':</strong>' . "\n"; 877 if (strstr(strtolower($formatted_sql), 'select')) { // please show me help to the error on select 878 echo PMA_showMySQLDocu('SQL-Syntax', 'SELECT'); 879 } 880 if ($is_modify_link && isset($db)) { 881 if (isset($table)) { 882 $doedit_goto = '<a href="tbl_sql.php?' . PMA_generate_common_url($db, $table) . '&sql_query=' . urlencode($the_query) . '&show_query=1">'; 883 } else { 884 $doedit_goto = '<a href="db_sql.php?' . PMA_generate_common_url($db) . '&sql_query=' . urlencode($the_query) . '&show_query=1">'; 885 } 886 if ($GLOBALS['cfg']['PropertiesIconic']) { 887 echo $doedit_goto 888 . '<img class="icon" src=" '. $GLOBALS['pmaThemeImage'] . 'b_edit.png" width="16" height="16" alt="' . $GLOBALS['strEdit'] .'" />' 889 . '</a>'; 890 } else { 891 echo ' [' 892 . $doedit_goto . $GLOBALS['strEdit'] . '</a>' 893 . ']' . "\n"; 894 } 895 } // end if 896 echo ' </p>' . "\n" 897 .' <p>' . "\n" 898 .' ' . $formatted_sql . "\n" 899 .' </p>' . "\n"; 900 } // end if 901 902 $tmp_mysql_error = ''; // for saving the original $error_message 903 if (!empty($error_message)) { 904 $tmp_mysql_error = strtolower($error_message); // save the original $error_message 905 $error_message = htmlspecialchars($error_message); 906 $error_message = preg_replace("@((\015\012)|(\015)|(\012)){3,}@", "\n\n", $error_message); 907 } 908 // modified to show me the help on error-returns (Michael Keck) 909 // (now error-messages-server) 910 echo '<p>' . "\n" 911 . ' <strong>' . $GLOBALS['strMySQLSaid'] . '</strong>' 912 . PMA_showMySQLDocu('Error-messages-server', 'Error-messages-server') 913 . "\n" 914 . '</p>' . "\n"; 915 916 // The error message will be displayed within a CODE segment. 917 // To preserve original formatting, but allow wordwrapping, we do a couple of replacements 918 919 // Replace all non-single blanks with their HTML-counterpart 920 $error_message = str_replace(' ', ' ', $error_message); 921 // Replace TAB-characters with their HTML-counterpart 922 $error_message = str_replace("\t", ' ', $error_message); 923 // Replace linebreaks 924 $error_message = nl2br($error_message); 925 926 echo '<code>' . "\n" 927 . $error_message . "\n" 928 . '</code><br />' . "\n"; 929 930 // feature request #1036254: 931 // Add a link by MySQL-Error #1062 - Duplicate entry 932 // 2004-10-20 by mkkeck 933 // 2005-01-17 modified by mkkeck bugfix 934 if (substr($error_message, 1, 4) == '1062') { 935 // get the duplicate entry 936 937 // get table name 938 /** 939 * @todo what would be the best delimiter, while avoiding special 940 * characters that can become high-ascii after editing, depending 941 * upon which editor is used by the developer? 942 */ 943 $error_table = array(); 944 if (preg_match('@ALTER\s*TABLE\s*\`([^\`]+)\`@iu', $the_query, $error_table)) { 945 $error_table = $error_table[1]; 946 } elseif (preg_match('@INSERT\s*INTO\s*\`([^\`]+)\`@iu', $the_query, $error_table)) { 947 $error_table = $error_table[1]; 948 } elseif (preg_match('@UPDATE\s*\`([^\`]+)\`@iu', $the_query, $error_table)) { 949 $error_table = $error_table[1]; 950 } elseif (preg_match('@INSERT\s*\`([^\`]+)\`@iu', $the_query, $error_table)) { 951 $error_table = $error_table[1]; 952 } 953 954 // get fields 955 $error_fields = array(); 956 if (preg_match('@\(([^\)]+)\)@i', $the_query, $error_fields)) { 957 $error_fields = explode(',', $error_fields[1]); 958 } elseif (preg_match('@(`[^`]+`)\s*=@i', $the_query, $error_fields)) { 959 $error_fields = explode(',', $error_fields[1]); 960 } 961 if (is_array($error_table) || is_array($error_fields)) { 962 963 // duplicate value 964 $duplicate_value = array(); 965 preg_match('@\'([^\']+)\'@i', $tmp_mysql_error, $duplicate_value); 966 $duplicate_value = $duplicate_value[1]; 967 968 $sql = ' 969 SELECT * 970 FROM ' . PMA_backquote($error_table) . ' 971 WHERE CONCAT_WS("-", ' . implode(', ', $error_fields) . ') 972 = "' . PMA_sqlAddslashes($duplicate_value) . '" 973 ORDER BY ' . implode(', ', $error_fields); 974 unset($error_table, $error_fields, $duplicate_value); 975 976 echo ' <form method="post" action="import.php" style="padding: 0; margin: 0">' ."\n" 977 .' <input type="hidden" name="sql_query" value="' . htmlentities($sql) . '" />' . "\n" 978 .' ' . PMA_generate_common_hidden_inputs($db, $table) . "\n" 979 .' <input type="submit" name="submit" value="' . $GLOBALS['strBrowse'] . '" />' . "\n" 980 .' </form>' . "\n"; 981 unset($sql); 982 } 983 } // end of show duplicate entry 984 985 echo '</div>'; 986 echo '<fieldset class="tblFooters">'; 987 988 if (!empty($back_url) && $exit) { 989 $goto_back_url='<a href="' . (strstr($back_url, '?') ? $back_url . '&no_history=true' : $back_url . '?no_history=true') . '">'; 990 echo '[ ' . $goto_back_url . $GLOBALS['strBack'] . '</a> ]'; 991 } 992 echo ' </fieldset>' . "\n\n"; 993 if ($exit) { 994 /** 995 * display footer and exit 996 */ 997 require_once './libraries/footer.inc.php'; 998 } 999 } // end of the 'PMA_mysqlDie()' function 1000 1001 /** 1002 * Returns a string formatted with CONVERT ... USING 1003 * if MySQL supports it 1004 * 1005 * @param string the string itself 1006 * @param string the mode: quoted or unquoted (this one by default) 1007 * 1008 * @return the formatted string 1009 * 1010 * @access private 1011 */ 1012 function PMA_convert_using($string, $mode='unquoted') 1013 { 1014 if ($mode == 'quoted') { 1015 $possible_quote = "'"; 1016 } else { 1017 $possible_quote = ""; 1018 } 1019 1020 if (PMA_MYSQL_INT_VERSION >= 40100) { 1021 list($conn_charset) = explode('_', $GLOBALS['collation_connection']); 1022 $converted_string = "CONVERT(" . $possible_quote . $string . $possible_quote . " USING " . $conn_charset . ")"; 1023 } else { 1024 $converted_string = $possible_quote . $string . $possible_quote; 1025 } 1026 return $converted_string; 1027 } // end function 1028 1029 /** 1030 * Send HTTP header, taking IIS limits into account (600 seems ok) 1031 * 1032 * @param string $uri the header to send 1033 * @return boolean always true 1034 */ 1035 function PMA_sendHeaderLocation($uri) 1036 { 1037 if (PMA_IS_IIS && strlen($uri) > 600) { 1038 1039 echo '<html><head><title>- - -</title>' . "\n"; 1040 echo '<meta http-equiv="expires" content="0">' . "\n"; 1041 echo '<meta http-equiv="Pragma" content="no-cache">' . "\n"; 1042 echo '<meta http-equiv="Cache-Control" content="no-cache">' . "\n"; 1043 echo '<meta http-equiv="Refresh" content="0;url=' .$uri . '">' . "\n"; 1044 echo '<script type="text/javascript" language="javascript">' . "\n"; 1045 echo '//<![CDATA[' . "\n"; 1046 echo 'setTimeout ("window.location = unescape(\'"' . $uri . '"\')",2000); </script>' . "\n"; 1047 echo '//]]>' . "\n"; 1048 echo '</head>' . "\n"; 1049 echo '<body>' . "\n"; 1050 echo '<script type="text/javascript" language="javascript">' . "\n"; 1051 echo '//<![CDATA[' . "\n"; 1052 echo 'document.write (\'<p><a href="' . $uri . '">' . $GLOBALS['strGo'] . '</a></p>\');' . "\n"; 1053 echo '//]]>' . "\n"; 1054 echo '</script></body></html>' . "\n"; 1055 1056 } else { 1057 if (SID) { 1058 if (strpos($uri, '?') === false) { 1059 header('Location: ' . $uri . '?' . SID); 1060 } else { 1061 $separator = PMA_get_arg_separator(); 1062 header('Location: ' . $uri . $separator . SID); 1063 } 1064 } else { 1065 session_write_close(); 1066 if (headers_sent()) { 1067 if (function_exists('debug_print_backtrace')) { 1068 echo '<pre>'; 1069 debug_print_backtrace(); 1070 echo '</pre>'; 1071 } 1072 trigger_error('PMA_sendHeaderLocation called when headers are already sent!', E_USER_ERROR); 1073 } 1074 // bug #1523784: IE6 does not like 'Refresh: 0', it 1075 // results in a blank page 1076 // but we need it when coming from the cookie login panel) 1077 if (PMA_IS_IIS && defined('PMA_COMING_FROM_COOKIE_LOGIN')) { 1078 header('Refresh: 0; ' . $uri); 1079 } else { 1080 header('Location: ' . $uri); 1081 } 1082 } 1083 } 1084 } 1085 1086 /** 1087 * returns array with tables of given db with extended infomation and grouped 1088 * 1089 * @uses $GLOBALS['cfg']['LeftFrameTableSeparator'] 1090 * @uses $GLOBALS['cfg']['LeftFrameTableLevel'] 1091 * @uses $GLOBALS['cfg']['ShowTooltipAliasTB'] 1092 * @uses $GLOBALS['cfg']['NaturalOrder'] 1093 * @uses PMA_backquote() 1094 * @uses count() 1095 * @uses array_merge 1096 * @uses uksort() 1097 * @uses strstr() 1098 * @uses explode() 1099 * @param string $db name of db 1100 * return array (rekursive) grouped table list 1101 */ 1102 function PMA_getTableList($db, $tables = null) 1103 { 1104 $sep = $GLOBALS['cfg']['LeftFrameTableSeparator']; 1105 1106 if ( null === $tables ) { 1107 $tables = PMA_DBI_get_tables_full($db); 1108 if ($GLOBALS['cfg']['NaturalOrder']) { 1109 uksort($tables, 'strnatcasecmp'); 1110 } 1111 } 1112 1113 if (count($tables) < 1) { 1114 return $tables; 1115 } 1116 1117 $default = array( 1118 'Name' => '', 1119 'Rows' => 0, 1120 'Comment' => '', 1121 'disp_name' => '', 1122 ); 1123 1124 $table_groups = array(); 1125 1126 foreach ($tables as $table_name => $table) { 1127 1128 // check for correct row count 1129 if (null === $table['Rows']) { 1130 // Do not check exact row count here, 1131 // if row count is invalid possibly the table is defect 1132 // and this would break left frame; 1133 // but we can check row count if this is a view, 1134 // since PMA_Table::countRecords() returns a limited row count 1135 // in this case. 1136 1137 // set this because PMA_Table::countRecords() can use it 1138 $tbl_is_view = PMA_Table::isView($db, $table['Name']); 1139 1140 if ($tbl_is_view) { 1141 $table['Rows'] = PMA_Table::countRecords($db, $table['Name'], 1142 $return = true); 1143 } 1144 } 1145 1146 // in $group we save the reference to the place in $table_groups 1147 // where to store the table info 1148 if ($GLOBALS['cfg']['LeftFrameDBTree'] 1149 && $sep && strstr($table_name, $sep)) 1150 { 1151 $parts = explode($sep, $table_name); 1152 1153 $group =& $table_groups; 1154 $i = 0; 1155 $group_name_full = ''; 1156 while ($i < count($parts) - 1 1157 && $i < $GLOBALS['cfg']['LeftFrameTableLevel']) { 1158 $group_name = $parts[$i] . $sep; 1159 $group_name_full .= $group_name; 1160 1161 if (!isset($group[$group_name])) { 1162 $group[$group_name] = array(); 1163 $group[$group_name]['is' . $sep . 'group'] = true; 1164 $group[$group_name]['tab' . $sep . 'count'] = 1; 1165 $group[$group_name]['tab' . $sep . 'group'] = $group_name_full; 1166 } elseif (!isset($group[$group_name]['is' . $sep . 'group'])) { 1167 $table = $group[$group_name]; 1168 $group[$group_name] = array(); 1169 $group[$group_name][$group_name] = $table; 1170 unset($table); 1171 $group[$group_name]['is' . $sep . 'group'] = true; 1172 $group[$group_name]['tab' . $sep . 'count'] = 1; 1173 $group[$group_name]['tab' . $sep . 'group'] = $group_name_full; 1174 } else { 1175 $group[$group_name]['tab' . $sep . 'count']++; 1176 } 1177 $group =& $group[$group_name]; 1178 $i++; 1179 } 1180 } else { 1181 if (!isset($table_groups[$table_name])) { 1182 $table_groups[$table_name] = array(); 1183 } 1184 $group =& $table_groups; 1185 } 1186 1187 1188 if ($GLOBALS['cfg']['ShowTooltipAliasTB'] 1189 && $GLOBALS['cfg']['ShowTooltipAliasTB'] !== 'nested') { 1190 // switch tooltip and name 1191 $table['Comment'] = $table['Name']; 1192 $table['disp_name'] = $table['Comment']; 1193 } else { 1194 $table['disp_name'] = $table['Name']; 1195 } 1196 1197 $group[$table_name] = array_merge($default, $table); 1198 } 1199 1200 return $table_groups; 1201 } 1202 1203 /* ----------------------- Set of misc functions ----------------------- */ 1204 1205 1206 /** 1207 * Adds backquotes on both sides of a database, table or field name. 1208 * and escapes backquotes inside the name with another backquote 1209 * 1210 * <code> 1211 * echo PMA_backquote('owner`s db'); // `owner``s db` 1212 * </code> 1213 * 1214 * @param mixed $a_name the database, table or field name to "backquote" 1215 * or array of it 1216 * @param boolean $do_it a flag to bypass this function (used by dump 1217 * functions) 1218 * @return mixed the "backquoted" database, table or field name if the 1219 * current MySQL release is >= 3.23.6, the original one 1220 * else 1221 * @access public 1222 */ 1223 function PMA_backquote($a_name, $do_it = true) 1224 { 1225 if (! $do_it) { 1226 return $a_name; 1227 } 1228 1229 if (is_array($a_name)) { 1230 $result = array(); 1231 foreach ($a_name as $key => $val) { 1232 $result[$key] = PMA_backquote($val); 1233 } 1234 return $result; 1235 } 1236 1237 // '0' is also empty for php :-( 1238 if (strlen($a_name) && $a_name !== '*') { 1239 return '`' . str_replace('`', '``', $a_name) . '`'; 1240 } else { 1241 return $a_name; 1242 } 1243 } // end of the 'PMA_backquote()' function 1244 1245 1246 /** 1247 * Defines the <CR><LF> value depending on the user OS. 1248 * 1249 * @return string the <CR><LF> value to use 1250 * 1251 * @access public 1252 */ 1253 function PMA_whichCrlf() 1254 { 1255 $the_crlf = "\n"; 1256 1257 // The 'PMA_USR_OS' constant is defined in "./libraries/defines.lib.php" 1258 // Win case 1259 if (PMA_USR_OS == 'Win') { 1260 $the_crlf = "\r\n"; 1261 } 1262 // Others 1263 else { 1264 $the_crlf = "\n"; 1265 } 1266 1267 return $the_crlf; 1268 } // end of the 'PMA_whichCrlf()' function 1269 1270 /** 1271 * Reloads navigation if needed. 1272 * 1273 * @global mixed configuration 1274 * @global bool whether to reload 1275 * 1276 * @access public 1277 */ 1278 function PMA_reloadNavigation() 1279 { 1280 global $cfg; 1281 1282 // Reloads the navigation frame via JavaScript if required 1283 if (isset($GLOBALS['reload']) && $GLOBALS['reload']) { 1284 echo "\n"; 1285 $reload_url = './navigation.php?' . PMA_generate_common_url((isset($GLOBALS['db']) ? $GLOBALS['db'] : ''), '', '&'); 1286 ?> 1287 <script type="text/javascript" language="javascript"> 1288 //<![CDATA[ 1289 if (typeof(window.parent) != 'undefined' 1290 && typeof(window.parent.frame_navigation) != 'undefined') { 1291 window.parent.goTo('<?php echo $reload_url; ?>'); 1292 } 1293 //]]> 1294 </script> 1295 <?php 1296 unset($GLOBALS['reload']); 1297 } 1298 } 1299 1300 /** 1301 * displays the message and the query 1302 * usually the message is the result of the query executed 1303 * 1304 * @param string $message the message to display 1305 * @param string $sql_query the query to display 1306 * @global array the configuration array 1307 * @uses $GLOBALS['cfg'] 1308 * @access public 1309 */ 1310 function PMA_showMessage($message, $sql_query = null) 1311 { 1312 global $cfg; 1313 1314 if (null === $sql_query) { 1315 if (! empty($GLOBALS['display_query'])) { 1316 $sql_query = $GLOBALS['display_query']; 1317 } elseif ($cfg['SQP']['fmtType'] == 'none' && ! empty($GLOBALS['unparsed_sql'])) { 1318 $sql_query = $GLOBALS['unparsed_sql']; 1319 // could be empty, for example export + save on server 1320 } elseif (! empty($GLOBALS['sql_query'])) { 1321 $sql_query = $GLOBALS['sql_query']; 1322 } else { 1323 $sql_query = ''; 1324 } 1325 } 1326 1327 // Corrects the tooltip text via JS if required 1328 // @todo this is REALLY the wrong place to do this - very unexpected here 1329 if ( isset($GLOBALS['table']) && strlen($GLOBALS['table']) && $cfg['ShowTooltip']) { 1330 $result = PMA_DBI_try_query('SHOW TABLE STATUS FROM ' . PMA_backquote($GLOBALS['db']) . ' LIKE \'' . PMA_sqlAddslashes($GLOBALS['table'], true) . '\''); 1331 if ($result) { 1332 $tbl_status = PMA_DBI_fetch_assoc($result); 1333 $tooltip = (empty($tbl_status['Comment'])) 1334 ? '' 1335 : $tbl_status['Comment'] . ' '; 1336 $tooltip .= '(' . PMA_formatNumber($tbl_status['Rows'], 0) . ' ' . $GLOBALS['strRows'] . ')'; 1337 PMA_DBI_free_result($result); 1338 $uni_tbl = PMA_jsFormat($GLOBALS['db'] . '.' . $GLOBALS['table'], false); 1339 echo "\n"; 1340 echo '<script type="text/javascript" language="javascript">' . "\n"; 1341 echo '//<![CDATA[' . "\n"; 1342 echo "window.parent.updateTableTitle('" . $uni_tbl . "', '" . PMA_jsFormat($tooltip, false) . "');" . "\n"; 1343 echo '//]]>' . "\n"; 1344 echo '</script>' . "\n"; 1345 } // end if 1346 } // end if ... elseif 1347 1348 // Checks if the table needs to be repaired after a TRUNCATE query. 1349 // @todo this should only be done if isset($GLOBALS['sql_query']), what about $GLOBALS['display_query']??? 1350 // @todo this is REALLY the wrong place to do this - very unexpected here 1351 if (isset($GLOBALS['table']) && isset($GLOBALS['sql_query']) 1352 && $GLOBALS['sql_query'] == 'TRUNCATE TABLE ' . PMA_backquote($GLOBALS['table'])) { 1353 if (!isset($tbl_status)) { 1354 $result = @PMA_DBI_try_query('SHOW TABLE STATUS FROM ' . PMA_backquote($GLOBALS['db']) . ' LIKE \'' . PMA_sqlAddslashes($GLOBALS['table'], true) . '\''); 1355 if ($result) { 1356 $tbl_status = PMA_DBI_fetch_assoc($result); 1357 PMA_DBI_free_result($result); 1358 } 1359 } 1360 if (isset($tbl_status) && (int) $tbl_status['Index_length'] > 1024) { 1361 PMA_DBI_try_query('REPAIR TABLE ' . PMA_backquote($GLOBALS['table'])); 1362 } 1363 } 1364 unset($tbl_status); 1365 echo '<br />' . "\n"; 1366 1367 echo '<div align="' . $GLOBALS['cell_align_left'] . '">' . "\n"; 1368 if (!empty($GLOBALS['show_error_header'])) { 1369 echo '<div class="error">' . "\n"; 1370 echo '<h1>' . $GLOBALS['strError'] . '</h1>' . "\n"; 1371 } 1372 1373 echo '<div class="notice">'; 1374 echo PMA_sanitize($message); 1375 if (isset($GLOBALS['special_message'])) { 1376 echo PMA_sanitize($GLOBALS['special_message']); 1377 unset($GLOBALS['special_message']); 1378 } 1379 echo '</div>'; 1380 1381 if (!empty($GLOBALS['show_error_header'])) { 1382 echo '</div>'; 1383 } 1384 1385 if ($cfg['ShowSQL'] == true && ! empty($sql_query)) { 1386 // Basic url query part 1387 $url_qpart = '?' . PMA_generate_common_url(isset($GLOBALS['db']) ? $GLOBALS['db'] : '', isset($GLOBALS['table']) ? $GLOBALS['table'] : ''); 1388 1389 // Html format the query to be displayed 1390 // The nl2br function isn't used because its result isn't a valid 1391 // xhtml1.0 statement before php4.0.5 ("<br>" and not "<br />") 1392 // If we want to show some sql code it is easiest to create it here 1393 /* SQL-Parser-Analyzer */ 1394 1395 if (!empty($GLOBALS['show_as_php'])) { 1396 $new_line = '\'<br />' . "\n" . ' . \' '; 1397 } 1398 if (isset($new_line)) { 1399 /* SQL-Parser-Analyzer */ 1400 $query_base = PMA_sqlAddslashes(htmlspecialchars($sql_query), false, false, true); 1401 /* SQL-Parser-Analyzer */ 1402 $query_base = preg_replace("@((\015\012)|(\015)|(\012))+@", $new_line, $query_base); 1403 } else { 1404 $query_base = $sql_query; 1405 } 1406 1407 $max_characters = 1000; 1408 if (! defined('PMA_QUERY_TOO_BIG') && strlen($query_base) > $max_characters) { 1409 define('PMA_QUERY_TOO_BIG',1); 1410 $query_base = nl2br(htmlspecialchars($sql_query)); 1411 } 1412 1413 // Parse SQL if needed 1414 // (here, use "! empty" because when deleting a bookmark, 1415 // $GLOBALS['parsed_sql'] is set but empty 1416 if (! empty($GLOBALS['parsed_sql']) && $query_base == $GLOBALS['parsed_sql']['raw']) { 1417 $parsed_sql = $GLOBALS['parsed_sql']; 1418 } else { 1419 // when the query is large (for example an INSERT of binary 1420 // data), the parser chokes; so avoid parsing the query 1421 if (! defined('PMA_QUERY_TOO_BIG')) { 1422 $parsed_sql = PMA_SQP_parse($query_base); 1423 } 1424 } 1425 1426 // Analyze it 1427 if (isset($parsed_sql)) { 1428 $analyzed_display_query = PMA_SQP_analyze($parsed_sql); 1429 } 1430 1431 // Here we append the LIMIT added for navigation, to 1432 // enable its display. Adding it higher in the code 1433 // to $sql_query would create a problem when 1434 // using the Refresh or Edit links. 1435 1436 // Only append it on SELECTs. 1437 1438 /** 1439 * @todo what would be the best to do when someone hits Refresh: 1440 * use the current LIMITs ? 1441 */ 1442 1443 if (isset($analyzed_display_query[0]['queryflags']['select_from']) 1444 && isset($GLOBALS['sql_limit_to_append'])) { 1445 $query_base = $analyzed_display_query[0]['section_before_limit'] . "\n" . $GLOBALS['sql_limit_to_append'] . $analyzed_display_query[0]['section_after_limit']; 1446 // Need to reparse query 1447 $parsed_sql = PMA_SQP_parse($query_base); 1448 } 1449 1450 if (!empty($GLOBALS['show_as_php'])) { 1451 $query_base = '$sql = \'' . $query_base; 1452 } elseif (!empty($GLOBALS['validatequery'])) { 1453 $query_base = PMA_validateSQL($query_base); 1454 } else { 1455 if (isset($parsed_sql)) { 1456 $query_base = PMA_formatSql($parsed_sql, $query_base); 1457 } 1458 } 1459 1460 // Prepares links that may be displayed to edit/explain the query 1461 // (don't go to default pages, we must go to the page 1462 // where the query box is available) 1463 1464 $edit_target = isset($GLOBALS['db']) ? (isset($GLOBALS['table']) ? 'tbl_sql.php' : 'db_sql.php') : 'server_sql.php'; 1465 1466 if (isset($cfg['SQLQuery']['Edit']) 1467 && ($cfg['SQLQuery']['Edit'] == true) 1468 && (!empty($edit_target)) 1469 && ! defined('PMA_QUERY_TOO_BIG')) { 1470 1471 if ($cfg['EditInWindow'] == true) { 1472 $onclick = 'window.parent.focus_querywindow(\'' . PMA_jsFormat($sql_query, false) . '\'); return false;'; 1473 } else { 1474 $onclick = ''; 1475 } 1476 1477 $edit_link = $edit_target 1478 . $url_qpart 1479 . '&sql_query=' . urlencode($sql_query) 1480 . '&show_query=1#querybox'; 1481 $edit_link = ' [' . PMA_linkOrButton($edit_link, $GLOBALS['strEdit'], array('onclick' => $onclick)) . ']'; 1482 } else { 1483 $edit_link = ''; 1484 } 1485 1486 // Want to have the query explained (Mike Beck 2002-05-22) 1487 // but only explain a SELECT (that has not been explained) 1488 /* SQL-Parser-Analyzer */ 1489 if (isset($cfg['SQLQuery']['Explain']) 1490 && $cfg['SQLQuery']['Explain'] == true 1491 && ! defined('PMA_QUERY_TOO_BIG')) { 1492 1493 // Detect if we are validating as well 1494 // To preserve the validate uRL data 1495 if (!empty($GLOBALS['validatequery'])) { 1496 $explain_link_validate = '&validatequery=1'; 1497 } else { 1498 $explain_link_validate = ''; 1499 } 1500 1501 $explain_link = 'import.php' 1502 . $url_qpart 1503 . $explain_link_validate 1504 . '&sql_query='; 1505 1506 if (preg_match('@^SELECT[[:space:]]+@i', $sql_query)) { 1507 $explain_link .= urlencode('EXPLAIN ' . $sql_query); 1508 $message = $GLOBALS['strExplain']; 1509 } elseif (preg_match('@^EXPLAIN[[:space:]]+SELECT[[:space:]]+@i', $sql_query)) { 1510 $explain_link .= urlencode(substr($sql_query, 8)); 1511 $message = $GLOBALS['strNoExplain']; 1512 } else { 1513 $explain_link = ''; 1514 } 1515 if (!empty($explain_link)) { 1516 $explain_link = ' [' . PMA_linkOrButton($explain_link, $message) . ']'; 1517 } 1518 } else { 1519 $explain_link = ''; 1520 } //show explain 1521 1522 // Also we would like to get the SQL formed in some nice 1523 // php-code (Mike Beck 2002-05-22) 1524 if (isset($cfg['SQLQuery']['ShowAsPHP']) 1525 && $cfg['SQLQuery']['ShowAsPHP'] == true 1526 && ! defined('PMA_QUERY_TOO_BIG')) { 1527 $php_link = 'import.php' 1528 . $url_qpart 1529 . '&show_query=1' 1530 . '&sql_query=' . urlencode($sql_query) 1531 . '&show_as_php='; 1532 1533 if (!empty($GLOBALS['show_as_php'])) { 1534 $php_link .= '0'; 1535 $message = $GLOBALS['strNoPhp']; 1536 } else { 1537 $php_link .= '1'; 1538 $message = $GLOBALS['strPhp']; 1539 } 1540 $php_link = ' [' . PMA_linkOrButton($php_link, $message) . ']'; 1541 1542 if (isset($GLOBALS['show_as_php'])) { 1543 $runquery_link 1544 = 'import.php' 1545 . $url_qpart 1546 . '&show_query=1' 1547 . '&sql_query=' . urlencode($sql_query); 1548 $php_link .= ' [' . PMA_linkOrButton($runquery_link, $GLOBALS['strRunQuery']) . ']'; 1549 } 1550 1551 } else { 1552 $php_link = ''; 1553 } //show as php 1554 1555 // Refresh query 1556 if (isset($cfg['SQLQuery']['Refresh']) 1557 && $cfg['SQLQuery']['Refresh'] 1558 && preg_match('@^(SELECT|SHOW)[[:space:]]+@i', $sql_query)) { 1559 1560 $refresh_link = 'import.php' 1561 . $url_qpart 1562 . '&show_query=1' 1563 . (isset($_GET['pos']) ? '&pos=' . $_GET['pos'] : '') 1564 . '&sql_query=' . urlencode($sql_query); 1565 $refresh_link = ' [' . PMA_linkOrButton($refresh_link, $GLOBALS['strRefresh']) . ']'; 1566 } else { 1567 $refresh_link = ''; 1568 } //show as php 1569 1570 if (isset($cfg['SQLValidator']['use']) 1571 && $cfg['SQLValidator']['use'] == true 1572 && isset($cfg['SQLQuery']['Validate']) 1573 && $cfg['SQLQuery']['Validate'] == true) { 1574 $validate_link = 'import.php' 1575 . $url_qpart 1576 . '&show_query=1' 1577 . '&sql_query=' . urlencode($sql_query) 1578 . '&validatequery='; 1579 if (!empty($GLOBALS['validatequery'])) { 1580 $validate_link .= '0'; 1581 $validate_message = $GLOBALS['strNoValidateSQL'] ; 1582 } else { 1583 $validate_link .= '1'; 1584 $validate_message = $GLOBALS['strValidateSQL'] ; 1585 } 1586 $validate_link = ' [' . PMA_linkOrButton($validate_link, $validate_message) . ']'; 1587 } else { 1588 $validate_link = ''; 1589 } //validator 1590 unset($sql_query); 1591 1592 // Displays the message 1593 echo '<fieldset class="">' . "\n"; 1594 echo ' <legend>' . $GLOBALS['strSQLQuery'] . ':</legend>'; 1595 echo ' <div>'; 1596 // when uploading a 700 Kio binary file into a LONGBLOB, 1597 // I get a white page, strlen($query_base) is 2 x 700 Kio 1598 // so put a hard limit here (let's say 1000) 1599 if (defined('PMA_QUERY_TOO_BIG')) { 1600 echo ' ' . substr($query_base,0,$max_characters) . '[...]'; 1601 } else { 1602 echo ' ' . $query_base; 1603 } 1604 1605 //Clean up the end of the PHP 1606 if (!empty($GLOBALS['show_as_php'])) { 1607 echo '\';'; 1608 } 1609 echo ' </div>'; 1610 echo '</fieldset>' . "\n"; 1611 1612 if (!empty($edit_target)) { 1613 echo '<fieldset class="tblFooters">'; 1614 echo $edit_link . $explain_link . $php_link . $refresh_link . $validate_link; 1615 echo '</fieldset>'; 1616 } 1617 } 1618 echo '</div><br />' . "\n"; 1619 } // end of the 'PMA_showMessage()' function 1620 1621 1622 /** 1623 * Formats $value to byte view 1624 * 1625 * @param double the value to format 1626 * @param integer the sensitiveness 1627 * @param integer the number of decimals to retain 1628 * 1629 * @return array the formatted value and its unit 1630 * 1631 * @access public 1632 * 1633 * @author staybyte 1634 * @version 1.2 - 18 July 2002 1635 */ 1636 function PMA_formatByteDown($value, $limes = 6, $comma = 0) 1637 { 1638 $dh = PMA_pow(10, $comma); 1639 $li = PMA_pow(10, $limes); 1640 $return_value = $value; 1641 $unit = $GLOBALS['byteUnits'][0]; 1642 1643 for ($d = 6, $ex = 15; $d >= 1; $d--, $ex-=3) { 1644 if (isset($GLOBALS['byteUnits'][$d]) && $value >= $li * PMA_pow(10, $ex)) { 1645 // use 1024.0 to avoid integer overflow on 64-bit machines 1646 $value = round($value / (PMA_pow(1024, $d) / $dh)) /$dh; 1647 $unit = $GLOBALS['byteUnits'][$d]; 1648 break 1; 1649 } // end if 1650 } // end for 1651 1652 if ($unit != $GLOBALS['byteUnits'][0]) { 1653 $return_value = number_format($value, $comma, $GLOBALS['number_decimal_separator'], $GLOBALS['number_thousands_separator']); 1654 } else { 1655 $return_value = number_format($value, 0, $GLOBALS['number_decimal_separator'], $GLOBALS['number_thousands_separator']); 1656 } 1657 1658 return array($return_value, $unit); 1659 } // end of the 'PMA_formatByteDown' function 1660 1661 /** 1662 * Formats $value to the given length and appends SI prefixes 1663 * $comma is not substracted from the length 1664 * with a $length of 0 no truncation occurs, number is only formated 1665 * to the current locale 1666 * <code> 1667 * echo PMA_formatNumber(123456789, 6); // 123,457 k 1668 * echo PMA_formatNumber(-123456789, 4, 2); // -123.46 M 1669 * echo PMA_formatNumber(-0.003, 6); // -3 m 1670 * echo PMA_formatNumber(0.003, 3, 3); // 0.003 1671 * echo PMA_formatNumber(0.00003, 3, 2); // 0.03 m 1672 * echo PMA_formatNumber(0, 6); // 0 1673 * </code> 1674 * @param double $value the value to format 1675 * @param integer $length the max length 1676 * @param integer $comma the number of decimals to retain 1677 * @param boolean $only_down do not reformat numbers below 1 1678 * 1679 * @return string the formatted value and its unit 1680 * 1681 * @access public 1682 * 1683 * @author staybyte, sebastian mendel 1684 * @version 1.1.0 - 2005-10-27 1685 */ 1686 function PMA_formatNumber($value, $length = 3, $comma = 0, $only_down = false) 1687 { 1688 if ($length === 0) { 1689 return number_format($value, 1690 $comma, 1691 $GLOBALS['number_decimal_separator'], 1692 $GLOBALS['number_thousands_separator']); 1693 } 1694 1695 // this units needs no translation, ISO 1696 $units = array( 1697 -8 => 'y', 1698 -7 => 'z', 1699 -6 => 'a', 1700 -5 => 'f', 1701 -4 => 'p', 1702 -3 => 'n', 1703 -2 => 'µ', 1704 -1 => 'm', 1705 0 => ' ', 1706 1 => 'k', 1707 2 => 'M', 1708 3 => 'G', 1709 4 => 'T', 1710 5 => 'P', 1711 6 => 'E', 1712 7 => 'Z', 1713 8 => 'Y' 1714 ); 1715 1716 // we need at least 3 digits to be displayed 1717 if (3 > $length + $comma) { 1718 $length = 3 - $comma; 1719 } 1720 1721 // check for negativ value to retain sign 1722 if ($value < 0) { 1723 $sign = '-'; 1724 $value = abs($value); 1725 } else { 1726 $sign = ''; 1727 } 1728 1729 $dh = PMA_pow(10, $comma); 1730 $li = PMA_pow(10, $length); 1731 $unit = $units[0]; 1732 1733 if ($value >= 1) { 1734 for ($d = 8; $d >= 0; $d--) { 1735 if (isset($units[$d]) && $value >= $li * PMA_pow(1000, $d-1)) { 1736 $value = round($value / (PMA_pow(1000, $d) / $dh)) /$dh; 1737 $unit = $units[$d]; 1738 break 1; 1739 } // end if 1740 } // end for 1741 } elseif (!$only_down && (float) $value !== 0.0) { 1742 for ($d = -8; $d <= 8; $d++) { 1743 if (isset($units[$d]) && $value <= $li * PMA_pow(1000, $d-1)) { 1744 $value = round($value / (PMA_pow(1000, $d) / $dh)) /$dh; 1745 $unit = $units[$d]; 1746 break 1; 1747 } // end if 1748 } // end for 1749 } // end if ($value >= 1) elseif (!$only_down && (float) $value !== 0.0) 1750 1751 $value = number_format($value, 1752 $comma, 1753 $GLOBALS['number_decimal_separator'], 1754 $GLOBALS['number_thousands_separator']); 1755 1756 return $sign . $value . ' ' . $unit; 1757 } // end of the 'PMA_formatNumber' function 1758 1759 /** 1760 * Extracts ENUM / SET options from a type definition string 1761 * 1762 * @param string The column type definition 1763 * 1764 * @return array The options or 1765 * boolean false in case of an error. 1766 * 1767 * @author rabus 1768 */ 1769 function PMA_getEnumSetOptions($type_def) 1770 { 1771 $open = strpos($type_def, '('); 1772 $close = strrpos($type_def, ')'); 1773 if (!$open || !$close) { 1774 return false; 1775 } 1776 $options = substr($type_def, $open + 2, $close - $open - 3); 1777 $options = explode('\',\'', $options); 1778 return $options; 1779 } // end of the 'PMA_getEnumSetOptions' function 1780 1781 /** 1782 * Writes localised date 1783 * 1784 * @param string the current timestamp 1785 * 1786 * @return string the formatted date 1787 * 1788 * @access public 1789 */ 1790 function PMA_localisedDate($timestamp = -1, $format = '') 1791 { 1792 global $datefmt, $month, $day_of_week; 1793 1794 if ($format == '') { 1795 $format = $datefmt; 1796 } 1797 1798 if ($timestamp == -1) { 1799 $timestamp = time(); 1800 } 1801 1802 $date = preg_replace('@%[aA]@', $day_of_week[(int)strftime('%w', $timestamp)], $format); 1803 $date = preg_replace('@%[bB]@', $month[(int)strftime('%m', $timestamp)-1], $date); 1804 1805 return strftime($date, $timestamp); 1806 } // end of the 'PMA_localisedDate()' function 1807 1808 1809 /** 1810 * returns a tab for tabbed navigation. 1811 * If the variables $link and $args ar left empty, an inactive tab is created 1812 * 1813 * @uses array_merge() 1814 * basename() 1815 * $GLOBALS['strEmpty'] 1816 * $GLOBALS['strDrop'] 1817 * $GLOBALS['active_page'] 1818 * $GLOBALS['PHP_SELF'] 1819 * htmlentities() 1820 * PMA_generate_common_url() 1821 * $GLOBALS['url_query'] 1822 * urlencode() 1823 * $GLOBALS['cfg']['MainPageIconic'] 1824 * $GLOBALS['pmaThemeImage'] 1825 * sprintf() 1826 * trigger_error() 1827 * E_USER_NOTICE 1828 * @param array $tab array with all options 1829 * @return string html code for one tab, a link if valid otherwise a span 1830 * @access public 1831 */ 1832 function PMA_getTab($tab) 1833 { 1834 // default values 1835 $defaults = array( 1836 'text' => '', 1837 'class' => '', 1838 'active' => false, 1839 'link' => '', 1840 'sep' => '?', 1841 'attr' => '', 1842 'args' => '', 1843 'warning' => '', 1844 ); 1845 1846 $tab = array_merge($defaults, $tab); 1847 1848 // determine additionnal style-class 1849 if (empty($tab['class'])) { 1850 if ($tab['text'] == $GLOBALS['strEmpty'] 1851 || $tab['text'] == $GLOBALS['strDrop']) { 1852 $tab['class'] = 'caution'; 1853 } elseif (!empty($tab['active']) 1854 || (isset($GLOBALS['active_page']) 1855 && $GLOBALS['active_page'] == $tab['link']) 1856 || basename(PMA_getenv('PHP_SELF')) == $tab['link']) 1857 { 1858 $tab['class'] = 'active'; 1859 } 1860 } 1861 1862 if (!empty($tab['warning'])) { 1863 $tab['class'] .= ' warning'; 1864 $tab['attr'] .= ' title="' . htmlspecialchars($tab['warning']) . '"'; 1865 } 1866 1867 // build the link 1868 if (!empty($tab['link'])) { 1869 $tab['link'] = htmlentities($tab['link']); 1870 $tab['link'] = $tab['link'] . $tab['sep'] 1871 .(empty($GLOBALS['url_query']) ? 1872 PMA_generate_common_url() : $GLOBALS['url_query']); 1873 if (!empty($tab['args'])) { 1874 foreach ($tab['args'] as $param => $value) { 1875 $tab['link'] .= '&' . urlencode($param) . '=' 1876 . urlencode($value); 1877 } 1878 } 1879 } 1880 1881 // display icon, even if iconic is disabled but the link-text is missing 1882 if (($GLOBALS['cfg']['MainPageIconic'] || empty($tab['text'])) 1883 && isset($tab['icon'])) { 1884 $image = '<img class="icon" src="' . htmlentities($GLOBALS['pmaThemeImage']) 1885 .'%1$s" width="16" height="16" alt="%2$s" />%2$s'; 1886 $tab['text'] = sprintf($image, htmlentities($tab['icon']), $tab['text']); 1887 } 1888 // check to not display an empty link-text 1889 elseif (empty($tab['text'])) { 1890 $tab['text'] = '?'; 1891 trigger_error('empty linktext in function ' . __FUNCTION__ . '()', 1892 E_USER_NOTICE); 1893 } 1894 1895 if (!empty($tab['link'])) { 1896 $out = '<a class="tab' . htmlentities($tab['class']) . '"' 1897 .' href="' . $tab['link'] . '" ' . $tab['attr'] . '>' 1898 . $tab['text'] . '</a>'; 1899 } else { 1900 $out = '<span class="tab' . htmlentities($tab['class']) . '">' 1901 . $tab['text'] . '</span>'; 1902 } 1903 1904 return $out; 1905 } // end of the 'PMA_getTab()' function 1906 1907 /** 1908 * returns html-code for a tab navigation 1909 * 1910 * @uses PMA_getTab() 1911 * @uses htmlentities() 1912 * @param array $tabs one element per tab 1913 * @param string $tag_id id used for the html-tag 1914 * @return string html-code for tab-navigation 1915 */ 1916 function PMA_getTabs($tabs, $tag_id = 'topmenu') 1917 { 1918 $tab_navigation = 1919 '<div id="' . htmlentities($tag_id) . 'container">' . "\n" 1920 .'<ul id="' . htmlentities($tag_id) . '">' . "\n"; 1921 1922 foreach ($tabs as $tab) { 1923 $tab_navigation .= '<li>' . PMA_getTab($tab) . '</li>' . "\n"; 1924 } 1925 1926 $tab_navigation .= 1927 '</ul>' . "\n" 1928 .'<div class="clearfloat"></div>' 1929 .'</div>' . "\n"; 1930 1931 return $tab_navigation; 1932 } 1933 1934 1935 /** 1936 * Displays a link, or a button if the link's URL is too large, to 1937 * accommodate some browsers' limitations 1938 * 1939 * @param string the URL 1940 * @param string the link message 1941 * @param mixed $tag_params string: js confirmation 1942 * array: additional tag params (f.e. style="") 1943 * @param boolean $new_form we set this to false when we are already in 1944 * a form, to avoid generating nested forms 1945 * 1946 * @return string the results to be echoed or saved in an array 1947 */ 1948 function PMA_linkOrButton($url, $message, $tag_params = array(), 1949 $new_form = true, $strip_img = false, $target = '') 1950 { 1951 if (! is_array($tag_params)) { 1952 $tmp = $tag_params; 1953 $tag_params = array(); 1954 if (!empty($tmp)) { 1955 $tag_params['onclick'] = 'return confirmLink(this, \'' . $tmp . '\')'; 1956 } 1957 unset($tmp); 1958 } 1959 if (! empty($target)) { 1960 $tag_params['target'] = htmlentities($target); 1961 } 1962 1963 $tag_params_strings = array(); 1964 foreach ($tag_params as $par_name => $par_value) { 1965 // htmlspecialchars() only on non javascript 1966 $par_value = substr($par_name, 0, 2) == 'on' 1967 ? $par_value 1968 : htmlspecialchars($par_value); 1969 $tag_params_strings[] = $par_name . '="' . $par_value . '"'; 1970 } 1971 1972 // previously the limit was set to 2047, it seems 1000 is better 1973 if (strlen($url) <= 1000) { 1974 // no whitespace within an <a> else Safari will make it part of the link 1975 $ret = "\n" . '<a href="' . $url . '" ' 1976 . implode(' ', $tag_params_strings) . '>' 1977 . $message . '</a>' . "\n"; 1978 } else { 1979 // no spaces (linebreaks) at all 1980 // or after the hidden fields 1981 // IE will display them all 1982 1983 // add class=link to submit button 1984 if (empty($tag_params['class'])) { 1985 $tag_params['class'] = 'link'; 1986 } 1987 1988 // decode encoded url separators 1989 $separator = PMA_get_arg_separator(); 1990 // on most places separator is still hard coded ... 1991 if ($separator !== '&') { 1992 // ... so always replace & with $separator 1993 $url = str_replace(htmlentities('&'), $separator, $url); 1994 $url = str_replace('&', $separator, $url); 1995 } 1996 $url = str_replace(htmlentities($separator), $separator, $url); 1997 // end decode 1998 1999 $url_parts = parse_url($url); 2000 $query_parts = explode($separator, $url_parts['query']); 2001 if ($new_form) { 2002 $ret = '<form action="' . $url_parts['path'] . '" class="link"' 2003 . ' method="post"' . $target . ' style="display: inline;">'; 2004 $subname_open = ''; 2005 $subname_close = ''; 2006 $submit_name = ''; 2007 } else { 2008 $query_parts[] = 'redirect=' . $url_parts['path']; 2009 if (empty($GLOBALS['subform_counter'])) { 2010 $GLOBALS['subform_counter'] = 0; 2011 } 2012 $GLOBALS['subform_counter']++; 2013 $ret = ''; 2014 $subname_open = 'subform[' . $GLOBALS['subform_counter'] . ']['; 2015 $subname_close = ']'; 2016 $submit_name = ' name="usesubform[' . $GLOBALS['subform_counter'] . ']"'; 2017 } 2018 foreach ($query_parts as $query_pair) { 2019 list($eachvar, $eachval) = explode('=', $query_pair); 2020 $ret .= '<input type="hidden" name="' . $subname_open . $eachvar 2021 . $subname_close . '" value="' 2022 . htmlspecialchars(urldecode($eachval)) . '" />'; 2023 } // end while 2024 2025 if (stristr($message, '<img')) { 2026 if ($strip_img) { 2027 $message = trim(strip_tags($message)); 2028 $ret .= '<input type="submit"' . $submit_name . ' ' 2029 . implode(' ', $tag_params_strings) 2030 . ' value="' . htmlspecialchars($message) . '" />'; 2031 } else { 2032 $ret .= '<input type="image"' . $submit_name . ' ' 2033 . implode(' ', $tag_params_strings) 2034 . ' src="' . preg_replace( 2035 '/^.*\ssrc="([^"]*)".*$/si', '\1', $message) . '"' 2036 . ' value="' . htmlspecialchars( 2037 preg_replace('/^.*\salt="([^"]*)".*$/si', '\1', 2038 $message)) 2039 . '" />'; 2040 } 2041 } else { 2042 $message = trim(strip_tags($message)); 2043 $ret .= '<input type="submit"' . $submit_name . ' ' 2044 . implode(' ', $tag_params_strings) 2045 . ' value="' . htmlspecialchars($message) . '" />'; 2046 } 2047 if ($new_form) { 2048 $ret .= '</form>'; 2049 } 2050 } // end if... else... 2051 2052 return $ret; 2053 } // end of the 'PMA_linkOrButton()' function 2054 2055 2056 /** 2057 * Returns a given timespan value in a readable format. 2058 * 2059 * @param int the timespan 2060 * 2061 * @return string the formatted value 2062 */ 2063 function PMA_timespanFormat($seconds) 2064 { 2065 $return_string = ''; 2066 $days = floor($seconds / 86400); 2067 if ($days > 0) { 2068 $seconds -= $days * 86400; 2069 } 2070 $hours = floor($seconds / 3600); 2071 if ($days > 0 || $hours > 0) { 2072 $seconds -= $hours * 3600; 2073 } 2074 $minutes = floor($seconds / 60); 2075 if ($days > 0 || $hours > 0 || $minutes > 0) { 2076 $seconds -= $minutes * 60; 2077 } 2078 return sprintf($GLOBALS['timespanfmt'], (string)$days, (string)$hours, (string)$minutes, (string)$seconds); 2079 } 2080 2081 /** 2082 * Takes a string and outputs each character on a line for itself. Used 2083 * mainly for horizontalflipped display mode. 2084 * Takes care of special html-characters. 2085 * Fulfills todo-item 2086 * http://sf.net/tracker/?func=detail&aid=544361&group_id=23067&atid=377411 2087 * 2088 * @param string The string 2089 * @param string The Separator (defaults to "<br />\n") 2090 * 2091 * @access public 2092 * @author Garvin Hicking <me@supergarv.de> 2093 * @return string The flipped string 2094 */ 2095 function PMA_flipstring($string, $Separator = "<br />\n") 2096 { 2097 $format_string = ''; 2098 $charbuff = false; 2099 2100 for ($i = 0; $i < strlen($string); $i++) { 2101 $char = $string{$i}; 2102 $append = false; 2103 2104 if ($char == '&') { 2105 $format_string .= $charbuff; 2106 $charbuff = $char; 2107 $append = true; 2108 } elseif (!empty($charbuff)) { 2109 $charbuff .= $char; 2110 } elseif ($char == ';' && !empty($charbuff)) { 2111 $format_string .= $charbuff; 2112 $charbuff = false; 2113 $append = true; 2114 } else { 2115 $format_string .= $char; 2116 $append = true; 2117 } 2118 2119 if ($append && ($i != strlen($string))) { 2120 $format_string .= $Separator; 2121 } 2122 } 2123 2124 return $format_string; 2125 } 2126 2127 2128 /** 2129 * Function added to avoid path disclosures. 2130 * Called by each script that needs parameters, it displays 2131 * an error message and, by default, stops the execution. 2132 * 2133 * Not sure we could use a strMissingParameter message here, 2134 * would have to check if the error message file is always available 2135 * 2136 * @param array The names of the parameters needed by the calling 2137 * script. 2138 * @param boolean Stop the execution? 2139 * (Set this manually to false in the calling script 2140 * until you know all needed parameters to check). 2141 * @param boolean Whether to include this list in checking for special params. 2142 * @global string path to current script 2143 * @global boolean flag whether any special variable was required 2144 * 2145 * @access public 2146 * @author Marc Delisle (lem9@users.sourceforge.net) 2147 */ 2148 function PMA_checkParameters($params, $die = true, $request = true) 2149 { 2150 global $PHP_SELF, $checked_special; 2151 2152 if (!isset($checked_special)) { 2153 $checked_special = false; 2154 } 2155 2156 $reported_script_name = basename($PHP_SELF); 2157 $found_error = false; 2158 $error_message = ''; 2159 2160 foreach ($params as $param) { 2161 if ($request && $param != 'db' && $param != 'table') { 2162 $checked_special = true; 2163 } 2164 2165 if (!isset($GLOBALS[$param])) { 2166 $error_message .= $reported_script_name . ': Missing parameter: ' . $param . ' <a href="./Documentation.html#faqmissingparameters" target="documentation"> (FAQ 2.8)</a><br />'; 2167 $found_error = true; 2168 } 2169 } 2170 if ($found_error) { 2171 /** 2172 * display html meta tags 2173 */ 2174 require_once './libraries/header_meta_style.inc.php'; 2175 echo '</head><body><p>' . $error_message . '</p></body></html>'; 2176 if ($die) { 2177 exit(); 2178 } 2179 } 2180 } // end function 2181 2182 /** 2183 * Function to generate unique condition for specified row. 2184 * 2185 * @uses PMA_MYSQL_INT_VERSION 2186 * @uses $GLOBALS['analyzed_sql'][0] 2187 * @uses PMA_DBI_field_flags() 2188 * @uses PMA_backquote() 2189 * @uses PMA_sqlAddslashes() 2190 * @uses stristr() 2191 * @uses bin2hex() 2192 * @uses preg_replace() 2193 * @param resource $handle current query result 2194 * @param integer $fields_cnt number of fields 2195 * @param array $fields_meta meta information about fields 2196 * @param array $row current row 2197 * 2198 * @access public 2199 * @author Michal Cihar (michal@cihar.com) and others... 2200 * @return string calculated condition 2201 */ 2202 function PMA_getUniqueCondition($handle, $fields_cnt, $fields_meta, $row) 2203 { 2204 $primary_key = ''; 2205 $unique_key = ''; 2206 $nonprimary_condition = ''; 2207 2208 for ($i = 0; $i < $fields_cnt; ++$i) { 2209 $condition = ''; 2210 $field_flags = PMA_DBI_field_flags($handle, $i); 2211 $meta = $fields_meta[$i]; 2212 2213 // do not use a column alias in a condition 2214 if (! isset($meta->orgname) || ! strlen($meta->orgname)) { 2215 $meta->orgname = $meta->name; 2216 2217 if (isset($GLOBALS['analyzed_sql'][0]['select_expr']) 2218 && is_array($GLOBALS['analyzed_sql'][0]['select_expr'])) { 2219 foreach ($GLOBALS['analyzed_sql'][0]['select_expr'] 2220 as $select_expr) { 2221 // need (string) === (string) 2222 // '' !== 0 but '' == 0 2223 if ((string) $select_expr['alias'] === (string) $meta->name) { 2224 $meta->orgname = $select_expr['column']; 2225 break; 2226 } // end if 2227 } // end foreach 2228 } 2229 } 2230 2231 // Do not use a table alias in a condition. 2232 // Test case is: 2233 // select * from galerie x WHERE 2234 //(select count(*) from galerie y where y.datum=x.datum)>1 2235 // 2236 // But orgtable is present only with mysqli extension so the 2237 // fix is only for mysqli. 2238 if (isset($meta->orgtable) && $meta->table != $meta->orgtable) { 2239 $meta->table = $meta->orgtable; 2240 } 2241 2242 // to fix the bug where float fields (primary or not) 2243 // can't be matched because of the imprecision of 2244 // floating comparison, use CONCAT 2245 // (also, the syntax "CONCAT(field) IS NULL" 2246 // that we need on the next "if" will work) 2247 if ($meta->type == 'real') { 2248 $condition = ' CONCAT(' . PMA_backquote($meta->table) . '.' 2249 . PMA_backquote($meta->orgname) . ') '; 2250 } else { 2251 // string and blob fields have to be converted using 2252 // the system character set (always utf8) since 2253 // mysql4.1 can use different charset for fields. 2254 if (PMA_MYSQL_INT_VERSION >= 40100 2255 && ($meta->type == 'string' || $meta->type == 'blob')) { 2256 $condition = ' CONVERT(' . PMA_backquote($meta->table) . '.' 2257 . PMA_backquote($meta->orgname) . ' USING utf8) '; 2258 } else { 2259 $condition = ' ' . PMA_backquote($meta->table) . '.' 2260 . PMA_backquote($meta->orgname) . ' '; 2261 } 2262 } // end if... else... 2263 2264 if (!isset($row[$i]) || is_null($row[$i])) { 2265 $condition .= 'IS NULL AND'; 2266 } else { 2267 // timestamp is numeric on some MySQL 4.1 2268 if ($meta->numeric && $meta->type != 'timestamp') { 2269 $condition .= '= ' . $row[$i] . ' AND'; 2270 } elseif ($meta->type == 'blob' 2271 // hexify only if this is a true not empty BLOB 2272 && stristr($field_flags, 'BINARY') 2273 && !empty($row[$i])) { 2274 // do not waste memory building a too big condition 2275 if (strlen($row[$i]) < 1000) { 2276 if (PMA_MYSQL_INT_VERSION < 40002) { 2277 $condition .= 'LIKE 0x' . bin2hex($row[$i]) . ' AND'; 2278 } else { 2279 // use a CAST if possible, to avoid problems 2280 // if the field contains wildcard characters % or _ 2281 $condition .= '= CAST(0x' . bin2hex($row[$i]) 2282 . ' AS BINARY) AND'; 2283 } 2284 } else { 2285 // this blob won't be part of the final condition 2286 $condition = ''; 2287 } 2288 } else { 2289 $condition .= '= \'' 2290 . PMA_sqlAddslashes($row[$i], false, true) . '\' AND'; 2291 } 2292 } 2293 if ($meta->primary_key > 0) { 2294 $primary_key .= $condition; 2295 } elseif ($meta->unique_key > 0) { 2296 $unique_key .= $condition; 2297 } 2298 $nonprimary_condition .= $condition; 2299 } // end for 2300 2301 // Correction University of Virginia 19991216: 2302 // prefer primary or unique keys for condition, 2303 // but use conjunction of all values if no primary key 2304 if ($primary_key) { 2305 $preferred_condition = $primary_key; 2306 } elseif ($unique_key) { 2307 $preferred_condition = $unique_key; 2308 } else { 2309 $preferred_condition = $nonprimary_condition; 2310 } 2311 2312 return preg_replace('|\s?AND$|', '', $preferred_condition); 2313 } // end function 2314 2315 /** 2316 * Generate a button or image tag 2317 * 2318 * @param string name of button element 2319 * @param string class of button element 2320 * @param string name of image element 2321 * @param string text to display 2322 * @param string image to display 2323 * 2324 * @access public 2325 * @author Michal Cihar (michal@cihar.com) 2326 */ 2327 function PMA_buttonOrImage($button_name, $button_class, $image_name, $text, 2328 $image) 2329 { 2330 global $pmaThemeImage, $propicon; 2331 2332 /* Opera has trouble with <input type="image"> */ 2333 /* IE has trouble with <button> */ 2334 if (PMA_USR_BROWSER_AGENT != 'IE') { 2335 echo '<button class="' . $button_class . '" type="submit"' 2336 .' name="' . $button_name . '" value="' . $text . '"' 2337 .' title="' . $text . '">' . "\n" 2338 .'<img class="icon" src="' . $pmaThemeImage . $image . '"' 2339 .' title="' . $text . '" alt="' . $text . '" width="16"' 2340 .' height="16" />' 2341 .($propicon == 'both' ? ' ' . $text : '') . "\n" 2342 .'</button>' . "\n"; 2343 } else { 2344 echo '<input type="image" name="' . $image_name . '" value="' 2345 . $text . '" title="' . $text . '" src="' . $pmaThemeImage 2346 . $image . '" />' 2347 . ($propicon == 'both' ? ' ' . $text : '') . "\n"; 2348 } 2349 } // end function 2350 2351 /** 2352 * Generate a pagination selector for browsing resultsets 2353 * 2354 * @param string URL for the JavaScript 2355 * @param string Number of rows in the pagination set 2356 * @param string current page number 2357 * @param string number of total pages 2358 * @param string If the number of pages is lower than this 2359 * variable, no pages will be ommitted in 2360 * pagination 2361 * @param string How many rows at the beginning should always 2362 * be shown? 2363 * @param string How many rows at the end should always 2364 * be shown? 2365 * @param string Percentage of calculation page offsets to 2366 * hop to a next page 2367 * @param string Near the current page, how many pages should 2368 * be considered "nearby" and displayed as 2369 * well? 2370 * 2371 * @access public 2372 * @author Garvin Hicking (pma@supergarv.de) 2373 */ 2374 function PMA_pageselector($url, $rows, $pageNow = 1, $nbTotalPage = 1, 2375 $showAll = 200, $sliceStart = 5, $sliceEnd = 5, $percent = 20, 2376 $range = 10) 2377 { 2378 $gotopage = $GLOBALS['strPageNumber'] 2379 . ' <select name="goToPage" onchange="goToUrl(this, \'' 2380 . $url . '\');">' . "\n"; 2381 if ($nbTotalPage < $showAll) { 2382 $pages = range(1, $nbTotalPage); 2383 } else { 2384 $pages = array(); 2385 2386 // Always show first X pages 2387 for ($i = 1; $i <= $sliceStart; $i++) { 2388 $pages[] = $i; 2389 } 2390 2391 // Always show last X pages 2392 for ($i = $nbTotalPage - $sliceEnd; $i <= $nbTotalPage; $i++) { 2393 $pages[] = $i; 2394 } 2395 2396 // garvin: Based on the number of results we add the specified 2397 // $percent percentate to each page number, 2398 // so that we have a representing page number every now and then to 2399 // immideately jump to specific pages. 2400 // As soon as we get near our currently chosen page ($pageNow - 2401 // $range), every page number will be 2402 // shown. 2403 $i = $sliceStart; 2404 $x = $nbTotalPage - $sliceEnd; 2405 $met_boundary = false; 2406 while ($i <= $x) { 2407 if ($i >= ($pageNow - $range) && $i <= ($pageNow + $range)) { 2408 // If our pageselector comes near the current page, we use 1 2409 // counter increments 2410 $i++; 2411 $met_boundary = true; 2412 } else { 2413 // We add the percentate increment to our current page to 2414 // hop to the next one in range 2415 $i = $i + floor($nbTotalPage / $percent); 2416 2417 // Make sure that we do not cross our boundaries. 2418 if ($i > ($pageNow - $range) && !$met_boundary) { 2419 $i = $pageNow - $range; 2420 } 2421 } 2422 2423 if ($i > 0 && $i <= $x) { 2424 $pages[] = $i; 2425 } 2426 } 2427 2428 // Since because of ellipsing of the current page some numbers may be double, 2429 // we unify our array: 2430 sort($pages); 2431 $pages = array_unique($pages); 2432 } 2433 2434 foreach ($pages as $i) { 2435 if ($i == $pageNow) { 2436 $selected = 'selected="selected" style="font-weight: bold"'; 2437 } else { 2438 $selected = ''; 2439 } 2440 $gotopage .= ' <option ' . $selected . ' value="' . (($i - 1) * $rows) . '">' . $i . '</option>' . "\n"; 2441 } 2442 2443 $gotopage .= ' </select>'; 2444 2445 return $gotopage; 2446 } // end function 2447 2448 /** 2449 * @todo add documentation 2450 */ 2451 function PMA_userDir($dir) 2452 { 2453 global $cfg; 2454 2455 if (substr($dir, -1) != '/') { 2456 $dir .= '/'; 2457 } 2458 2459 return str_replace('%u', $cfg['Server']['user'], $dir); 2460 } 2461 2462 /** 2463 * returns html code for db link to default db page 2464 * 2465 * @uses $GLOBALS['cfg']['DefaultTabDatabase'] 2466 * @uses $GLOBALS['db'] 2467 * @uses $GLOBALS['strJumpToDB'] 2468 * @uses PMA_generate_common_url() 2469 * @param string $database 2470 * @return string html link to default db page 2471 */ 2472 function PMA_getDbLink($database = null) 2473 { 2474 if (!strlen($database)) { 2475 if (!strlen($GLOBALS['db'])) { 2476 return ''; 2477 } 2478 $database = $GLOBALS['db']; 2479 } else { 2480 $database = PMA_unescape_mysql_wildcards($database); 2481 } 2482 2483 return '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($database) . '"' 2484 .' title="' . sprintf($GLOBALS['strJumpToDB'], htmlspecialchars($database)) . '">' 2485 .htmlspecialchars($database) . '</a>'; 2486 } 2487 2488 /** 2489 * Displays a lightbulb hint explaining a known external bug 2490 * that affects a functionality 2491 * 2492 * @uses PMA_showHint() 2493 * @param string $functionality localized message explaining the func. 2494 * @param string $component 'mysql' (eventually, 'php') 2495 * @param string $minimum_version of this component 2496 * @param string $bugref bug reference for this component 2497 */ 2498 function PMA_externalBug($functionality, $component, $minimum_version, $bugref) { 2499 if ($component == 'mysql' && PMA_MYSQL_INT_VERSION < $minimum_version) { 2500 echo PMA_showHint(sprintf($GLOBALS['strKnownExternalBug'], $functionality, 'http://bugs.mysql.com/' . $bugref)); 2501 } 2502 } 2503 2504 /** 2505 * include here only libraries which contain only function definitions 2506 * no code im main()! 2507 */ 2508 /** 2509 * Include URL/hidden inputs generating. 2510 */ 2511 require_once './libraries/url_generating.lib.php'; 2512 2513 } 2514 2515 2516 /******************************************************************************/ 2517 /* start procedural code label_start_procedural */ 2518 2519 /** 2520 * protect against older PHP versions' bug about GLOBALS overwrite 2521 * (no need to localize this message :)) 2522 * but what if script.php?GLOBALS[admin]=1&GLOBALS[_REQUEST]=1 ??? 2523 */ 2524 if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS']) 2525 || isset($_SERVER['GLOBALS']) || isset($_COOKIE['GLOBALS']) 2526 || isset($_ENV['GLOBALS'])) { 2527 die('GLOBALS overwrite attempt'); 2528 } 2529 2530 /** 2531 * protect against possible exploits - there is no need to have so much vars 2532 */ 2533 if (count($_REQUEST) > 1000) { 2534 die('possible exploit'); 2535 } 2536 2537 /** 2538 * Check for numeric keys 2539 * (if register_globals is on, numeric key can be found in $GLOBALS) 2540 */ 2541 2542 foreach ($GLOBALS as $key => $dummy) { 2543 if (is_numeric($key)) { 2544 die('numeric key detected'); 2545 } 2546 } 2547 2548 /** 2549 * just to be sure there was no import (registering) before here 2550 * we empty the global space 2551 */ 2552 $variables_whitelist = array ( 2553 'GLOBALS', 2554 '_SERVER', 2555 '_GET', 2556 '_POST', 2557 '_REQUEST', 2558 '_FILES', 2559 '_ENV', 2560 '_COOKIE', 2561 '_SESSION', 2562 ); 2563 2564 foreach (get_defined_vars() as $key => $value) { 2565 if (! in_array($key, $variables_whitelist)) { 2566 unset($$key); 2567 } 2568 } 2569 unset($key, $value, $variables_whitelist); 2570 2571 2572 /** 2573 * Subforms - some functions need to be called by form, cause of the limited url 2574 * length, but if this functions inside another form you cannot just open a new 2575 * form - so phpMyAdmin uses 'arrays' inside this form 2576 * 2577 * <code> 2578 * <form ...> 2579 * ... main form elments ... 2580 * <intput type="hidden" name="subform[action1][id]" value="1" /> 2581 * ... other subform data ... 2582 * <intput type="submit" name="usesubform[action1]" value="do action1" /> 2583 * ... other subforms ... 2584 * <intput type="hidden" name="subform[actionX][id]" value="X" /> 2585 * ... other subform data ... 2586 * <intput type="submit" name="usesubform[actionX]" value="do actionX" /> 2587 * ... main form elments ... 2588 * <intput type="submit" name="main_action" value="submit form" /> 2589 * </form> 2590 * </code 2591 * 2592 * so we now check if a subform is submitted 2593 */ 2594 $__redirect = null; 2595 if (isset($_POST['usesubform'])) { 2596 // if a subform is present and should be used 2597 // the rest of the form is deprecated 2598 $subform_id = key($_POST['usesubform']); 2599 $subform = $_POST['subform'][$subform_id]; 2600 $_POST = $subform; 2601 $_REQUEST = $subform; 2602 /** 2603 * some subforms need another page than the main form, so we will just 2604 * include this page at the end of this script - we use $__redirect to 2605 * track this 2606 */ 2607 if (isset($_POST['redirect']) 2608 && $_POST['redirect'] != basename(PMA_getenv('PHP_SELF'))) { 2609 $__redirect = $_POST['redirect']; 2610 unset($_POST['redirect']); 2611 } 2612 unset($subform_id, $subform); 2613 } 2614 // end check if a subform is submitted 2615 2616 // remove quotes added by php 2617 if (get_magic_quotes_gpc()) { 2618 PMA_arrayWalkRecursive($_GET, 'stripslashes', true); 2619 PMA_arrayWalkRecursive($_POST, 'stripslashes', true); 2620 PMA_arrayWalkRecursive($_COOKIE, 'stripslashes', true); 2621 PMA_arrayWalkRecursive($_REQUEST, 'stripslashes', true); 2622 } 2623 2624 /** 2625 * In some cases, this one is not set 2626 * 2627 */ 2628 if (! isset($_REQUEST['js_frame']) || ! is_string($_REQUEST['js_frame'])) { 2629 $_REQUEST['js_frame'] = ''; 2630 } 2631 2632 /** 2633 * clean cookies on new install or upgrade 2634 * when changing something with increment the cookie version 2635 */ 2636 $pma_cookie_version = 4; 2637 if (isset($_COOKIE) 2638 && (! isset($_COOKIE['pmaCookieVer']) 2639 || $_COOKIE['pmaCookieVer'] < $pma_cookie_version)) { 2640 // delete all cookies 2641 foreach($_COOKIE as $cookie_name => $tmp) { 2642 PMA_removeCookie($cookie_name); 2643 } 2644 $_COOKIE = array(); 2645 PMA_setCookie('pmaCookieVer', $pma_cookie_version); 2646 } 2647 2648 /** 2649 * include deprecated grab_globals only if required 2650 */ 2651 if (empty($__redirect) && !defined('PMA_NO_VARIABLES_IMPORT')) { 2652 require './libraries/grab_globals.lib.php'; 2653 } 2654 2655 /** 2656 * include session handling after the globals, to prevent overwriting 2657 */ 2658 require_once './libraries/session.inc.php'; 2659 2660 /** 2661 * init some variables LABEL_variables_init 2662 */ 2663 2664 /** 2665 * holds errors 2666 * @global array $GLOBALS['PMA_errors'] 2667 */ 2668 $GLOBALS['PMA_errors'] = array(); 2669 2670 /** 2671 * holds params to be passed to next page 2672 * @global array $GLOBALS['url_params'] 2673 */ 2674 $GLOBALS['url_params'] = array(); 2675 2676 /** 2677 * the whitelist for $GLOBALS['goto'] 2678 * @global array $goto_whitelist 2679 */ 2680 $goto_whitelist = array( 2681 //'browse_foreigners.php', 2682 //'calendar.php', 2683 //'changelog.php', 2684 //'chk_rel.php', 2685 'db_create.php', 2686 'db_datadict.php', 2687 'db_sql.php', 2688 'db_export.php', 2689 'db_importdocsql.php', 2690 'db_qbe.php', 2691 'db_structure.php', 2692 'db_import.php', 2693 'db_operations.php', 2694 'db_printview.php', 2695 'db_search.php', 2696 //'Documentation.html', 2697 //'error.php', 2698 'export.php', 2699 'import.php', 2700 //'index.php', 2701 //'navigation.php', 2702 //'license.php', 2703 'main.php', 2704 'pdf_pages.php', 2705 'pdf_schema.php', 2706 //'phpinfo.php', 2707 'querywindow.php', 2708 //'readme.php', 2709 'server_binlog.php', 2710 'server_collations.php', 2711 'server_databases.php', 2712 'server_engines.php', 2713 'server_export.php', 2714 'server_import.php', 2715 'server_privileges.php', 2716 'server_processlist.php', 2717 'server_sql.php', 2718 'server_status.php', 2719 'server_variables.php', 2720 'sql.php', 2721 'tbl_addfield.php', 2722 'tbl_alter.php', 2723 'tbl_change.php', 2724 'tbl_create.php', 2725 'tbl_import.php', 2726 'tbl_indexes.php', 2727 'tbl_move_copy.php', 2728 'tbl_printview.php', 2729 'tbl_sql.php', 2730 'tbl_export.php', 2731 'tbl_operations.php', 2732 'tbl_structure.php', 2733 'tbl_relation.php', 2734 'tbl_replace.php', 2735 'tbl_row_action.php', 2736 'tbl_select.php', 2737 //'themes.php', 2738 'transformation_overview.php', 2739 'transformation_wrapper.php', 2740 'translators.html', 2741 'user_password.php', 2742 ); 2743 2744 /** 2745 * check $__redirect against whitelist 2746 */ 2747 if (! PMA_checkPageValidity($__redirect, $goto_whitelist)) { 2748 $__redirect = null; 2749 } 2750 2751 /** 2752 * holds page that should be displayed 2753 * @global string $GLOBALS['goto'] 2754 */ 2755 $GLOBALS['goto'] = ''; 2756 // Security fix: disallow accessing serious server files via "?goto=" 2757 if (PMA_checkPageValidity($_REQUEST['goto'], $goto_whitelist)) { 2758 $GLOBALS['goto'] = $_REQUEST['goto']; 2759 $GLOBALS['url_params']['goto'] = $_REQUEST['goto']; 2760 } else { 2761 unset($_REQUEST['goto'], $_GET['goto'], $_POST['goto'], $_COOKIE['goto']); 2762 } 2763 2764 /** 2765 * returning page 2766 * @global string $GLOBALS['back'] 2767 */ 2768 if (PMA_checkPageValidity($_REQUEST['back'], $goto_whitelist)) { 2769 $GLOBALS['back'] = $_REQUEST['back']; 2770 } else { 2771 unset($_REQUEST['back'], $_GET['back'], $_POST['back'], $_COOKIE['back']); 2772 } 2773 2774 /** 2775 * Check whether user supplied token is valid, if not remove any possibly 2776 * dangerous stuff from request. 2777 * 2778 * remember that some objects in the session with session_start and __wakeup() 2779 * could access this variables before we reach this point 2780 * f.e. PMA_Config: fontsize 2781 * 2782 * @todo variables should be handled by their respective owners (objects) 2783 * f.e. lang, server, convcharset, collation_connection in PMA_Config 2784 */ 2785 if ((isset($_REQUEST['token']) && !is_string($_REQUEST['token'])) || empty($_REQUEST['token']) || $_SESSION[' PMA_token '] != $_REQUEST['token']) { 2786 /** 2787 * List of parameters which are allowed from unsafe source 2788 */ 2789 $allow_list = array( 2790 'db', 'table', 'lang', 'server', 'convcharset', 'collation_connection', 'target', 2791 /* Session ID */ 2792 'phpMyAdmin', 2793 /* Cookie preferences */ 2794 'pma_lang', 'pma_charset', 'pma_collation_connection', 2795 /* Possible login form */ 2796 'pma_servername', 'pma_username', 'pma_password', 2797 ); 2798 /** 2799 * Require cleanup functions 2800 */ 2801 require_once ('./libraries/cleanup.lib.php'); 2802 /** 2803 * Do actual cleanup 2804 */ 2805 PMA_remove_request_vars($allow_list); 2806 2807 } 2808 2809 2810 /** 2811 * @global string $convcharset 2812 * @see select_lang.lib.php 2813 */ 2814 if (isset($_REQUEST['convcharset'])) { 2815 $convcharset = strip_tags($_REQUEST['convcharset']); 2816 } 2817 2818 /** 2819 * current selected database 2820 * @global string $GLOBALS['db'] 2821 */ 2822 $GLOBALS['db'] = ''; 2823 if (isset($_REQUEST['db']) && is_string($_REQUEST['db'])) { 2824 // can we strip tags from this? 2825 // only \ and / is not allowed in db names for MySQL 2826 $GLOBALS['db'] = $_REQUEST['db']; 2827 $GLOBALS['url_params']['db'] = $GLOBALS['db']; 2828 } 2829 2830 /** 2831 * current selected table 2832 * @global string $GLOBALS['table'] 2833 */ 2834 $GLOBALS['table'] = ''; 2835 if (isset($_REQUEST['table']) && is_string($_REQUEST['table'])) { 2836 // can we strip tags from this? 2837 // only \ and / is not allowed in table names for MySQL 2838 $GLOBALS['table'] = $_REQUEST['table']; 2839 $GLOBALS['url_params']['table'] = $GLOBALS['table']; 2840 } 2841 2842 /** 2843 * sql query to be executed 2844 * @global string $GLOBALS['sql_query'] 2845 */ 2846 if (isset($_REQUEST['sql_query']) && is_string($_REQUEST['sql_query'])) { 2847 $GLOBALS['sql_query'] = $_REQUEST['sql_query']; 2848 } 2849 2850 //$_REQUEST['set_theme'] // checked later in this file LABEL_theme_setup 2851 //$_REQUEST['server']; // checked later in this file 2852 //$_REQUEST['lang']; // checked by LABEL_loading_language_file 2853 2854 2855 2856 /******************************************************************************/ 2857 /* parsing config file LABEL_parsing_config_file */ 2858 2859 if (empty($_SESSION['PMA_Config'])) { 2860 /** 2861 * We really need this one! 2862 */ 2863 if (!function_exists('preg_replace')) { 2864 header('Location: error.php' 2865 . '?lang=' . urlencode($available_languages[$lang][2]) 2866 . '&dir=' . urlencode($text_dir) 2867 . '&type=' . urlencode($strError) 2868 . '&error=' . urlencode( 2869 strtr(sprintf($strCantLoad, 'pcre'), 2870 array('<br />' => '[br]'))) 2871 . '&' . SID 2872 ); 2873 exit(); 2874 } 2875 2876 /** 2877 * @global PMA_Config $_SESSION['PMA_Config'] 2878 */ 2879 $_SESSION['PMA_Config'] = new PMA_Config('./config.inc.php'); 2880 2881 } elseif (version_compare(phpversion(), '5', 'lt')) { 2882 /** 2883 * @todo move all __wakeup() functionality into session.inc.php 2884 */ 2885 $_SESSION['PMA_Config']->__wakeup(); 2886 } 2887 2888 if (!defined('PMA_MINIMUM_COMMON')) { 2889 $_SESSION['PMA_Config']->checkPmaAbsoluteUri(); 2890 } 2891 2892 /** 2893 * BC - enable backward compatibility 2894 * exports all config settings into $GLOBALS ($GLOBALS['cfg']) 2895 */ 2896 $_SESSION['PMA_Config']->enableBc(); 2897 2898 2899 /** 2900 * check https connection 2901 */ 2902 if ($_SESSION['PMA_Config']->get('ForceSSL') 2903 && !$_SESSION['PMA_Config']->get('is_https')) { 2904 PMA_sendHeaderLocation( 2905 preg_replace('/^http/', 'https', 2906 $_SESSION['PMA_Config']->get('PmaAbsoluteUri')) 2907 . PMA_generate_common_url($_GET)); 2908 exit; 2909 } 2910 2911 2912 /******************************************************************************/ 2913 /* loading language file LABEL_loading_language_file */ 2914 2915 /** 2916 * Added messages while developing: 2917 */ 2918 if (file_exists('./lang/added_messages.php')) { 2919 include './lang/added_messages.php'; 2920 } 2921 2922 /** 2923 * Includes the language file if it hasn't been included yet 2924 */ 2925 require './libraries/language.lib.php'; 2926 2927 2928 /** 2929 * check for errors occured while loading config 2930 * this check is done here after loading lang files to present errors in locale 2931 */ 2932 if ($_SESSION['PMA_Config']->error_config_file) { 2933 $GLOBALS['PMA_errors'][] = $strConfigFileError 2934 . '<br /><br />' 2935 . ($_SESSION['PMA_Config']->getSource() == './config.inc.php' ? 2936 '<a href="show_config_errors.php"' 2937 .' target="_blank">' . $_SESSION['PMA_Config']->getSource() . '</a>' 2938 : 2939 '<a href="' . $_SESSION['PMA_Config']->getSource() . '"' 2940 .' target="_blank">' . $_SESSION['PMA_Config']->getSource() . '</a>'); 2941 } 2942 if ($_SESSION['PMA_Config']->error_config_default_file) { 2943 $GLOBALS['PMA_errors'][] = sprintf($strConfigDefaultFileError, 2944 $_SESSION['PMA_Config']->default_source); 2945 } 2946 if ($_SESSION['PMA_Config']->error_pma_uri) { 2947 $GLOBALS['PMA_errors'][] = sprintf($strPmaUriError); 2948 } 2949 2950 /** 2951 * current server 2952 * @global integer $GLOBALS['server'] 2953 */ 2954 $GLOBALS['server'] = 0; 2955 2956 /** 2957 * Servers array fixups. 2958 * $default_server comes from PMA_Config::enableBc() 2959 * @todo merge into PMA_Config 2960 */ 2961 // Do we have some server? 2962 if (!isset($cfg['Servers']) || count($cfg['Servers']) == 0) { 2963 // No server => create one with defaults 2964 $cfg['Servers'] = array(1 => $default_server); 2965 } else { 2966 // We have server(s) => apply default config 2967 $new_servers = array(); 2968 2969 foreach ($cfg['Servers'] as $server_index => $each_server) { 2970 2971 // Detect wrong configuration 2972 if (!is_int($server_index) || $server_index < 1) { 2973 $GLOBALS['PMA_errors'][] = sprintf($strInvalidServerIndex, $server_index); 2974 } 2975 2976 $each_server = array_merge($default_server, $each_server); 2977 2978 // Don't use servers with no hostname 2979 if ($each_server['connect_type'] == 'tcp' && empty($each_server['host'])) { 2980 $GLOBALS['PMA_errors'][] = sprintf($strInvalidServerHostname, $server_index); 2981 } 2982 2983 // Final solution to bug #582890 2984 // If we are using a socket connection 2985 // and there is nothing in the verbose server name 2986 // or the host field, then generate a name for the server 2987 // in the form of "Server 2", localized of course! 2988 if ($each_server['connect_type'] == 'socket' && empty($each_server['host']) && empty($each_server['verbose'])) { 2989 $each_server['verbose'] = $GLOBALS['strServer'] . $server_index; 2990 } 2991 2992 $new_servers[$server_index] = $each_server; 2993 } 2994 $cfg['Servers'] = $new_servers; 2995 unset($new_servers, $server_index, $each_server); 2996 } 2997 2998 // Cleanup 2999 unset($default_server); 3000 3001 3002 /******************************************************************************/ 3003 /* setup themes LABEL_theme_setup */ 3004 3005 /** 3006 * @global PMA_Theme_Manager $_SESSION['PMA_Theme_Manager'] 3007 */ 3008 if (! isset($_SESSION['PMA_Theme_Manager'])) { 3009 $_SESSION['PMA_Theme_Manager'] = new PMA_Theme_Manager; 3010 } else { 3011 /** 3012 * @todo move all __wakeup() functionality into session.inc.php 3013 */ 3014 $_SESSION['PMA_Theme_Manager']->checkConfig(); 3015 } 3016 3017 // for the theme per server feature 3018 if (isset($_REQUEST['server']) && !isset($_REQUEST['set_theme'])) { 3019 $GLOBALS['server'] = $_REQUEST['server']; 3020 $tmp = $_SESSION['PMA_Theme_Manager']->getThemeCookie(); 3021 if (empty($tmp)) { 3022 $tmp = $_SESSION['PMA_Theme_Manager']->theme_default; 3023 } 3024 $_SESSION['PMA_Theme_Manager']->setActiveTheme($tmp); 3025 unset($tmp); 3026 } 3027 /** 3028 * @todo move into PMA_Theme_Manager::__wakeup() 3029 */ 3030 if (isset($_REQUEST['set_theme'])) { 3031 // if user selected a theme 3032 $_SESSION['PMA_Theme_Manager']->setActiveTheme($_REQUEST['set_theme']); 3033 } 3034 3035 /** 3036 * the theme object 3037 * @global PMA_Theme $_SESSION['PMA_Theme'] 3038 */ 3039 $_SESSION['PMA_Theme'] = $_SESSION['PMA_Theme_Manager']->theme; 3040 3041 // BC 3042 /** 3043 * the active theme 3044 * @global string $GLOBALS['theme'] 3045 */ 3046 $GLOBALS['theme'] = $_SESSION['PMA_Theme']->getName(); 3047 /** 3048 * the theme path 3049 * @global string $GLOBALS['pmaThemePath'] 3050 */ 3051 $GLOBALS['pmaThemePath'] = $_SESSION['PMA_Theme']->getPath(); 3052 /** 3053 * the theme image path 3054 * @global string $GLOBALS['pmaThemeImage'] 3055 */ 3056 $GLOBALS['pmaThemeImage'] = $_SESSION['PMA_Theme']->getImgPath(); 3057 3058 /** 3059 * load layout file if exists 3060 */ 3061 if (@file_exists($_SESSION['PMA_Theme']->getLayoutFile())) { 3062 include $_SESSION['PMA_Theme']->getLayoutFile(); 3063 /** 3064 * @todo remove if all themes are update use Navi instead of Left as frame name 3065 */ 3066 if (! isset($GLOBALS['cfg']['NaviWidth']) 3067 && isset($GLOBALS['cfg']['LeftWidth'])) { 3068 $GLOBALS['cfg']['NaviWidth'] = $GLOBALS['cfg']['LeftWidth']; 3069 } 3070 } 3071 3072 if (! defined('PMA_MINIMUM_COMMON')) { 3073 /** 3074 * Charset conversion. 3075 */ 3076 require_once './libraries/charset_conversion.lib.php'; 3077 3078 /** 3079 * String handling 3080 */ 3081 require_once './libraries/string.lib.php'; 3082 3083 /** 3084 * Lookup server by name 3085 * by Arnold - Helder Hosting 3086 * (see FAQ 4.8) 3087 */ 3088 if (! empty($_REQUEST['server']) && is_string($_REQUEST['server']) 3089 && ! is_numeric($_REQUEST['server'])) { 3090 foreach ($cfg['Servers'] as $i => $server) { 3091 if ($server['host'] == $_REQUEST['server']) { 3092 $_REQUEST['server'] = $i; 3093 break; 3094 } 3095 } 3096 if (is_string($_REQUEST['server'])) { 3097 unset($_REQUEST['server']); 3098 } 3099 unset($i); 3100 } 3101 3102 /** 3103 * If no server is selected, make sure that $cfg['Server'] is empty (so 3104 * that nothing will work), and skip server authentication. 3105 * We do NOT exit here, but continue on without logging into any server. 3106 * This way, the welcome page will still come up (with no server info) and 3107 * present a choice of servers in the case that there are multiple servers 3108 * and '$cfg['ServerDefault'] = 0' is set. 3109 */ 3110 3111 if (isset($_REQUEST['server']) && (is_string($_REQUEST['server']) || is_numeric($_REQUEST['server'])) && ! empty($_REQUEST['server']) && ! empty($cfg['Servers'][$_REQUEST['server']])) { 3112 $GLOBALS['server'] = $_REQUEST['server']; 3113 $cfg['Server'] = $cfg['Servers'][$GLOBALS['server']]; 3114 } else { 3115 if (!empty($cfg['Servers'][$cfg['ServerDefault']])) { 3116 $GLOBALS['server'] = $cfg['ServerDefault']; 3117 $cfg['Server'] = $cfg['Servers'][$GLOBALS['server']]; 3118 } else { 3119 $GLOBALS['server'] = 0; 3120 $cfg['Server'] = array(); 3121 } 3122 } 3123 $GLOBALS['url_params']['server'] = $GLOBALS['server']; 3124 3125 3126 if (! empty($cfg['Server'])) { 3127 3128 /** 3129 * Loads the proper database interface for this server 3130 */ 3131 require_once './libraries/database_interface.lib.php'; 3132 3133 // Gets the authentication library that fits the $cfg['Server'] settings 3134 // and run authentication 3135 3136 // (for a quick check of path disclosure in auth/cookies:) 3137 $coming_from_common = true; 3138 3139 // to allow HTTP or http 3140 $cfg['Server']['auth_type'] = strtolower($cfg['Server']['auth_type']); 3141 if (!file_exists('./libraries/auth/' . $cfg['Server']['auth_type'] . '.auth.lib.php')) { 3142 header('Location: error.php' 3143 . '?lang=' . urlencode($available_languages[$lang][2]) 3144 . '&dir=' . urlencode($text_dir) 3145 . '&type=' . urlencode($strError) 3146 . '&error=' . urlencode( 3147 $strInvalidAuthMethod . ' ' 3148 . $cfg['Server']['auth_type']) 3149 . '&' . SID 3150 ); 3151 exit(); 3152 } 3153 /** 3154 * the required auth type plugin 3155 */ 3156 require_once './libraries/auth/' . $cfg['Server']['auth_type'] . '.auth.lib.php'; 3157 3158 if (!PMA_auth_check()) { 3159 PMA_auth(); 3160 } else { 3161 PMA_auth_set_user(); 3162 } 3163 3164 // Check IP-based Allow/Deny rules as soon as possible to reject the 3165 // user 3166 // Based on mod_access in Apache: 3167 // http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/aaa/mod_access.c?rev=1.37&content-type=text/vnd.viewcvs-markup 3168 // Look at: "static int check_dir_access(request_rec *r)" 3169 // Robbat2 - May 10, 2002 3170 if (isset($cfg['Server']['AllowDeny']) 3171 && isset($cfg['Server']['AllowDeny']['order'])) { 3172 3173 /** 3174 * ip based access library 3175 */ 3176 require_once './libraries/ip_allow_deny.lib.php'; 3177 3178 $allowDeny_forbidden = false; // default 3179 if ($cfg['Server']['AllowDeny']['order'] == 'allow,deny') { 3180 $allowDeny_forbidden = true; 3181 if (PMA_allowDeny('allow')) { 3182 $allowDeny_forbidden = false; 3183 } 3184 if (PMA_allowDeny('deny')) { 3185 $allowDeny_forbidden = true; 3186 } 3187 } elseif ($cfg['Server']['AllowDeny']['order'] == 'deny,allow') { 3188 if (PMA_allowDeny('deny')) { 3189 $allowDeny_forbidden = true; 3190 } 3191 if (PMA_allowDeny('allow')) { 3192 $allowDeny_forbidden = false; 3193 } 3194 } elseif ($cfg['Server']['AllowDeny']['order'] == 'explicit') { 3195 if (PMA_allowDeny('allow') 3196 && !PMA_allowDeny('deny')) { 3197 $allowDeny_forbidden = false; 3198 } else { 3199 $allowDeny_forbidden = true; 3200 } 3201 } // end if ... elseif ... elseif 3202 3203 // Ejects the user if banished 3204 if ($allowDeny_forbidden) { 3205 PMA_auth_fails(); 3206 } 3207 unset($allowDeny_forbidden); //Clean up after you! 3208 } // end if 3209 3210 // is root allowed? 3211 if (!$cfg['Server']['AllowRoot'] && $cfg['Server']['user'] == 'root') { 3212 $allowDeny_forbidden = true; 3213 PMA_auth_fails(); 3214 unset($allowDeny_forbidden); //Clean up after you! 3215 } 3216 3217 $bkp_track_err = @ini_set('track_errors', 1); 3218 3219 // Try to connect MySQL with the control user profile (will be used to 3220 // get the privileges list for the current user but the true user link 3221 // must be open after this one so it would be default one for all the 3222 // scripts) 3223 if ($cfg['Server']['controluser'] != '') { 3224 $controllink = PMA_DBI_connect($cfg['Server']['controluser'], 3225 $cfg['Server']['controlpass'], true); 3226 } else { 3227 $controllink = PMA_DBI_connect($cfg['Server']['user'], 3228 $cfg['Server']['password'], true); 3229 } // end if ... else 3230 3231 // Pass #1 of DB-Config to read in master level DB-Config will go here 3232 // Robbat2 - May 11, 2002 3233 3234 // Connects to the server (validates user's login) 3235 $userlink = PMA_DBI_connect($cfg['Server']['user'], 3236 $cfg['Server']['password'], false); 3237 3238 // Pass #2 of DB-Config to read in user level DB-Config will go here 3239 // Robbat2 - May 11, 2002 3240 3241 @ini_set('track_errors', $bkp_track_err); 3242 unset($bkp_track_err); 3243 3244 /** 3245 * If we auto switched to utf-8 we need to reread messages here 3246 */ 3247 if (defined('PMA_LANG_RELOAD')) { 3248 require './libraries/language.lib.php'; 3249 } 3250 3251 /** 3252 * SQL Parser code 3253 */ 3254 require_once './libraries/sqlparser.lib.php'; 3255 3256 /** 3257 * SQL Validator interface code 3258 */ 3259 require_once './libraries/sqlvalidator.lib.php'; 3260 3261 /** 3262 * the PMA_List_Database class 3263 */ 3264 require_once './libraries/PMA_List_Database.class.php'; 3265 $PMA_List_Database = new PMA_List_Database($userlink, $controllink); 3266 3267 } // end server connecting 3268 3269 /** 3270 * Kanji encoding convert feature appended by Y.Kawada (2002/2/20) 3271 */ 3272 if (@function_exists('mb_convert_encoding') 3273 && strpos(' ' . $lang, 'ja-') 3274 && file_exists('./libraries/kanji-encoding.lib.php')) { 3275 require_once './libraries/kanji-encoding.lib.php'; 3276 define('PMA_MULTIBYTE_ENCODING', 1); 3277 } // end if 3278 3279 /** 3280 * save some settings in cookies 3281 * @todo should be done in PMA_Config 3282 */ 3283 PMA_setCookie('pma_lang', $GLOBALS['lang']); 3284 PMA_setCookie('pma_charset', $GLOBALS['convcharset']); 3285 PMA_setCookie('pma_collation_connection', $GLOBALS['collation_connection']); 3286 3287 $_SESSION['PMA_Theme_Manager']->setThemeCookie(); 3288 } // end if !defined('PMA_MINIMUM_COMMON') 3289 3290 if (!empty($__redirect) && in_array($__redirect, $goto_whitelist)) { 3291 // to handle bug #1388167 3292 if (isset($_GET['is_js_confirmed'])) { 3293 $is_js_confirmed = 1; 3294 } 3295 /** 3296 * include subform target page 3297 */ 3298 require $__redirect; 3299 exit(); 3300 } 3301 ?>
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 |
|