<?php/* $Id: common.lib.php,v 2.266.2.27.2.2 2006/08/21 11:45:16 lem9 Exp $ */// vim: expandtab sw=4 ts=4 sts=4:/*** Misc stuff and functions used by almost all the scripts.* Among other things, it contains the advanced authentication work.*//*** Order of sections for common.lib.php:** the include of libraries/defines_mysql.lib.php must be after the connection* to db to get the MySql version** the authentication libraries must be before the connection to db** ... so the required order is:** LABEL_definition_of_functions* - definition of functions* LABEL_variables_init* - init some variables always needed* LABEL_parsing_config_file* - parsing of the config file* LABEL_loading_language_file* - loading language file* LABEL_theme_setup* - setting up themes** - load of mysql extension (if necessary) label_loading_mysql* - loading of an authentication library label_* - db connection* - authentication work* - load of the libraries/defines_mysql.lib.php library to get the MySQL* release number*//*** For now, avoid warnings of E_STRICT mode* (this must be done before function definitions)*/if (defined('E_STRICT')) {$old_error_reporting = error_reporting(0);if ($old_error_reporting & E_STRICT) {error_reporting($old_error_reporting ^ E_STRICT);} else {error_reporting($old_error_reporting);}unset($old_error_reporting);}/*** Avoid object cloning errors*/@ini_set('zend.ze1_compatibility_mode',false);/******************************************************************************//* definition of functions LABEL_definition_of_functions *//*** Removes insecure parts in a path; used before include() or* require() when a part of the path comes from an insecure source* like a cookie or form.** @param string The path to check** @return string The secured path** @access public* @author Marc Delisle (lem9@users.sourceforge.net)*/function PMA_securePath($path){// change .. to .$path = preg_replace('@\.\.*@', '.', $path);return $path;} // end function/*** returns array with dbs grouped with extended infos** @uses $GLOBALS['dblist'] from PMA_availableDatabases()* @uses $GLOBALS['num_dbs'] from PMA_availableDatabases()* @uses $GLOBALS['cfgRelation']['commwork']* @uses $GLOBALS['cfg']['ShowTooltip']* @uses $GLOBALS['cfg']['LeftFrameDBTree']* @uses $GLOBALS['cfg']['LeftFrameDBSeparator']* @uses $GLOBALS['cfg']['ShowTooltipAliasDB']* @uses PMA_availableDatabases()* @uses PMA_getTableCount()* @uses PMA_getComments()* @uses PMA_availableDatabases()* @uses is_array()* @uses implode()* @uses strstr()* @uses explode()* @return array db list*/function PMA_getDbList(){if (empty($GLOBALS['dblist'])) {PMA_availableDatabases();}$dblist = $GLOBALS['dblist'];$dbgroups = array();$parts = array();foreach ($dblist as $key => $db) {// garvin: Get comments from PMA comments table$db_tooltip = '';if ($GLOBALS['cfg']['ShowTooltip']&& $GLOBALS['cfgRelation']['commwork']) {$_db_tooltip = PMA_getComments($db);if (is_array($_db_tooltip)) {$db_tooltip = implode(' ', $_db_tooltip);}}if ($GLOBALS['cfg']['LeftFrameDBTree']&& $GLOBALS['cfg']['LeftFrameDBSeparator']&& strstr($db, $GLOBALS['cfg']['LeftFrameDBSeparator'])){$pos = strrpos($db, $GLOBALS['cfg']['LeftFrameDBSeparator']);$group = substr($db, 0, $pos);$disp_name_cut = substr($db, $pos);} else {$group = $db;$disp_name_cut = $db;}$disp_name = $db;if ($db_tooltip && $GLOBALS['cfg']['ShowTooltipAliasDB']) {$disp_name = $db_tooltip;$disp_name_cut = $db_tooltip;$db_tooltip = $db;}$dbgroups[$group][$db] = array('name' => $db,'disp_name_cut' => $disp_name_cut,'disp_name' => $disp_name,'comment' => $db_tooltip,'num_tables' => PMA_getTableCount($db),);} // end foreach ($dblist as $db)return $dbgroups;}/*** returns html code for select form element with dbs** @return string html code select*/function PMA_getHtmlSelectDb($selected = ''){$dblist = PMA_getDbList();// TODO: IE can not handle different text directions in select boxes// so, as mostly names will be in english, we set the whole selectbox to LTR// and EN$return = '<select name="db" id="lightm_db" xml:lang="en" dir="ltr"'.' onchange="if (this.value != \'\') window.parent.openDb(this.value);">' . "\n".'<option value="" dir="' . $GLOBALS['text_dir'] . '">(' . $GLOBALS['strDatabases'] . ') ...</option>'."\n";foreach ($dblist as $group => $dbs) {if (count($dbs) > 1) {$return .= '<optgroup label="' . htmlspecialchars($group). '">' . "\n";// wether display db_name cuted by the group part$cut = true;} else {// .. or full$cut = false;}foreach ($dbs as $db) {$return .= '<option value="' . $db['name'] . '"'.' title="' . $db['comment'] . '"';if ($db['name'] == $selected) {$return .= ' selected="selected"';}$return .= '>' . ($cut ? $db['disp_name_cut'] : $db['disp_name']).' (' . $db['num_tables'] . ')</option>' . "\n";}if (count($dbs) > 1) {$return .= '</optgroup>' . "\n";}}$return .= '</select>';return $return;}/*** returns count of tables in given db** @param string $db database to count tables for* @return integer count of tables in $db*/function PMA_getTableCount($db){$tables = PMA_DBI_try_query('SHOW TABLES FROM ' . PMA_backquote($db) . ';',null, PMA_DBI_QUERY_STORE);if ($tables) {$num_tables = PMA_DBI_num_rows($tables);PMA_DBI_free_result($tables);} else {$num_tables = 0;}return $num_tables;}/*** Get the complete list of Databases a user can access** @param boolean whether to include check on failed 'only_db' operations* @param resource database handle (superuser)* @param integer amount of databases inside the 'only_db' container* @param resource possible resource from a failed previous query* @param resource database handle (user)* @param array configuration* @param array previous list of databases** @return array all databases a user has access to** @access private*/function PMA_safe_db_list($only_db_check, $controllink, $dblist_cnt, $userlink,$cfg, $dblist){if ($only_db_check == false) {// try to get the available dbs list// use userlink by default$dblist = PMA_DBI_get_dblist();$dblist_cnt = count($dblist);// PMA_DBI_get_dblist() relies on the ability to run "SHOW DATABASES".// On servers started with --skip-show-database, this is not possible// so we have here a fallback method, which relies on the controluser// being able to access the "mysql" db, as explained in the doc.if (!$dblist_cnt) {$auth_query = 'SELECT User, Select_priv '. 'FROM mysql.user '. 'WHERE User = \'' . PMA_sqlAddslashes($cfg['Server']['user']) . '\'';$rs = PMA_DBI_try_query($auth_query, $controllink);} // end}// Access to "mysql" db allowed and dblist still empty -> gets the// usable db listif (!$dblist_cnt && ($rs && @PMA_DBI_num_rows($rs))) {$row = PMA_DBI_fetch_assoc($rs);PMA_DBI_free_result($rs);// Correction uva 19991215// Previous code assumed database "mysql" admin table "db" column// "db" contains literal name of user database, and works if so.// Mysql usage generally (and uva usage specifically) allows this// column to contain regular expressions (we have all databases// owned by a given student/faculty/staff beginning with user i.d.// and governed by default by a single set of privileges with// regular expression as key). This breaks previous code.// This maintenance is to fix code to work correctly for regular// expressions.if ($row['Select_priv'] != 'Y') {// 1. get allowed dbs from the "mysql.db" table// lem9: User can be blank (anonymous user)$local_query = 'SELECT DISTINCT Db FROM mysql.db WHERE Select_priv = \'Y\' AND (User = \'' . PMA_sqlAddslashes($cfg['Server']['user']) . '\' OR User = \'\')';$rs = PMA_DBI_try_query($local_query, $controllink);if ($rs && @PMA_DBI_num_rows($rs)) {// Will use as associative array of the following 2 code// lines:// the 1st is the only line intact from before// correction,// the 2nd replaces $dblist[] = $row['Db'];$uva_mydbs = array();// Code following those 2 lines in correction continues// populating $dblist[], as previous code did. But it is// now populated with actual database names instead of// with regular expressions.while ($row = PMA_DBI_fetch_assoc($rs)) {// loic1: all databases cases - part 1if ( !isset($row['Db']) || ! strlen($row['Db']) || $row['Db'] == '%') {$uva_mydbs['%'] = 1;break;}// loic1: avoid multiple entries for dbsif (!isset($uva_mydbs[$row['Db']])) {$uva_mydbs[$row['Db']] = 1;}} // end whilePMA_DBI_free_result($rs);$uva_alldbs = PMA_DBI_query('SHOW DATABASES;', $GLOBALS['controllink']);// loic1: all databases cases - part 2if (isset($uva_mydbs['%'])) {while ($uva_row = PMA_DBI_fetch_row($uva_alldbs)) {$dblist[] = $uva_row[0];} // end while} else {while ($uva_row = PMA_DBI_fetch_row($uva_alldbs)) {$uva_db = $uva_row[0];if (isset($uva_mydbs[$uva_db]) && $uva_mydbs[$uva_db] == 1) {$dblist[] = $uva_db;$uva_mydbs[$uva_db] = 0;} elseif (!isset($dblist[$uva_db])) {foreach ($uva_mydbs AS $uva_matchpattern => $uva_value) {// loic1: fixed bad regexp// TODO: db names may contain characters// that are regexp instructions$re = '(^|(\\\\\\\\)+|[^\])';$uva_regex = ereg_replace($re . '%', '\\1.*', ereg_replace($re . '_', '\\1.{1}', $uva_matchpattern));// Fixed db name matching// 2000-08-28 -- Benjamin Gandonif (ereg('^' . $uva_regex . '$', $uva_db)) {$dblist[] = $uva_db;break;}} // end while} // end if ... elseif ...} // end while} // end elsePMA_DBI_free_result($uva_alldbs);unset($uva_mydbs);} // end if// 2. get allowed dbs from the "mysql.tables_priv" table$local_query = 'SELECT DISTINCT Db FROM mysql.tables_priv WHERE Table_priv LIKE \'%Select%\' AND User = \'' . PMA_sqlAddslashes($cfg['Server']['user']) . '\'';$rs = PMA_DBI_try_query($local_query, $controllink);if ($rs && @PMA_DBI_num_rows($rs)) {while ($row = PMA_DBI_fetch_assoc($rs)) {if (!in_array($row['Db'], $dblist)) {$dblist[] = $row['Db'];}} // end whilePMA_DBI_free_result($rs);} // end if} // end if} // end building available dbs from the "mysql" dbreturn $dblist;}/*** Converts numbers like 10M into bytes** @param string $size* @return integer $size*/function get_real_size($size = 0){if (!$size) {return 0;}$scan['MB'] = 1048576;$scan['Mb'] = 1048576;$scan['M'] = 1048576;$scan['m'] = 1048576;$scan['KB'] = 1024;$scan['Kb'] = 1024;$scan['K'] = 1024;$scan['k'] = 1024;while (list($key) = each($scan)) {if ((strlen($size) > strlen($key))&& (substr($size, strlen($size) - strlen($key)) == $key)) {$size = substr($size, 0, strlen($size) - strlen($key)) * $scan[$key];break;}}return $size;} // end function get_real_size()/*** loads php module** @uses PHP_OS* @uses extension_loaded()* @uses ini_get()* @uses function_exists()* @uses ob_start()* @uses phpinfo()* @uses strip_tags()* @uses ob_get_contents()* @uses ob_end_clean()* @uses preg_match()* @uses strtoupper()* @uses substr()* @uses dl()* @param string $module name if module to load* @return boolean success loading module*/function PMA_dl($module){static $dl_allowed = null;if (extension_loaded($module)) {return true;}if (null === $dl_allowed) {if (!@ini_get('safe_mode')&& @ini_get('enable_dl')&& @function_exists('dl')) {ob_start();phpinfo(INFO_GENERAL); /* Only general info */$a = strip_tags(ob_get_contents());ob_end_clean();if (preg_match('@Thread Safety[[:space:]]*enabled@', $a)) {if (preg_match('@Server API[[:space:]]*\(CGI\|CLI\)@', $a)) {$dl_allowed = true;} else {$dl_allowed = false;}} else {$dl_allowed = true;}} else {$dl_allowed = false;}}if (!$dl_allowed) {return false;}if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {$module_file = 'php_' . $module . '.dll';} else {$module_file = $module . '.so';}return @dl($module_file);}/*** merges array recursive like array_merge_recursive() but keyed-values are* always overwritten.** array PMA_array_merge_recursive(array $array1[, array $array2[, array ...]])** @see http://php.net/array_merge* @see http://php.net/array_merge_recursive* @uses func_num_args()* @uses func_get_arg()* @uses is_array()* @uses call_user_func_array()* @param array array to merge* @param array array to merge* @param array ...* @return array merged array*/function PMA_array_merge_recursive(){switch(func_num_args()) {case 0 :return false;break;case 1 :// when does that happen?return func_get_arg(0);break;case 2 :$args = func_get_args();if (!is_array($args[0]) || !is_array($args[1])) {return $args[1];}foreach ($args[1] AS $key2 => $value2) {if (isset($args[0][$key2]) && !is_int($key2)) {$args[0][$key2] = PMA_array_merge_recursive($args[0][$key2],$value2);} else {// we erase the parent array, otherwise we cannot override a directive that// contains array elements, like this:// (in config.default.php) $cfg['ForeignKeyDropdownOrder'] = array('id-content','content-id');// (in config.inc.php) $cfg['ForeignKeyDropdownOrder'] = array('content-id');if (is_int($key2) && $key2 == 0) {unset($args[0]);}$args[0][$key2] = $value2;}}return $args[0];break;default :$args = func_get_args();$args[1] = PMA_array_merge_recursive($args[0], $args[1]);array_shift($args);return call_user_func_array('PMA_array_merge_recursive', $args);break;}}/*** calls $function vor every element in $array recursively** @param array $array array to walk* @param string $function function to call for every array element*/function PMA_arrayWalkRecursive(&$array, $function, $apply_to_keys_also = false){foreach ($array as $key => $value) {if (is_array($value)) {PMA_arrayWalkRecursive($array[$key], $function, $apply_to_keys_also);} else {$array[$key] = $function($value);}if ($apply_to_keys_also && is_string($key)) {$new_key = $function($key);if ($new_key != $key) {$array[$new_key] = $array[$key];unset($array[$key]);}}}}/*** boolean phpMyAdmin.PMA_checkPageValidity(string &$page, array $whitelist)** checks given given $page against given $whitelist and returns true if valid* it ignores optionaly query paramters in $page (script.php?ignored)** @uses in_array()* @uses urldecode()* @uses substr()* @uses strpos()* @param string &$page page to check* @param array $whitelist whitelist to check page against* @return boolean whether $page is valid or not (in $whitelist or not)*/function PMA_checkPageValidity(&$page, $whitelist){if (! isset($page)) {return false;}if (in_array($page, $whitelist)) {return true;} elseif (in_array(substr($page, 0, strpos($page . '?', '?')), $whitelist)) {return true;} else {$_page = urldecode($page);if (in_array(substr($_page, 0, strpos($_page . '?', '?')), $whitelist)) {return true;}}return false;}/*** trys to find the value for the given environment vriable name** searchs in $_SERVER, $_ENV than trys getenv() and apache_getenv()* in this order** @param string $var_name variable name* @return string value of $var or empty string*/function PMA_getenv($var_name) {if (isset($_SERVER[$var_name])) {return $_SERVER[$var_name];} elseif (isset($_ENV[$var_name])) {return $_ENV[$var_name];} elseif (getenv($var_name)) {return getenv($var_name);} elseif (function_exists('apache_getenv')&& apache_getenv($var_name, true)) {return apache_getenv($var_name, true);}return '';}/*** include here only libraries which contain only function definitions* no code im main()!*//* Input sanitizing */require_once './libraries/sanitizing.lib.php';require_once './libraries/Theme.class.php';require_once './libraries/Theme_Manager.class.php';require_once './libraries/Config.class.php';if (!defined('PMA_MINIMUM_COMMON')) {/*** Displays the maximum size for an upload** @param integer the size** @return string the message** @access public*/function PMA_displayMaximumUploadSize($max_upload_size){list($max_size, $max_unit) = PMA_formatByteDown($max_upload_size);return '(' . sprintf($GLOBALS['strMaximumSize'], $max_size, $max_unit) . ')';}/*** Generates a hidden field which should indicate to the browser* the maximum size for upload** @param integer the size** @return string the INPUT field** @access public*/function PMA_generateHiddenMaxFileSize($max_size){return '<input type="hidden" name="MAX_FILE_SIZE" value="' .$max_size . '" />';}/*** Add slashes before "'" and "\" characters so a value containing them can* be used in a sql comparison.** @param string the string to slash* @param boolean whether the string will be used in a 'LIKE' clause* (it then requires two more escaped sequences) or not* @param boolean whether to treat cr/lfs as escape-worthy entities* (converts \n to \\n, \r to \\r)** @param boolean whether this function is used as part of the* "Create PHP code" dialog** @return string the slashed string** @access public*/function PMA_sqlAddslashes($a_string = '', $is_like = false, $crlf = false, $php_code = false){if ($is_like) {$a_string = str_replace('\\', '\\\\\\\\', $a_string);} else {$a_string = str_replace('\\', '\\\\', $a_string);}if ($crlf) {$a_string = str_replace("\n", '\n', $a_string);$a_string = str_replace("\r", '\r', $a_string);$a_string = str_replace("\t", '\t', $a_string);}if ($php_code) {$a_string = str_replace('\'', '\\\'', $a_string);} else {$a_string = str_replace('\'', '\'\'', $a_string);}return $a_string;} // end of the 'PMA_sqlAddslashes()' function/*** Add slashes before "_" and "%" characters for using them in MySQL* database, table and field names.* Note: This function does not escape backslashes!** @param string the string to escape** @return string the escaped string** @access public*/function PMA_escape_mysql_wildcards($name){$name = str_replace('_', '\\_', $name);$name = str_replace('%', '\\%', $name);return $name;} // end of the 'PMA_escape_mysql_wildcards()' function/*** removes slashes before "_" and "%" characters* Note: This function does not unescape backslashes!** @param string $name the string to escape* @return string the escaped string* @access public*/function PMA_unescape_mysql_wildcards($name){$name = str_replace('\\_', '_', $name);$name = str_replace('\\%', '%', $name);return $name;} // end of the 'PMA_unescape_mysql_wildcards()' function/*** format sql strings** @param mixed pre-parsed SQL structure** @return string the formatted sql** @global array the configuration array* @global boolean whether the current statement is a multiple one or not** @access public** @author Robin Johnson <robbat2@users.sourceforge.net>*/function PMA_formatSql($parsed_sql, $unparsed_sql = ''){global $cfg;// Check that we actually have a valid set of parsed data// well, not quite// first check for the SQL parser having hit an errorif (PMA_SQP_isError()) {return $parsed_sql;}// then check for an arrayif (!is_array($parsed_sql)) {// We don't so just return the input directly// This is intended to be used for when the SQL Parser is turned off$formatted_sql = '<pre>' . "\n". (($cfg['SQP']['fmtType'] == 'none' && $unparsed_sql != '') ? $unparsed_sql : $parsed_sql) . "\n". '</pre>';return $formatted_sql;}$formatted_sql = '';switch ($cfg['SQP']['fmtType']) {case 'none':if ($unparsed_sql != '') {$formatted_sql = "<pre>\n" . PMA_SQP_formatNone(array('raw' => $unparsed_sql)) . "\n</pre>";} else {$formatted_sql = PMA_SQP_formatNone($parsed_sql);}break;case 'html':$formatted_sql = PMA_SQP_formatHtml($parsed_sql, 'color');break;case 'text'://$formatted_sql = PMA_SQP_formatText($parsed_sql);$formatted_sql = PMA_SQP_formatHtml($parsed_sql, 'text');break;default:break;} // end switchreturn $formatted_sql;} // end of the "PMA_formatSql()" function/*** Displays a link to the official MySQL documentation** @param string chapter of "HTML, one page per chapter" documentation* @param string contains name of page/anchor that is being linked* @param bool whether to use big icon (like in left frame)** @return string the html link** @access public*/function PMA_showMySQLDocu($chapter, $link, $big_icon = false){global $cfg;if ($cfg['MySQLManualType'] == 'none' || empty($cfg['MySQLManualBase'])) {return '';}// Fixup for newly used names:$chapter = str_replace('_', '-', strtolower($chapter));$link = str_replace('_', '-', strtolower($link));switch ($cfg['MySQLManualType']) {case 'chapters':if (empty($chapter)) {$chapter = 'index';}$url = $cfg['MySQLManualBase'] . '/' . $chapter . '.html#' . $link;break;case 'big':$url = $cfg['MySQLManualBase'] . '#' . $link;break;case 'searchable':if (empty($link)) {$link = 'index';}$url = $cfg['MySQLManualBase'] . '/' . $link . '.html';break;case 'viewable':default:if (empty($link)) {$link = 'index';}$mysql = '5.0';if (defined('PMA_MYSQL_INT_VERSION')) {if (PMA_MYSQL_INT_VERSION < 50000) {$mysql = '4.1';} elseif (PMA_MYSQL_INT_VERSION >= 50100) {$mysql = '5.1';} elseif (PMA_MYSQL_INT_VERSION >= 50000) {$mysql = '5.0';}}$url = $cfg['MySQLManualBase'] . '/' . $mysql . '/en/' . $link . '.html';break;}if ($big_icon) {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>';} elseif ($GLOBALS['cfg']['ReplaceHelpImg']) {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>';} else {return '[<a href="' . $url . '" target="mysql_doc">' . $GLOBALS['strDocu'] . '</a>]';}} // end of the 'PMA_showMySQLDocu()' function/*** Displays a hint icon, on mouse over show the hint** @param string the error message** @access public*/function PMA_showHint($hint_message){//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) . '\');" />';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;" />';}/*** Displays a MySQL error message in the right frame.** @param string the error message* @param string the sql query that failed* @param boolean whether to show a "modify" link or not* @param string the "back" link url (full path is not required)* @param boolean EXIT the page?** @global array the configuration array** @access public*/function PMA_mysqlDie($error_message = '', $the_query = '',$is_modify_link = true, $back_url = '',$exit = true){global $cfg, $table, $db, $sql_query;require_once './libraries/header.inc.php';if (!$error_message) {$error_message = PMA_DBI_getError();}if (!$the_query && !empty($GLOBALS['sql_query'])) {$the_query = $GLOBALS['sql_query'];}// --- Added to solve bug #641765// Robbat2 - 12 January 2003, 9:46PM// Revised, Robbat2 - 13 January 2003, 2:59PMif (!function_exists('PMA_SQP_isError') || PMA_SQP_isError()) {$formatted_sql = htmlspecialchars($the_query);} elseif (empty($the_query) || trim($the_query) == '') {$formatted_sql = '';} else {$formatted_sql = PMA_formatSql(PMA_SQP_parse($the_query), $the_query);}// ---echo "\n" . '<!-- PMA-SQL-ERROR -->' . "\n";echo ' <div class="error"><h1>' . $GLOBALS['strError'] . '</h1>' . "\n";// if the config password is wrong, or the MySQL server does not// respond, do not show the query that would reveal the// username/passwordif (!empty($the_query) && !strstr($the_query, 'connect')) {// --- Added to solve bug #641765// Robbat2 - 12 January 2003, 9:46PM// Revised, Robbat2 - 13 January 2003, 2:59PMif (function_exists('PMA_SQP_isError') && PMA_SQP_isError()) {echo PMA_SQP_getErrorString() . "\n";echo '<br />' . "\n";}// ---// modified to show me the help on sql errors (Michael Keck)echo ' <p><strong>' . $GLOBALS['strSQLQuery'] . ':</strong>' . "\n";if (strstr(strtolower($formatted_sql), 'select')) { // please show me help to the error on selectecho PMA_showMySQLDocu('SQL-Syntax', 'SELECT');}if ($is_modify_link && isset($db)) {if (isset($table)) {$doedit_goto = '<a href="tbl_properties.php?' . PMA_generate_common_url($db, $table) . '&sql_query=' . urlencode($the_query) . '&show_query=1">';} else {$doedit_goto = '<a href="db_details.php?' . PMA_generate_common_url($db) . '&sql_query=' . urlencode($the_query) . '&show_query=1">';}if ($GLOBALS['cfg']['PropertiesIconic']) {echo $doedit_goto. '<img class="icon" src=" '. $GLOBALS['pmaThemeImage'] . 'b_edit.png" width="16" height="16" alt="' . $GLOBALS['strEdit'] .'" />'. '</a>';} else {echo ' ['. $doedit_goto . $GLOBALS['strEdit'] . '</a>'. ']' . "\n";}} // end ifecho ' </p>' . "\n".' <p>' . "\n".' ' . $formatted_sql . "\n".' </p>' . "\n";} // end if$tmp_mysql_error = ''; // for saving the original $error_messageif (!empty($error_message)) {$tmp_mysql_error = strtolower($error_message); // save the original $error_message$error_message = htmlspecialchars($error_message);$error_message = preg_replace("@((\015\012)|(\015)|(\012)){3,}@", "\n\n", $error_message);}// modified to show me the help on error-returns (Michael Keck)echo '<p>' . "\n". ' <strong>' . $GLOBALS['strMySQLSaid'] . '</strong>'. PMA_showMySQLDocu('Error-returns', 'Error-returns'). "\n". '</p>' . "\n";// The error message will be displayed within a CODE segment.// To preserve original formatting, but allow wordwrapping, we do a couple of replacements// Replace all non-single blanks with their HTML-counterpart$error_message = str_replace(' ', ' ', $error_message);// Replace TAB-characters with their HTML-counterpart$error_message = str_replace("\t", ' ', $error_message);// Replace linebreaks$error_message = nl2br($error_message);echo '<code>' . "\n". $error_message . "\n". '</code><br />' . "\n";// feature request #1036254:// Add a link by MySQL-Error #1062 - Duplicate entry// 2004-10-20 by mkkeck// 2005-01-17 modified by mkkeck bugfixif (substr($error_message, 1, 4) == '1062') {// get the duplicate entry// get table name// TODO: what would be the best delimiter, while avoiding// special characters that can become high-ascii after editing,// depending upon which editor is used by the developer?$error_table = array();if (preg_match('@ALTER\s*TABLE\s*\`([^\`]+)\`@iu', $the_query, $error_table)) {$error_table = $error_table[1];} elseif (preg_match('@INSERT\s*INTO\s*\`([^\`]+)\`@iu', $the_query, $error_table)) {$error_table = $error_table[1];} elseif (preg_match('@UPDATE\s*\`([^\`]+)\`@iu', $the_query, $error_table)) {$error_table = $error_table[1];} elseif (preg_match('@INSERT\s*\`([^\`]+)\`@iu', $the_query, $error_table)) {$error_table = $error_table[1];}// get fields$error_fields = array();if (preg_match('@\(([^\)]+)\)@i', $the_query, $error_fields)) {$error_fields = explode(',', $error_fields[1]);} elseif (preg_match('@(`[^`]+`)\s*=@i', $the_query, $error_fields)) {$error_fields = explode(',', $error_fields[1]);}if (is_array($error_table) || is_array($error_fields)) {// duplicate value$duplicate_value = array();preg_match('@\'([^\']+)\'@i', $tmp_mysql_error, $duplicate_value);$duplicate_value = $duplicate_value[1];$sql = 'SELECT *FROM ' . PMA_backquote($error_table) . 'WHERE CONCAT_WS("-", ' . implode(', ', $error_fields) . ')= "' . PMA_sqlAddslashes($duplicate_value) . '"ORDER BY ' . implode(', ', $error_fields);unset($error_table, $error_fields, $duplicate_value);echo ' <form method="post" action="import.php" style="padding: 0; margin: 0">' ."\n".' <input type="hidden" name="sql_query" value="' . htmlentities($sql) . '" />' . "\n".' ' . PMA_generate_common_hidden_inputs($db, $table) . "\n".' <input type="submit" name="submit" value="' . $GLOBALS['strBrowse'] . '" />' . "\n".' </form>' . "\n";unset($sql);}} // end of show duplicate entryecho '</div>';echo '<fieldset class="tblFooters">';if (!empty($back_url) && $exit) {$goto_back_url='<a href="' . (strstr($back_url, '?') ? $back_url . '&no_history=true' : $back_url . '?no_history=true') . '">';echo '[ ' . $goto_back_url . $GLOBALS['strBack'] . '</a> ]';}echo ' </fieldset>' . "\n\n";if ($exit) {require_once './libraries/footer.inc.php';}} // end of the 'PMA_mysqlDie()' function/*** Returns a string formatted with CONVERT ... USING* if MySQL supports it** @param string the string itself* @param string the mode: quoted or unquoted (this one by default)** @return the formatted string** @access private*/function PMA_convert_using($string, $mode='unquoted'){if ($mode == 'quoted') {$possible_quote = "'";} else {$possible_quote = "";}if (PMA_MYSQL_INT_VERSION >= 40100) {list($conn_charset) = explode('_', $GLOBALS['collation_connection']);$converted_string = "CONVERT(" . $possible_quote . $string . $possible_quote . " USING " . $conn_charset . ")";} else {$converted_string = $possible_quote . $string . $possible_quote;}return $converted_string;} // end function/*** Send HTTP header, taking IIS limits into account (600 seems ok)** @param string $uri the header to send* @return boolean always true*/function PMA_sendHeaderLocation($uri){if (PMA_IS_IIS && strlen($uri) > 600) {echo '<html><head><title>- - -</title>' . "\n";echo '<meta http-equiv="expires" content="0">' . "\n";echo '<meta http-equiv="Pragma" content="no-cache">' . "\n";echo '<meta http-equiv="Cache-Control" content="no-cache">' . "\n";echo '<meta http-equiv="Refresh" content="0;url=' .$uri . '">' . "\n";echo '<script type="text/javascript" language="javascript">' . "\n";echo '//<![CDATA[' . "\n";echo 'setTimeout ("window.location = unescape(\'"' . $uri . '"\')",2000); </script>' . "\n";echo '//]]>' . "\n";echo '</head>' . "\n";echo '<body>' . "\n";echo '<script type="text/javascript" language="javascript">' . "\n";echo '//<![CDATA[' . "\n";echo 'document.write (\'<p><a href="' . $uri . '">' . $GLOBALS['strGo'] . '</a></p>\');' . "\n";echo '//]]>' . "\n";echo '</script></body></html>' . "\n";} else {if (SID) {if (strpos($uri, '?') === false) {header('Location: ' . $uri . '?' . SID);} else {// use seperators defined by php, but prefer ';'// as recommended by W3C$php_arg_separator_input = ini_get('arg_separator.input');if (strpos($php_arg_separator_input, ';') !== false) {$separator = ';';} elseif (strlen($php_arg_separator_input) > 0) {$separator = $php_arg_separator_input{0};} else {$separator = '&';}header('Location: ' . $uri . $separator . SID);}} else {session_write_close();// bug #1523784, IE6 does not like 'Refresh: 0', it// results in a blank pageif (PMA_IS_IIS && defined('PMA_COMING_FROM_COOKIE_LOGIN')) {header('Refresh: 0; ' . $uri);} else {header('Location: ' . $uri);}}}}/*** Get the list and number of available databases.** @param string the url to go back to in case of error** @return boolean always true** @global array the list of available databases* @global integer the number of available databases* @global array current configuration*/function PMA_availableDatabases($error_url = ''){global $dblist;global $num_dbs;global $cfg;// 1. A list of allowed databases has already been defined by the// authentication process -> gets the available databases listif (count($dblist)) {foreach ($dblist as $key => $db) {if (!@PMA_DBI_select_db($db) || (!empty($GLOBALS['cfg']['Server']['hide_db']) && preg_match('/' . $GLOBALS['cfg']['Server']['hide_db'] . '/', $db))) {unset($dblist[$key]);} // end if} // end for} // end if// 2. Allowed database list is empty -> gets the list of all databases// on the serverelseif (empty($cfg['Server']['only_db'])) {$dblist = PMA_DBI_get_dblist(); // needed? or PMA_mysqlDie('', 'SHOW DATABASES;', false, $error_url);} // end else$num_dbs = count($dblist);// natural order for db list; but do not sort if user asked// for a specific order with the 'only_db' mechanismif (!is_array($GLOBALS['cfg']['Server']['only_db'])&& $GLOBALS['cfg']['NaturalOrder']) {natsort($dblist);}return true;} // end of the 'PMA_availableDatabases()' function/*** returns array with tables of given db with extended infomation and grouped** @uses $GLOBALS['cfg']['LeftFrameTableSeparator']* @uses $GLOBALS['cfg']['LeftFrameTableLevel']* @uses $GLOBALS['cfg']['ShowTooltipAliasTB']* @uses $GLOBALS['cfg']['NaturalOrder']* @uses PMA_DBI_fetch_result()* @uses PMA_backquote()* @uses count()* @uses array_merge* @uses uksort()* @uses strstr()* @uses explode()* @param string $db name of db* return array (rekursive) grouped table list*/function PMA_getTableList($db, $tables = null){$sep = $GLOBALS['cfg']['LeftFrameTableSeparator'];if ( null === $tables ) {$tables = PMA_DBI_get_tables_full($db);if ($GLOBALS['cfg']['NaturalOrder']) {uksort($tables, 'strnatcasecmp');}}if (count($tables) < 1) {return $tables;}$default = array('Name' => '','Rows' => 0,'Comment' => '','disp_name' => '',);$table_groups = array();foreach ($tables as $table_name => $table) {// check for correct row countif (null === $table['Rows']) {// Do not check exact row count here,// if row count is invalid possibly the table is defect// and this would break left frame;// but we can check row count if this is a view,// since PMA_countRecords() returns a limited row count// in this case.// set this because PMA_countRecords() can use it$tbl_is_view = PMA_tableIsView($db, $table['Name']);if ($tbl_is_view) {$table['Rows'] = PMA_countRecords($db, $table['Name'],$return = true);}}// in $group we save the reference to the place in $table_groups// where to store the table infoif ($GLOBALS['cfg']['LeftFrameDBTree']&& $sep && strstr($table_name, $sep)){$parts = explode($sep, $table_name);$group =& $table_groups;$i = 0;$group_name_full = '';while ($i < count($parts) - 1&& $i < $GLOBALS['cfg']['LeftFrameTableLevel']) {$group_name = $parts[$i] . $sep;$group_name_full .= $group_name;if (!isset($group[$group_name])) {$group[$group_name] = array();$group[$group_name]['is' . $sep . 'group'] = true;$group[$group_name]['tab' . $sep . 'count'] = 1;$group[$group_name]['tab' . $sep . 'group'] = $group_name_full;} elseif (!isset($group[$group_name]['is' . $sep . 'group'])) {$table = $group[$group_name];$group[$group_name] = array();$group[$group_name][$group_name] = $table;unset($table);$group[$group_name]['is' . $sep . 'group'] = true;$group[$group_name]['tab' . $sep . 'count'] = 1;$group[$group_name]['tab' . $sep . 'group'] = $group_name_full;} else {$group[$group_name]['tab' . $sep . 'count']++;}$group =& $group[$group_name];$i++;}} else {if (!isset($table_groups[$table_name])) {$table_groups[$table_name] = array();}$group =& $table_groups;}if ($GLOBALS['cfg']['ShowTooltipAliasTB']&& $GLOBALS['cfg']['ShowTooltipAliasTB'] !== 'nested') {// switch tooltip and name$table['Comment'] = $table['Name'];$table['disp_name'] = $table['Comment'];} else {$table['disp_name'] = $table['Name'];}$group[$table_name] = array_merge($default, $table);}return $table_groups;}/* ----------------------- Set of misc functions ----------------------- *//*** Adds backquotes on both sides of a database, table or field name.* and escapes backquotes inside the name with another backquote** <code>* echo PMA_backquote('owner`s db'); // `owner``s db`* </code>** @param mixed $a_name the database, table or field name to "backquote"* or array of it* @param boolean $do_it a flag to bypass this function (used by dump* functions)* @return mixed the "backquoted" database, table or field name if the* current MySQL release is >= 3.23.6, the original one* else* @access public*/function PMA_backquote($a_name, $do_it = true){if (! $do_it) {return $a_name;}if (is_array($a_name)) {$result = array();foreach ($a_name as $key => $val) {$result[$key] = PMA_backquote($val);}return $result;}// '0' is also empty for php :-(if (strlen($a_name) && $a_name != '*') {return '`' . str_replace('`', '``', $a_name) . '`';} else {return $a_name;}} // end of the 'PMA_backquote()' function/*** Format a string so it can be passed to a javascript function.* This function is used to displays a javascript confirmation box for* "DROP/DELETE/ALTER" queries.** @param string the string to format* @param boolean whether to add backquotes to the string or not** @return string the formated string** @access public*/function PMA_jsFormat($a_string = '', $add_backquotes = true){if (is_string($a_string)) {$a_string = htmlspecialchars($a_string);$a_string = str_replace('\\', '\\\\', $a_string);$a_string = str_replace('\'', '\\\'', $a_string);$a_string = str_replace('#', '\\#', $a_string);$a_string = str_replace("\012", '\\\\n', $a_string);$a_string = str_replace("\015", '\\\\r', $a_string);}return (($add_backquotes) ? PMA_backquote($a_string) : $a_string);} // end of the 'PMA_jsFormat()' function/*** Defines the <CR><LF> value depending on the user OS.** @return string the <CR><LF> value to use** @access public*/function PMA_whichCrlf(){$the_crlf = "\n";// The 'PMA_USR_OS' constant is defined in "./libraries/defines.lib.php"// Win caseif (PMA_USR_OS == 'Win') {$the_crlf = "\r\n";}// Mac caseelseif (PMA_USR_OS == 'Mac') {$the_crlf = "\r";}// Otherselse {$the_crlf = "\n";}return $the_crlf;} // end of the 'PMA_whichCrlf()' function/*** Checks if this "table" is a view** @param string the database name* @param string the table name** @return boolean whether this is a view** @access public*/function PMA_tableIsView($db, $table) {// maybe we already know if the table is a view// TODO: see what we could do with the possible existence// of $table_is_viewif (isset($GLOBALS['tbl_is_view']) && $GLOBALS['tbl_is_view']) {return true;}// old MySQL version: no viewif (PMA_MYSQL_INT_VERSION < 50000) {return false;}if ( false === PMA_DBI_fetch_value('SELECT TABLE_NAME FROM information_schema.VIEWS WHERE TABLE_SCHEMA = \'' . $db . '\' AND TABLE_NAME = \'' . $table . '\';')) {return false;} else {return true;}}/*** Counts and returns (or displays) the number of records in a table** Revision 13 July 2001: Patch for limiting dump size from* vinay@sanisoft.com & girish@sanisoft.com** @param string the current database name* @param string the current table name* @param boolean whether to retain or to displays the result* @param boolean whether to force an exact count** @return mixed the number of records if retain is required, true else** @access public*/function PMA_countRecords($db, $table, $ret = false, $force_exact = false){global $err_url, $cfg;if (!$force_exact) {$result = PMA_DBI_query('SHOW TABLE STATUS FROM ' . PMA_backquote($db) . ' LIKE \'' . PMA_sqlAddslashes($table, true) . '\';');$showtable = PMA_DBI_fetch_assoc($result);$num = (isset($showtable['Rows']) ? $showtable['Rows'] : 0);if ($num < $cfg['MaxExactCount']) {unset($num);}PMA_DBI_free_result($result);}$tbl_is_view = PMA_tableIsView($db, $table);if (!isset($num)) {if (! $tbl_is_view) {$num = PMA_DBI_fetch_value('SELECT COUNT(*) AS num FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table));// necessary?if (! $num) {$num = 0;}// since counting all rows of a view could be too long} else {// try_query because if can fail (a VIEW was based on a// table that no longer exists)$result = PMA_DBI_try_query('SELECT 1 FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table) . ' LIMIT ' . $cfg['MaxExactCount'], null, PMA_DBI_QUERY_STORE);if (!PMA_DBI_getError()) {$num = PMA_DBI_num_rows($result);} else {$num = 0;}}}if ($ret) {return $num;} else {// Note: as of PMA 2.8.0, we no longer seem to be using// PMA_countRecords() in display mode.echo number_format($num, 0, $GLOBALS['number_decimal_separator'], $GLOBALS['number_thousands_separator']);if ($tbl_is_view) {echo ' ' . sprintf($GLOBALS['strViewMaxExactCount'], $cfg['MaxExactCount'], '[a@./Documentation.html#cfg_MaxExactCount@_blank]', '[/a]');}return true;}} // end of the 'PMA_countRecords()' function/*** Reloads navigation if needed.** @global mixed configuration* @global bool whether to reload** @access public*/function PMA_reloadNavigation(){global $cfg;// Reloads the navigation frame via JavaScript if requiredif (isset($GLOBALS['reload']) && $GLOBALS['reload']) {echo "\n";$reload_url = './left.php?' . PMA_generate_common_url((isset($GLOBALS['db']) ? $GLOBALS['db'] : ''), '', '&');?><script type="text/javascript" language="javascript">//<![CDATA[if (typeof(window.parent) != 'undefined'&& typeof(window.parent.frames[0]) != 'undefined') {window.parent.goTo('<?php echo $reload_url; ?>');}//]]></script><?phpunset($GLOBALS['reload']);}}/*** Displays a message at the top of the "main" (right) frame** @param string the message to display** @global array the configuration array** @access public*/function PMA_showMessage($message){global $cfg;// Sanitizes $message$message = PMA_sanitize($message);// Corrects the tooltip text via JS if requiredif ( isset($GLOBALS['table']) && strlen($GLOBALS['table']) && $cfg['ShowTooltip']) {$result = PMA_DBI_try_query('SHOW TABLE STATUS FROM ' . PMA_backquote($GLOBALS['db']) . ' LIKE \'' . PMA_sqlAddslashes($GLOBALS['table'], true) . '\'');if ($result) {$tbl_status = PMA_DBI_fetch_assoc($result);$tooltip = (empty($tbl_status['Comment']))? '': $tbl_status['Comment'] . ' ';$tooltip .= '(' . PMA_formatNumber($tbl_status['Rows'], 0) . ' ' . $GLOBALS['strRows'] . ')';PMA_DBI_free_result($result);$uni_tbl = PMA_jsFormat($GLOBALS['db'] . '.' . $GLOBALS['table'], false);echo "\n";?><script type="text/javascript" language="javascript">//<![CDATA[window.parent.updateTableTitle('<?php echo $uni_tbl; ?>', '<?php echo PMA_jsFormat($tooltip, false); ?>');//]]></script><?php} // end if} // end if ... elseif// Checks if the table needs to be repaired after a TRUNCATE query.if (isset($GLOBALS['table']) && isset($GLOBALS['sql_query'])&& $GLOBALS['sql_query'] == 'TRUNCATE TABLE ' . PMA_backquote($GLOBALS['table'])) {if (!isset($tbl_status)) {$result = @PMA_DBI_try_query('SHOW TABLE STATUS FROM ' . PMA_backquote($GLOBALS['db']) . ' LIKE \'' . PMA_sqlAddslashes($GLOBALS['table'], true) . '\'');if ($result) {$tbl_status = PMA_DBI_fetch_assoc($result);PMA_DBI_free_result($result);}}if (isset($tbl_status) && (int) $tbl_status['Index_length'] > 1024) {PMA_DBI_try_query('REPAIR TABLE ' . PMA_backquote($GLOBALS['table']));}}unset($tbl_status);?><br /><div align="<?php echo $GLOBALS['cell_align_left']; ?>"><?phpif (!empty($GLOBALS['show_error_header'])) {?><div class="error"><h1><?php echo $GLOBALS['strError']; ?></h1><?php}echo $message;if (isset($GLOBALS['special_message'])) {echo PMA_sanitize($GLOBALS['special_message']);unset($GLOBALS['special_message']);}if (!empty($GLOBALS['show_error_header'])) {echo '</div>';}if ($cfg['ShowSQL'] == true&& (!empty($GLOBALS['sql_query']) || !empty($GLOBALS['display_query']))) {$local_query = !empty($GLOBALS['display_query']) ? $GLOBALS['display_query'] : (($cfg['SQP']['fmtType'] == 'none' && isset($GLOBALS['unparsed_sql']) && $GLOBALS['unparsed_sql'] != '') ? $GLOBALS['unparsed_sql'] : $GLOBALS['sql_query']);// Basic url query part$url_qpart = '?' . PMA_generate_common_url(isset($GLOBALS['db']) ? $GLOBALS['db'] : '', isset($GLOBALS['table']) ? $GLOBALS['table'] : '');// Html format the query to be displayed// The nl2br function isn't used because its result isn't a valid// xhtml1.0 statement before php4.0.5 ("<br>" and not "<br />")// If we want to show some sql code it is easiest to create it here/* SQL-Parser-Analyzer */if (!empty($GLOBALS['show_as_php'])) {$new_line = '\'<br />' . "\n" . ' . \' ';}if (isset($new_line)) {/* SQL-Parser-Analyzer */$query_base = PMA_sqlAddslashes(htmlspecialchars($local_query), false, false, true);/* SQL-Parser-Analyzer */$query_base = preg_replace("@((\015\012)|(\015)|(\012))+@", $new_line, $query_base);} else {$query_base = $local_query;}// Parse SQL if neededif (isset($GLOBALS['parsed_sql']) && $query_base == $GLOBALS['parsed_sql']['raw']) {$parsed_sql = $GLOBALS['parsed_sql'];} else {// when the query is large (for example an INSERT of binary// data), the parser chokes; so avoid parsing itif (strlen($query_base) < 1000) {$parsed_sql = PMA_SQP_parse($query_base);}}// Analyze itif (isset($parsed_sql)) {$analyzed_display_query = PMA_SQP_analyze($parsed_sql);}// Here we append the LIMIT added for navigation, to// enable its display. Adding it higher in the code// to $local_query would create a problem when// using the Refresh or Edit links.// Only append it on SELECTs.// FIXME: what would be the best to do when someone// hits Refresh: use the current LIMITs ?if (isset($analyzed_display_query[0]['queryflags']['select_from'])&& isset($GLOBALS['sql_limit_to_append'])) {$query_base = $analyzed_display_query[0]['section_before_limit'] . "\n" . $GLOBALS['sql_limit_to_append'] . $analyzed_display_query[0]['section_after_limit'];// Need to reparse query$parsed_sql = PMA_SQP_parse($query_base);}if (!empty($GLOBALS['show_as_php'])) {$query_base = '$sql = \'' . $query_base;} elseif (!empty($GLOBALS['validatequery'])) {$query_base = PMA_validateSQL($query_base);} else {if (isset($parsed_sql)) {$query_base = PMA_formatSql($parsed_sql, $query_base);}}// Prepares links that may be displayed to edit/explain the query// (don't go to default pages, we must go to the page// where the query box is available)// (also, I don't see why we should check the goto variable)//if (!isset($GLOBALS['goto'])) {//$edit_target = (isset($GLOBALS['table'])) ? $cfg['DefaultTabTable'] : $cfg['DefaultTabDatabase'];$edit_target = isset($GLOBALS['db']) ? (isset($GLOBALS['table']) ? 'tbl_properties.php' : 'db_details.php') : 'server_sql.php';//} elseif ($GLOBALS['goto'] != 'main.php') {// $edit_target = $GLOBALS['goto'];//} else {// $edit_target = '';//}if (isset($cfg['SQLQuery']['Edit'])&& ($cfg['SQLQuery']['Edit'] == true)&& (!empty($edit_target))) {if ($cfg['EditInWindow'] == true) {$onclick = 'window.parent.focus_querywindow(\'' . urlencode($local_query) . '\'); return false;';} else {$onclick = '';}$edit_link = $edit_target. $url_qpart. '&sql_query=' . urlencode($local_query). '&show_query=1#querybox';$edit_link = ' [' . PMA_linkOrButton($edit_link, $GLOBALS['strEdit'], array('onclick' => $onclick)) . ']';} else {$edit_link = '';}// Want to have the query explained (Mike Beck 2002-05-22)// but only explain a SELECT (that has not been explained)/* SQL-Parser-Analyzer */if (isset($cfg['SQLQuery']['Explain'])&& $cfg['SQLQuery']['Explain'] == true) {// Detect if we are validating as well// To preserve the validate uRL dataif (!empty($GLOBALS['validatequery'])) {$explain_link_validate = '&validatequery=1';} else {$explain_link_validate = '';}$explain_link = 'import.php'. $url_qpart. $explain_link_validate. '&sql_query=';if (preg_match('@^SELECT[[:space:]]+@i', $local_query)) {$explain_link .= urlencode('EXPLAIN ' . $local_query);$message = $GLOBALS['strExplain'];} elseif (preg_match('@^EXPLAIN[[:space:]]+SELECT[[:space:]]+@i', $local_query)) {$explain_link .= urlencode(substr($local_query, 8));$message = $GLOBALS['strNoExplain'];} else {$explain_link = '';}if (!empty($explain_link)) {$explain_link = ' [' . PMA_linkOrButton($explain_link, $message) . ']';}} else {$explain_link = '';} //show explain// Also we would like to get the SQL formed in some nice// php-code (Mike Beck 2002-05-22)if (isset($cfg['SQLQuery']['ShowAsPHP'])&& $cfg['SQLQuery']['ShowAsPHP'] == true) {$php_link = 'import.php'. $url_qpart. '&show_query=1'. '&sql_query=' . urlencode($local_query). '&show_as_php=';if (!empty($GLOBALS['show_as_php'])) {$php_link .= '0';$message = $GLOBALS['strNoPhp'];} else {$php_link .= '1';$message = $GLOBALS['strPhp'];}$php_link = ' [' . PMA_linkOrButton($php_link, $message) . ']';if (isset($GLOBALS['show_as_php']) && $GLOBALS['show_as_php'] == '1') {$runquery_link= 'import.php'. $url_qpart. '&show_query=1'. '&sql_query=' . urlencode($local_query);$php_link .= ' [' . PMA_linkOrButton($runquery_link, $GLOBALS['strRunQuery']) . ']';}} else {$php_link = '';} //show as php// Refresh queryif (isset($cfg['SQLQuery']['Refresh'])&& $cfg['SQLQuery']['Refresh']&& preg_match('@^(SELECT|SHOW)[[:space:]]+@i', $local_query)) {$refresh_link = 'import.php'. $url_qpart. '&show_query=1'. (isset($_GET['pos']) ? '&pos=' . $_GET['pos'] : ''). '&sql_query=' . urlencode($local_query);$refresh_link = ' [' . PMA_linkOrButton($refresh_link, $GLOBALS['strRefresh']) . ']';} else {$refresh_link = '';} //show as phpif (isset($cfg['SQLValidator']['use'])&& $cfg['SQLValidator']['use'] == true&& isset($cfg['SQLQuery']['Validate'])&& $cfg['SQLQuery']['Validate'] == true) {$validate_link = 'import.php'. $url_qpart. '&show_query=1'. '&sql_query=' . urlencode($local_query). '&validatequery=';if (!empty($GLOBALS['validatequery'])) {$validate_link .= '0';$validate_message = $GLOBALS['strNoValidateSQL'] ;} else {$validate_link .= '1';$validate_message = $GLOBALS['strValidateSQL'] ;}$validate_link = ' [' . PMA_linkOrButton($validate_link, $validate_message) . ']';} else {$validate_link = '';} //validatorunset($local_query);// Displays the messageecho '<fieldset class="">' . "\n";echo ' <legend>' . $GLOBALS['strSQLQuery'] . ':</legend>';echo ' ' . $query_base;//Clean up the end of the PHPif (!empty($GLOBALS['show_as_php'])) {echo '\';';}echo '</fieldset>' . "\n";if (!empty($edit_target)) {echo '<fieldset class="tblFooters">';echo $edit_link . $explain_link . $php_link . $refresh_link . $validate_link;echo '</fieldset>';}}?></div><br /><?php} // end of the 'PMA_showMessage()' function/*** Formats $value to byte view** @param double the value to format* @param integer the sensitiveness* @param integer the number of decimals to retain** @return array the formatted value and its unit** @access public** @author staybyte* @version 1.2 - 18 July 2002*/function PMA_formatByteDown($value, $limes = 6, $comma = 0){$dh = pow(10, $comma);$li = pow(10, $limes);$return_value = $value;$unit = $GLOBALS['byteUnits'][0];for ($d = 6, $ex = 15; $d >= 1; $d--, $ex-=3) {if (isset($GLOBALS['byteUnits'][$d]) && $value >= $li * pow(10, $ex)) {$value = round($value / (pow(1024, $d) / $dh)) /$dh;$unit = $GLOBALS['byteUnits'][$d];break 1;} // end if} // end forif ($unit != $GLOBALS['byteUnits'][0]) {$return_value = number_format($value, $comma, $GLOBALS['number_decimal_separator'], $GLOBALS['number_thousands_separator']);} else {$return_value = number_format($value, 0, $GLOBALS['number_decimal_separator'], $GLOBALS['number_thousands_separator']);}return array($return_value, $unit);} // end of the 'PMA_formatByteDown' function/*** Formats $value to the given length and appends SI prefixes* $comma is not substracted from the length* with a $length of 0 no truncation occurs, number is only formated* to the current locale* <code>* echo PMA_formatNumber(123456789, 6); // 123,457 k* echo PMA_formatNumber(-123456789, 4, 2); // -123.46 M* echo PMA_formatNumber(-0.003, 6); // -3 m* echo PMA_formatNumber(0.003, 3, 3); // 0.003* echo PMA_formatNumber(0.00003, 3, 2); // 0.03 m* echo PMA_formatNumber(0, 6); // 0* </code>* @param double $value the value to format* @param integer $length the max length* @param integer $comma the number of decimals to retain* @param boolean $only_down do not reformat numbers below 1** @return string the formatted value and its unit** @access public** @author staybyte, sebastian mendel* @version 1.1.0 - 2005-10-27*/function PMA_formatNumber($value, $length = 3, $comma = 0, $only_down = false){if ($length === 0) {return number_format($value,$comma,$GLOBALS['number_decimal_separator'],$GLOBALS['number_thousands_separator']);}// this units needs no translation, ISO$units = array(-8 => 'y',-7 => 'z',-6 => 'a',-5 => 'f',-4 => 'p',-3 => 'n',-2 => 'µ',-1 => 'm',0 => ' ',1 => 'k',2 => 'M',3 => 'G',4 => 'T',5 => 'P',6 => 'E',7 => 'Z',8 => 'Y');// we need at least 3 digits to be displayedif (3 > $length + $comma) {$length = 3 - $comma;}// check for negativ value to retain signif ($value < 0) {$sign = '-';$value = abs($value);} else {$sign = '';}$dh = pow(10, $comma);$li = pow(10, $length);$unit = $units[0];if ($value >= 1) {for ($d = 8; $d >= 0; $d--) {if (isset($units[$d]) && $value >= $li * pow(1000, $d-1)) {$value = round($value / (pow(1000, $d) / $dh)) /$dh;$unit = $units[$d];break 1;} // end if} // end for} elseif (!$only_down && (float) $value !== 0.0) {for ($d = -8; $d <= 8; $d++) {if (isset($units[$d]) && $value <= $li * pow(1000, $d-1)) {$value = round($value / (pow(1000, $d) / $dh)) /$dh;$unit = $units[$d];break 1;} // end if} // end for} // end if ($value >= 1) elseif (!$only_down && (float) $value !== 0.0)$value = number_format($value,$comma,$GLOBALS['number_decimal_separator'],$GLOBALS['number_thousands_separator']);return $sign . $value . ' ' . $unit;} // end of the 'PMA_formatNumber' function/*** Extracts ENUM / SET options from a type definition string** @param string The column type definition** @return array The options or* boolean false in case of an error.** @author rabus*/function PMA_getEnumSetOptions($type_def){$open = strpos($type_def, '(');$close = strrpos($type_def, ')');if (!$open || !$close) {return false;}$options = substr($type_def, $open + 2, $close - $open - 3);$options = explode('\',\'', $options);return $options;} // end of the 'PMA_getEnumSetOptions' function/*** Writes localised date** @param string the current timestamp** @return string the formatted date** @access public*/function PMA_localisedDate($timestamp = -1, $format = ''){global $datefmt, $month, $day_of_week;if ($format == '') {$format = $datefmt;}if ($timestamp == -1) {$timestamp = time();}$date = preg_replace('@%[aA]@', $day_of_week[(int)strftime('%w', $timestamp)], $format);$date = preg_replace('@%[bB]@', $month[(int)strftime('%m', $timestamp)-1], $date);return strftime($date, $timestamp);} // end of the 'PMA_localisedDate()' function/*** returns a tab for tabbed navigation.* If the variables $link and $args ar left empty, an inactive tab is created** @uses array_merge()* basename()* $GLOBALS['strEmpty']* $GLOBALS['strDrop']* $GLOBALS['active_page']* $GLOBALS['PHP_SELF']* htmlentities()* PMA_generate_common_url()* $GLOBALS['url_query']* urlencode()* $GLOBALS['cfg']['MainPageIconic']* $GLOBALS['pmaThemeImage']* sprintf()* trigger_error()* E_USER_NOTICE* @param array $tab array with all options* @return string html code for one tab, a link if valid otherwise a span* @access public*/function PMA_getTab($tab){// default values$defaults = array('text' => '','class' => '','active' => false,'link' => '','sep' => '?','attr' => '','args' => '',);$tab = array_merge($defaults, $tab);// determine additionnal style-classif (empty($tab['class'])) {if ($tab['text'] == $GLOBALS['strEmpty']|| $tab['text'] == $GLOBALS['strDrop']) {$tab['class'] = 'caution';} elseif (!empty($tab['active'])|| (isset($GLOBALS['active_page'])&& $GLOBALS['active_page'] == $tab['link'])|| basename(PMA_getenv('PHP_SELF')) == $tab['link']){$tab['class'] = 'active';}}// build the linkif (!empty($tab['link'])) {$tab['link'] = htmlentities($tab['link']);$tab['link'] = $tab['link'] . $tab['sep'].(empty($GLOBALS['url_query']) ?PMA_generate_common_url() : $GLOBALS['url_query']);if (!empty($tab['args'])) {foreach ($tab['args'] as $param => $value) {$tab['link'] .= '&' . urlencode($param) . '='. urlencode($value);}}}// display icon, even if iconic is disabled but the link-text is missingif (($GLOBALS['cfg']['MainPageIconic'] || empty($tab['text']))&& isset($tab['icon'])) {$image = '<img class="icon" src="' . htmlentities($GLOBALS['pmaThemeImage']).'%1$s" width="16" height="16" alt="%2$s" />%2$s';$tab['text'] = sprintf($image, htmlentities($tab['icon']), $tab['text']);}// check to not display an empty link-textelseif (empty($tab['text'])) {$tab['text'] = '?';trigger_error('empty linktext in function ' . __FUNCTION__ . '()',E_USER_NOTICE);}if (!empty($tab['link'])) {$out = '<a class="tab' . htmlentities($tab['class']) . '"'.' href="' . $tab['link'] . '" ' . $tab['attr'] . '>'. $tab['text'] . '</a>';} else {$out = '<span class="tab' . htmlentities($tab['class']) . '">'. $tab['text'] . '</span>';}return $out;} // end of the 'PMA_getTab()' function/*** returns html-code for a tab navigation** @uses PMA_getTab()* @uses htmlentities()* @param array $tabs one element per tab* @param string $tag_id id used for the html-tag* @return string html-code for tab-navigation*/function PMA_getTabs($tabs, $tag_id = 'topmenu'){$tab_navigation ='<div id="' . htmlentities($tag_id) . 'container">' . "\n".'<ul id="' . htmlentities($tag_id) . '">' . "\n";foreach ($tabs as $tab) {$tab_navigation .= '<li>' . PMA_getTab($tab) . '</li>' . "\n";}$tab_navigation .='</ul>' . "\n".'<div class="clearfloat"></div>'.'</div>' . "\n";return $tab_navigation;}/*** Displays a link, or a button if the link's URL is too large, to* accommodate some browsers' limitations** @param string the URL* @param string the link message* @param mixed $tag_params string: js confirmation* array: additional tag params (f.e. style="")* @param boolean $new_form we set this to false when we are already in* a form, to avoid generating nested forms** @return string the results to be echoed or saved in an array*/function PMA_linkOrButton($url, $message, $tag_params = array(),$new_form = true, $strip_img = false, $target = ''){if (! is_array($tag_params)) {$tmp = $tag_params;$tag_params = array();if (!empty($tmp)) {$tag_params['onclick'] = 'return confirmLink(this, \'' . $tmp . '\')';}unset($tmp);}if (! empty($target)) {$tag_params['target'] = htmlentities($target);}$tag_params_strings = array();foreach ($tag_params as $par_name => $par_value) {// htmlentities() only on non javascript$par_value = substr($par_name, 0, 2) == 'on'? $par_value: htmlentities($par_value);$tag_params_strings[] = $par_name . '="' . $par_value . '"';}// previously the limit was set to 2047, it seems 1000 is betterif (strlen($url) <= 1000) {// no whitespace within an <a> else Safari will make it part of the link$ret = "\n" . '<a href="' . $url . '" '. implode(' ', $tag_params_strings) . '>'. $message . '</a>' . "\n";} else {// no spaces (linebreaks) at all// or after the hidden fields// IE will display them all// add class=link to submit buttonif (empty($tag_params['class'])) {$tag_params['class'] = 'link';}$url = str_replace('&', '&', $url);$url_parts = parse_url($url);$query_parts = explode('&', $url_parts['query']);if ($new_form) {$ret = '<form action="' . $url_parts['path'] . '" class="link"'. ' method="post"' . $target . ' style="display: inline;">';$subname_open = '';$subname_close = '';$submit_name = '';} else {$query_parts[] = 'redirect=' . $url_parts['path'];if (empty($GLOBALS['subform_counter'])) {$GLOBALS['subform_counter'] = 0;}$GLOBALS['subform_counter']++;$ret = '';$subname_open = 'subform[' . $GLOBALS['subform_counter'] . '][';$subname_close = ']';$submit_name = ' name="usesubform[' . $GLOBALS['subform_counter'] . ']"';}foreach ($query_parts AS $query_pair) {list($eachvar, $eachval) = explode('=', $query_pair);$ret .= '<input type="hidden" name="' . $subname_open . $eachvar. $subname_close . '" value="'. htmlspecialchars(urldecode($eachval)) . '" />';} // end whileif (stristr($message, '<img')) {if ($strip_img) {$message = trim(strip_tags($message));$ret .= '<input type="submit"' . $submit_name . ' '. implode(' ', $tag_params_strings). ' value="' . htmlspecialchars($message) . '" />';} else {$ret .= '<input type="image"' . $submit_name . ' '. implode(' ', $tag_params_strings). ' src="' . preg_replace('/^.*\ssrc="([^"]*)".*$/si', '\1', $message) . '"'. ' value="' . htmlspecialchars(preg_replace('/^.*\salt="([^"]*)".*$/si', '\1',$message)). '" />';}} else {$message = trim(strip_tags($message));$ret .= '<input type="submit"' . $submit_name . ' '. implode(' ', $tag_params_strings). ' value="' . htmlspecialchars($message) . '" />';}if ($new_form) {$ret .= '</form>';}} // end if... else...return $ret;} // end of the 'PMA_linkOrButton()' function/*** Returns a given timespan value in a readable format.** @param int the timespan** @return string the formatted value*/function PMA_timespanFormat($seconds){$return_string = '';$days = floor($seconds / 86400);if ($days > 0) {$seconds -= $days * 86400;}$hours = floor($seconds / 3600);if ($days > 0 || $hours > 0) {$seconds -= $hours * 3600;}$minutes = floor($seconds / 60);if ($days > 0 || $hours > 0 || $minutes > 0) {$seconds -= $minutes * 60;}return sprintf($GLOBALS['timespanfmt'], (string)$days, (string)$hours, (string)$minutes, (string)$seconds);}/*** Takes a string and outputs each character on a line for itself. Used* mainly for horizontalflipped display mode.* Takes care of special html-characters.* Fulfills todo-item* http://sf.net/tracker/?func=detail&aid=544361&group_id=23067&atid=377411** @param string The string* @param string The Separator (defaults to "<br />\n")** @access public* @author Garvin Hicking <me@supergarv.de>* @return string The flipped string*/function PMA_flipstring($string, $Separator = "<br />\n"){$format_string = '';$charbuff = false;for ($i = 0; $i < strlen($string); $i++) {$char = $string{$i};$append = false;if ($char == '&') {$format_string .= $charbuff;$charbuff = $char;$append = true;} elseif (!empty($charbuff)) {$charbuff .= $char;} elseif ($char == ';' && !empty($charbuff)) {$format_string .= $charbuff;$charbuff = false;$append = true;} else {$format_string .= $char;$append = true;}if ($append && ($i != strlen($string))) {$format_string .= $Separator;}}return $format_string;}/*** Function added to avoid path disclosures.* Called by each script that needs parameters, it displays* an error message and, by default, stops the execution.** Not sure we could use a strMissingParameter message here,* would have to check if the error message file is always available** @param array The names of the parameters needed by the calling* script.* @param boolean Stop the execution?* (Set this manually to false in the calling script* until you know all needed parameters to check).* @param boolean Whether to include this list in checking for special params.* @global string path to current script* @global boolean flag whether any special variable was required** @access public* @author Marc Delisle (lem9@users.sourceforge.net)*/function PMA_checkParameters($params, $die = true, $request = true){global $PHP_SELF, $checked_special;if (!isset($checked_special)) {$checked_special = false;}$reported_script_name = basename($PHP_SELF);$found_error = false;$error_message = '';foreach ($params AS $param) {if ($request && $param != 'db' && $param != 'table') {$checked_special = true;}if (!isset($GLOBALS[$param])) {$error_message .= $reported_script_name . ': Missing parameter: ' . $param . ' <a href="./Documentation.html#faqmissingparameters" target="documentation"> (FAQ 2.8)</a><br />';$found_error = true;}}if ($found_error) {require_once './libraries/header_meta_style.inc.php';echo '</head><body><p>' . $error_message . '</p></body></html>';if ($die) {exit();}}} // end function/*** Function to generate unique condition for specified row.** @param resource handle for current query* @param integer number of fields* @param array meta information about fields* @param array current row** @access public* @author Michal Cihar (michal@cihar.com)* @return string calculated condition*/function PMA_getUvaCondition($handle, $fields_cnt, $fields_meta, $row){$primary_key = '';$unique_key = '';$uva_nonprimary_condition = '';for ($i = 0; $i < $fields_cnt; ++$i) {$field_flags = PMA_DBI_field_flags($handle, $i);$meta = $fields_meta[$i];// do not use an alias in a condition$column_for_condition = $meta->name;if (isset($analyzed_sql[0]['select_expr']) && is_array($analyzed_sql[0]['select_expr'])) {foreach ($analyzed_sql[0]['select_expr'] AS $select_expr_position => $select_expr) {$alias = $analyzed_sql[0]['select_expr'][$select_expr_position]['alias'];if (strlen($alias)) {$true_column = $analyzed_sql[0]['select_expr'][$select_expr_position]['column'];if ($alias == $meta->name) {$column_for_condition = $true_column;} // end if} // end if} // end while}// to fix the bug where float fields (primary or not)// can't be matched because of the imprecision of// floating comparison, use CONCAT// (also, the syntax "CONCAT(field) IS NULL"// that we need on the next "if" will work)if ($meta->type == 'real') {$condition = ' CONCAT(' . PMA_backquote($column_for_condition) . ') ';} else {// string and blob fields have to be converted using// the system character set (always utf8) since// mysql4.1 can use different charset for fields.if (PMA_MYSQL_INT_VERSION >= 40100 && ($meta->type == 'string' || $meta->type == 'blob')) {$condition = ' CONVERT(' . PMA_backquote($column_for_condition) . ' USING utf8) ';} else {$condition = ' ' . PMA_backquote($column_for_condition) . ' ';}} // end if... else...if (!isset($row[$i]) || is_null($row[$i])) {$condition .= 'IS NULL AND';} else {// timestamp is numeric on some MySQL 4.1if ($meta->numeric && $meta->type != 'timestamp') {$condition .= '= ' . $row[$i] . ' AND';} elseif ($meta->type == 'blob'// hexify only if this is a true not empty BLOB&& stristr($field_flags, 'BINARY')&& !empty($row[$i])) {// use a CAST if possible, to avoid problems// if the field contains wildcard characters % or _if (PMA_MYSQL_INT_VERSION < 40002) {$condition .= 'LIKE 0x' . bin2hex($row[$i]). ' AND';} else {$condition .= '= CAST(0x' . bin2hex($row[$i]). ' AS BINARY) AND';}} else {$condition .= '= \'' . PMA_sqlAddslashes($row[$i], false, true) . '\' AND';}}if ($meta->primary_key > 0) {$primary_key .= $condition;} elseif ($meta->unique_key > 0) {$unique_key .= $condition;}$uva_nonprimary_condition .= $condition;} // end for// Correction uva 19991216: prefer primary or unique keys// for condition, but use conjunction of all values if no// primary keyif ($primary_key) {$uva_condition = $primary_key;} elseif ($unique_key) {$uva_condition = $unique_key;} else {$uva_condition = $uva_nonprimary_condition;}return preg_replace('|\s?AND$|', '', $uva_condition);} // end function/*** Function to generate unique condition for specified row.** @param string name of button element* @param string class of button element* @param string name of image element* @param string text to display* @param string image to display** @access public* @author Michal Cihar (michal@cihar.com)*/function PMA_buttonOrImage($button_name, $button_class, $image_name, $text,$image){global $pmaThemeImage, $propicon;/* Opera has trouble with <input type="image"> *//* IE has trouble with <button> */if (PMA_USR_BROWSER_AGENT != 'IE') {echo '<button class="' . $button_class . '" type="submit"'.' name="' . $button_name . '" value="' . $text . '"'.' title="' . $text . '">' . "\n".'<img class="icon" src="' . $pmaThemeImage . $image . '"'.' title="' . $text . '" alt="' . $text . '" width="16"'.' height="16" />'.($propicon == 'both' ? ' ' . $text : '') . "\n".'</button>' . "\n";} else {echo '<input type="image" name="' . $image_name . '" value="'. $text . '" title="' . $text . '" src="' . $pmaThemeImage. $image . '" />'. ($propicon == 'both' ? ' ' . $text : '') . "\n";}} // end function/*** Generate a pagination selector for browsing resultsets** @param string URL for the JavaScript* @param string Number of rows in the pagination set* @param string current page number* @param string number of total pages* @param string If the number of pages is lower than this* variable, no pages will be ommitted in* pagination* @param string How many rows at the beginning should always* be shown?* @param string How many rows at the end should always* be shown?* @param string Percentage of calculation page offsets to* hop to a next page* @param string Near the current page, how many pages should* be considered "nearby" and displayed as* well?** @access public* @author Garvin Hicking (pma@supergarv.de)*/function PMA_pageselector($url, $rows, $pageNow = 1, $nbTotalPage = 1,$showAll = 200, $sliceStart = 5, $sliceEnd = 5, $percent = 20,$range = 10){$gotopage = $GLOBALS['strPageNumber']. ' <select name="goToPage" onchange="goToUrl(this, \''. $url . '\');">' . "\n";if ($nbTotalPage < $showAll) {$pages = range(1, $nbTotalPage);} else {$pages = array();// Always show first X pagesfor ($i = 1; $i <= $sliceStart; $i++) {$pages[] = $i;}// Always show last X pagesfor ($i = $nbTotalPage - $sliceEnd; $i <= $nbTotalPage; $i++) {$pages[] = $i;}// garvin: Based on the number of results we add the specified// $percent percentate to each page number,// so that we have a representing page number every now and then to// immideately jump to specific pages.// As soon as we get near our currently chosen page ($pageNow -// $range), every page number will be// shown.$i = $sliceStart;$x = $nbTotalPage - $sliceEnd;$met_boundary = false;while ($i <= $x) {if ($i >= ($pageNow - $range) && $i <= ($pageNow + $range)) {// If our pageselector comes near the current page, we use 1// counter increments$i++;$met_boundary = true;} else {// We add the percentate increment to our current page to// hop to the next one in range$i = $i + floor($nbTotalPage / $percent);// Make sure that we do not cross our boundaries.if ($i > ($pageNow - $range) && !$met_boundary) {$i = $pageNow - $range;}}if ($i > 0 && $i <= $x) {$pages[] = $i;}}// Since because of ellipsing of the current page some numbers may be double,// we unify our array:sort($pages);$pages = array_unique($pages);}foreach ($pages AS $i) {if ($i == $pageNow) {$selected = 'selected="selected" style="font-weight: bold"';} else {$selected = '';}$gotopage .= ' <option ' . $selected . ' value="' . (($i - 1) * $rows) . '">' . $i . '</option>' . "\n";}$gotopage .= ' </select>';return $gotopage;} // end function/*** @TODO add documentation*/function PMA_generateFieldSpec($name, $type, $length, $attribute,$collation, $null, $default, $default_current_timestamp, $extra,$comment='', &$field_primary, $index, $default_orig = false){// $default_current_timestamp has priority over $default// TODO: on the interface, some js to clear the default value// when the default current_timestamp is checked$query = PMA_backquote($name) . ' ' . $type;if ($length != ''&& !preg_match('@^(DATE|DATETIME|TIME|TINYBLOB|TINYTEXT|BLOB|TEXT|MEDIUMBLOB|MEDIUMTEXT|LONGBLOB|LONGTEXT)$@i', $type)) {$query .= '(' . $length . ')';}if ($attribute != '') {$query .= ' ' . $attribute;}if (PMA_MYSQL_INT_VERSION >= 40100 && !empty($collation)&& $collation != 'NULL'&& preg_match('@^(TINYTEXT|TEXT|MEDIUMTEXT|LONGTEXT|VARCHAR|CHAR|ENUM|SET)$@i', $type)) {$query .= PMA_generateCharsetQueryPart($collation);}if (!($null === false)) {if (!empty($null)) {$query .= ' NOT NULL';} else {$query .= ' NULL';}}if ($default_current_timestamp && strpos(' ' . strtoupper($type), 'TIMESTAMP') == 1) {$query .= ' DEFAULT CURRENT_TIMESTAMP';// 0 is empty in PHP// auto_increment field cannot have a default value} elseif ($extra !== 'AUTO_INCREMENT' && (!empty($default) || $default == '0' || $default != $default_orig)) {if (strtoupper($default) == 'NULL') {$query .= ' DEFAULT NULL';} else {if (!empty($default) || $default == '0') {$query .= ' DEFAULT \'' . PMA_sqlAddslashes($default) . '\'';}}}if (!empty($extra)) {$query .= ' ' . $extra;// An auto_increment field must be use as a primary keyif ($extra == 'AUTO_INCREMENT' && isset($field_primary)) {$primary_cnt = count($field_primary);for ($j = 0; $j < $primary_cnt && $field_primary[$j] != $index; $j++) {// void} // end forif (isset($field_primary[$j]) && $field_primary[$j] == $index) {$query .= ' PRIMARY KEY';unset($field_primary[$j]);} // end if} // end if (auto_increment)}if (PMA_MYSQL_INT_VERSION >= 40100 && !empty($comment)) {$query .= " COMMENT '" . PMA_sqlAddslashes($comment) . "'";}return $query;} // end function/*** @TODO add documentation*/function PMA_generateAlterTable($oldcol, $newcol, $type, $length,$attribute, $collation, $null, $default, $default_current_timestamp,$extra, $comment='', $default_orig){$empty_a = array();return PMA_backquote($oldcol) . ' '. PMA_generateFieldSpec($newcol, $type, $length, $attribute,$collation, $null, $default, $default_current_timestamp, $extra,$comment, $empty_a, -1, $default_orig);} // end function/*** @TODO add documentation*/function PMA_userDir($dir){global $cfg;if (substr($dir, -1) != '/') {$dir .= '/';}return str_replace('%u', $cfg['Server']['user'], $dir);}/*** returns html code for db link to default db page** @uses $GLOBALS['cfg']['DefaultTabDatabase']* @uses $GLOBALS['db']* @uses $GLOBALS['strJumpToDB']* @uses PMA_generate_common_url()* @param string $database* @return string html link to default db page*/function PMA_getDbLink($database = null){if (!strlen($database)) {if (!strlen($GLOBALS['db'])) {return '';}$database = $GLOBALS['db'];}return '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($database) . '"'.' title="' . sprintf($GLOBALS['strJumpToDB'], htmlspecialchars($database)) . '">'.htmlspecialchars($database) . '</a>';}/*** removes cookie** @uses $GLOBALS['cookie_path']* @uses $GLOBALS['is_https']* @uses setcookie()* @uses time()* @param string $cookie name of cookie to remove* @return boolean result of setcookie()*/function PMA_removeCookie($cookie){return setcookie($cookie, '', time() - 3600,$GLOBALS['cookie_path'], '', $GLOBALS['is_https']);}/*** sets cookie if value is different from current cokkie value,* or removes if value is equal to default** @uses $GLOBALS['cookie_path']* @uses $GLOBALS['is_https']* @uses $_COOKIE* @uses PMA_removeCookie()* @uses setcookie()* @uses time()* @param string $cookie name of cookie to remove* @param mixed $value new cookie value* @param string $default default value* @return boolean result of setcookie()*/function PMA_setCookie($cookie, $value, $default = null){if (strlen($value) && null !== $default && $value === $default) {// remove cookie, default value is usedreturn PMA_removeCookie($cookie);}if (! strlen($value) && isset($_COOKIE[$cookie])) {// remove cookie, value is emptyreturn PMA_removeCookie($cookie);}if (! isset($_COOKIE[$cookie]) || $_COOKIE[$cookie] !== $value) {// set cookie with new valuereturn setcookie($cookie, $value, time() + 60*60*24*30,$GLOBALS['cookie_path'], '', $GLOBALS['is_https']);}// cookie has already $value as valuereturn true;}/*** include here only libraries which contain only function definitions* no code im main()!*//*** Include URL/hidden inputs generating.*/require_once './libraries/url_generating.lib.php';}/******************************************************************************//* start procedural code label_start_procedural *//*** protect against older PHP versions' bug about GLOBALS overwrite* (no need to localize this message :))* but what if script.php?GLOBALS[admin]=1&GLOBALS[_REQUEST]=1 ???*/if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS'])|| isset($_SERVER['GLOBALS']) || isset($_COOKIE['GLOBALS'])|| isset($_ENV['GLOBALS'])) {die('GLOBALS overwrite attempt');}/*** just to be sure there was no import (registering) before here* we empty the global space*/$variables_whitelist = array ('GLOBALS','_SERVER','_GET','_POST','_REQUEST','_FILES','_ENV','_COOKIE','_SESSION',);foreach (get_defined_vars() as $key => $value) {if (!in_array($key, $variables_whitelist)) {unset($$key);}}unset($key, $value);/*** check if a subform is submitted*/$__redirect = null;if (isset($_POST['usesubform'])) {// if a subform is present and should be used// the rest of the form is deprecated$subform_id = key($_POST['usesubform']);$subform = $_POST['subform'][$subform_id];$_POST = $subform;$_REQUEST = $subform;if (isset($_POST['redirect'])&& $_POST['redirect'] != basename(PMA_getenv('PHP_SELF'))) {$__redirect = $_POST['redirect'];unset($_POST['redirect']);} // end if (isset($_POST['redirect']))unset($subform_id, $subform);} // end if (isset($_POST['usesubform']))// end check if a subform is submittedif (get_magic_quotes_gpc()) {PMA_arrayWalkRecursive($_GET, 'stripslashes', true);PMA_arrayWalkRecursive($_POST, 'stripslashes', true);PMA_arrayWalkRecursive($_COOKIE, 'stripslashes', true);PMA_arrayWalkRecursive($_REQUEST, 'stripslashes', true);}require_once './libraries/session.inc.php';/*** include deprecated grab_globals only if required*/if (empty($__redirect) && !defined('PMA_NO_VARIABLES_IMPORT')) {require './libraries/grab_globals.lib.php';}/*** init some variables LABEL_variables_init*//*** @var array $GLOBALS['PMA_errors'] holds errors*/$GLOBALS['PMA_errors'] = array();/*** @var array $GLOBALS['url_params'] holds params to be passed to next page*/$GLOBALS['url_params'] = array();/*** @var array whitelist for $goto*/$goto_whitelist = array(//'browse_foreigners.php',//'calendar.php',//'changelog.php',//'chk_rel.php','db_create.php','db_datadict.php','db_details.php','db_details_export.php','db_details_importdocsql.php','db_details_qbe.php','db_details_structure.php','db_import.php','db_operations.php','db_printview.php','db_search.php',//'Documentation.html',//'error.php','export.php','import.php',//'index.php',//'left.php',//'license.php','main.php','pdf_pages.php','pdf_schema.php',//'phpinfo.php','querywindow.php',//'readme.php','server_binlog.php','server_collations.php','server_databases.php','server_engines.php','server_export.php','server_import.php','server_privileges.php','server_processlist.php','server_sql.php','server_status.php','server_variables.php','sql.php','tbl_addfield.php','tbl_alter.php','tbl_change.php','tbl_create.php','tbl_import.php','tbl_indexes.php','tbl_move_copy.php','tbl_printview.php','tbl_properties.php','tbl_properties_export.php','tbl_properties_operations.php','tbl_properties_structure.php','tbl_relation.php','tbl_replace.php','tbl_row_action.php','tbl_select.php',//'themes.php','transformation_overview.php','transformation_wrapper.php','translators.html','user_password.php',);/*** check $__redirect against whitelist*/if (! PMA_checkPageValidity($__redirect, $goto_whitelist)) {$__redirect = null;}/*** @var string $goto holds page that should be displayed*/// Security fix: disallow accessing serious server files via "?goto="if (PMA_checkPageValidity($_REQUEST['goto'], $goto_whitelist)) {$GLOBALS['goto'] = $_REQUEST['goto'];$GLOBALS['url_params']['goto'] = $_REQUEST['goto'];} else {unset($_REQUEST['goto'], $_GET['goto'], $_POST['goto'], $_COOKIE['goto']);$GLOBALS['goto'] = '';}/*** @var string $back returning page*/if (PMA_checkPageValidity($_REQUEST['back'], $goto_whitelist)) {$GLOBALS['back'] = $_REQUEST['back'];} else {unset($_REQUEST['back'], $_GET['back'], $_POST['back'], $_COOKIE['back']);}/*** Check whether user supplied token is valid, if not remove any* possibly dangerous stuff from request.*/if (!isset($_REQUEST['token']) || $_SESSION['PMA_token'] != $_REQUEST['token']) {/* List of parameters which are allowed from unsafe source */$allow_list = array('db', 'table', 'lang', 'server', 'convcharset', 'collation_connection', 'target',/* Session ID */'phpMyAdmin',/* Cookie preferences */'pma_lang', 'pma_charset', 'pma_collation_connection', 'pma_convcharset',/* Possible login form */'pma_username', 'pma_password',);$keys = array_keys($_REQUEST);/* Remove any non allowed stuff from requests */foreach($keys as $key) {if (!in_array($key, $allow_list)) {unset($_REQUEST[$key]);unset($_GET[$key]);unset($_POST[$key]);unset($GLOBALS[$key]);} else {// allowed stuff could be compromised so escape it$_REQUEST[$key] = htmlspecialchars($_REQUEST[$key], ENT_QUOTES);}}}/*** @var string $convcharset* @see also select_lang.lib.php*/if (isset($_REQUEST['convcharset'])) {$convcharset = strip_tags($_REQUEST['convcharset']);}/*** @var string $db current selected database*/if (isset($_REQUEST['db'])) {// can we strip tags from this?// only \ and / is not allowed in db names for MySQL$GLOBALS['db'] = $_REQUEST['db'];$GLOBALS['url_params']['db'] = $GLOBALS['db'];} else {$GLOBALS['db'] = '';}/*** @var string $db current selected database*/if (isset($_REQUEST['table'])) {// can we strip tags from this?// only \ and / is not allowed in table names for MySQL$GLOBALS['table'] = $_REQUEST['table'];$GLOBALS['url_params']['table'] = $GLOBALS['table'];} else {$GLOBALS['table'] = '';}/*** @var string $sql_query sql query to be executed*/if (isset($_REQUEST['sql_query'])) {$GLOBALS['sql_query'] = $_REQUEST['sql_query'];}//$_REQUEST['set_theme'] // checked later in this file LABEL_theme_setup//$_REQUEST['server']; // checked later in this file//$_REQUEST['lang']; // checked by LABEL_loading_language_file/******************************************************************************//* parsing config file LABEL_parsing_config_file */if (empty($_SESSION['PMA_Config'])) {/*** We really need this one!*/if (!function_exists('preg_replace')) {header('Location: error.php'. '?lang=' . urlencode($available_languages[$lang][2]). '&char=' . urlencode($charset). '&dir=' . urlencode($text_dir). '&type=' . urlencode($strError). '&error=' . urlencode(strtr(sprintf($strCantLoad, 'pcre'),array('<br />' => '[br]'))). '&' . SID);exit();}$_SESSION['PMA_Config'] = new PMA_Config('./config.inc.php');} elseif (version_compare(phpversion(), '5', 'lt')) {$_SESSION['PMA_Config']->__wakeup();}if (!defined('PMA_MINIMUM_COMMON')) {$_SESSION['PMA_Config']->checkPmaAbsoluteUri();}// BC$_SESSION['PMA_Config']->enableBc();/*** check https connection*/if ($_SESSION['PMA_Config']->get('ForceSSL')&& !$_SESSION['PMA_Config']->get('is_https')) {PMA_sendHeaderLocation(preg_replace('/^http/', 'https',$_SESSION['PMA_Config']->get('PmaAbsoluteUri')). PMA_generate_common_url($_GET));exit;}/******************************************************************************//* loading language file LABEL_loading_language_file *//*** Added messages while developing:*/if (file_exists('./lang/added_messages.php')) {include './lang/added_messages.php';}/*** Includes the language file if it hasn't been included yet*/require_once './libraries/select_lang.lib.php';/*** check for errors occured while loading config*/if ($_SESSION['PMA_Config']->error_config_file) {$GLOBALS['PMA_errors'][] = $strConfigFileError.'<br /><br />'.'<a href="' . $_SESSION['PMA_Config']->getSource() . '"'.' target="_blank">' . $_SESSION['PMA_Config']->getSource() . '</a>';}if ($_SESSION['PMA_Config']->error_config_default_file) {$GLOBALS['PMA_errors'][] = sprintf($strConfigDefaultFileError,$_SESSION['PMA_Config']->default_source);}if ($_SESSION['PMA_Config']->error_pma_uri) {$GLOBALS['PMA_errors'][] = sprintf($strPmaUriError);}/*** Servers array fixups.* $default_server comes from PMA_Config::enableBc()* @todo merge into PMA_Config*/// Do we have some server?if (!isset($cfg['Servers']) || count($cfg['Servers']) == 0) {// No server => create one with defaults$cfg['Servers'] = array(1 => $default_server);} else {// We have server(s) => apply default config$new_servers = array();foreach ($cfg['Servers'] as $server_index => $each_server) {if (!is_int($server_index) || $server_index < 1) {$GLOBALS['PMA_errors'][] = sprintf($strInvalidServerIndex, $server_index);continue;}$each_server = array_merge($default_server, $each_server);// Don't use servers with no hostnameif ($each_server['connect_type'] == 'tcp' && empty($each_server['host'])) {$GLOBALS['PMA_errors'][] = sprintf($strInvalidServerHostname, $server_index);continue;}// Final solution to bug #582890// If we are using a socket connection// and there is nothing in the verbose server name// or the host field, then generate a name for the server// in the form of "Server 2", localized of course!if ($each_server['connect_type'] == 'socket' && empty($each_server['host']) && empty($each_server['verbose'])) {$each_server['verbose'] = $GLOBALS['strServer'] . $server_index;}$new_servers[$server_index] = $each_server;}$cfg['Servers'] = $new_servers;unset($new_servers, $server_index, $each_server);}// Cleanupunset($default_server);/******************************************************************************//* setup themes LABEL_theme_setup */if (!isset($_SESSION['PMA_Theme_Manager'])) {$_SESSION['PMA_Theme_Manager'] = new PMA_Theme_Manager;} else {$_SESSION['PMA_Theme_Manager']->checkConfig();}if (isset($_REQUEST['set_theme'])) {// if user submit a theme$_SESSION['PMA_Theme_Manager']->setActiveTheme($_REQUEST['set_theme']);}$_SESSION['PMA_Theme'] = $_SESSION['PMA_Theme_Manager']->theme;// BC$GLOBALS['theme'] = $_SESSION['PMA_Theme']->getName();$GLOBALS['pmaThemePath'] = $_SESSION['PMA_Theme']->getPath();$GLOBALS['pmaThemeImage'] = $_SESSION['PMA_Theme']->getImgPath();/*** load layout file if exists*/if (@file_exists($_SESSION['PMA_Theme']->getLayoutFile())) {include $_SESSION['PMA_Theme']->getLayoutFile();}if (!defined('PMA_MINIMUM_COMMON')) {/*** Charset conversion.*/require_once './libraries/charset_conversion.lib.php';/*** String handling*/require_once './libraries/string.lib.php';/*** @var array database list*/$dblist = array();/*** If no server is selected, make sure that $cfg['Server'] is empty (so* that nothing will work), and skip server authentication.* We do NOT exit here, but continue on without logging into any server.* This way, the welcome page will still come up (with no server info) and* present a choice of servers in the case that there are multiple servers* and '$cfg['ServerDefault'] = 0' is set.*/if (!empty($_REQUEST['server']) && !empty($cfg['Servers'][$_REQUEST['server']])) {$GLOBALS['server'] = $_REQUEST['server'];$cfg['Server'] = $cfg['Servers'][$GLOBALS['server']];} else {if (!empty($cfg['Servers'][$cfg['ServerDefault']])) {$GLOBALS['server'] = $cfg['ServerDefault'];$cfg['Server'] = $cfg['Servers'][$GLOBALS['server']];} else {$GLOBALS['server'] = 0;$cfg['Server'] = array();}}$GLOBALS['url_params']['server'] = $GLOBALS['server'];if (!empty($cfg['Server'])) {/*** Loads the proper database interface for this server*/require_once './libraries/database_interface.lib.php';// Gets the authentication library that fits the $cfg['Server'] settings// and run authentication// (for a quick check of path disclosure in auth/cookies:)$coming_from_common = true;if (!file_exists('./libraries/auth/' . $cfg['Server']['auth_type'] . '.auth.lib.php')) {header('Location: error.php'. '?lang=' . urlencode($available_languages[$lang][2]). '&char=' . urlencode($charset). '&dir=' . urlencode($text_dir). '&type=' . urlencode($strError). '&error=' . urlencode($strInvalidAuthMethod . ' '. $cfg['Server']['auth_type']). '&' . SID);exit();}require_once './libraries/auth/' . $cfg['Server']['auth_type'] . '.auth.lib.php';if (!PMA_auth_check()) {PMA_auth();} else {PMA_auth_set_user();}// Check IP-based Allow/Deny rules as soon as possible to reject the// user// Based on mod_access in Apache:// http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/aaa/mod_access.c?rev=1.37&content-type=text/vnd.viewcvs-markup// Look at: "static int check_dir_access(request_rec *r)"// Robbat2 - May 10, 2002if (isset($cfg['Server']['AllowDeny'])&& isset($cfg['Server']['AllowDeny']['order'])) {require_once './libraries/ip_allow_deny.lib.php';$allowDeny_forbidden = false; // defaultif ($cfg['Server']['AllowDeny']['order'] == 'allow,deny') {$allowDeny_forbidden = true;if (PMA_allowDeny('allow')) {$allowDeny_forbidden = false;}if (PMA_allowDeny('deny')) {$allowDeny_forbidden = true;}} elseif ($cfg['Server']['AllowDeny']['order'] == 'deny,allow') {if (PMA_allowDeny('deny')) {$allowDeny_forbidden = true;}if (PMA_allowDeny('allow')) {$allowDeny_forbidden = false;}} elseif ($cfg['Server']['AllowDeny']['order'] == 'explicit') {if (PMA_allowDeny('allow')&& !PMA_allowDeny('deny')) {$allowDeny_forbidden = false;} else {$allowDeny_forbidden = true;}} // end if ... elseif ... elseif// Ejects the user if banishedif ($allowDeny_forbidden) {PMA_auth_fails();}unset($allowDeny_forbidden); //Clean up after you!} // end if// is root allowed?if (!$cfg['Server']['AllowRoot'] && $cfg['Server']['user'] == 'root') {$allowDeny_forbidden = true;PMA_auth_fails();unset($allowDeny_forbidden); //Clean up after you!}// The user can work with only some databasesif (isset($cfg['Server']['only_db']) && $cfg['Server']['only_db'] != '') {if (is_array($cfg['Server']['only_db'])) {$dblist = $cfg['Server']['only_db'];} else {$dblist[] = $cfg['Server']['only_db'];}} // end if$bkp_track_err = @ini_set('track_errors', 1);// Try to connect MySQL with the control user profile (will be used to// get the privileges list for the current user but the true user link// must be open after this one so it would be default one for all the// scripts)if ($cfg['Server']['controluser'] != '') {$controllink = PMA_DBI_connect($cfg['Server']['controluser'],$cfg['Server']['controlpass'], true);} else {$controllink = PMA_DBI_connect($cfg['Server']['user'],$cfg['Server']['password'], true);} // end if ... else// Pass #1 of DB-Config to read in master level DB-Config will go here// Robbat2 - May 11, 2002// Connects to the server (validates user's login)$userlink = PMA_DBI_connect($cfg['Server']['user'],$cfg['Server']['password'], false);// Pass #2 of DB-Config to read in user level DB-Config will go here// Robbat2 - May 11, 2002@ini_set('track_errors', $bkp_track_err);unset($bkp_track_err);/*** SQL Parser code*/require_once './libraries/sqlparser.lib.php';/*** SQL Validator interface code*/require_once './libraries/sqlvalidator.lib.php';// if 'only_db' is set for the current user, there is no need to check for// available databases in the "mysql" db$dblist_cnt = count($dblist);if ($dblist_cnt) {$true_dblist = array();$is_show_dbs = true;$dblist_asterisk_bool = false;for ($i = 0; $i < $dblist_cnt; $i++) {// The current positionif ($dblist[$i] == '*' && $dblist_asterisk_bool == false) {$dblist_asterisk_bool = true;$dblist_full = PMA_safe_db_list(false, $controllink, false,$userlink, $cfg, $dblist);foreach ($dblist_full as $dbl_val) {if (!in_array($dbl_val, $dblist)) {$true_dblist[] = $dbl_val;}}continue;} elseif ($dblist[$i] == '*') {// We don't want more than one asterisk inside our 'only_db'.continue;}if ($is_show_dbs && preg_match('/(^|[^\\\\])(_|%)/', $dblist[$i])) {$local_query = 'SHOW DATABASES LIKE \'' . $dblist[$i] . '\'';// here, a PMA_DBI_query() could fail silently// if SHOW DATABASES is disabled$rs = PMA_DBI_try_query($local_query, $userlink);if ($i == 0 && ! $rs) {$error_code = substr(PMA_DBI_getError($userlink), 1, 4);if ($error_code == 1227 || $error_code == 1045) {// "SHOW DATABASES" statement is disabled or not allowed to user$true_dblist[] = str_replace('\\_', '_', str_replace('\\%', '%', $dblist[$i]));$is_show_dbs = false;}unset($error_code);}// Debug// elseif (PMA_DBI_getError($controllink)) {// PMA_mysqlDie(PMA_DBI_getError($controllink), $local_query, false);// }while ($row = @PMA_DBI_fetch_row($rs)) {$true_dblist[] = $row[0];} // end whileif ($rs) {PMA_DBI_free_result($rs);}} else {$true_dblist[] = str_replace('\\_', '_',str_replace('\\%', '%', $dblist[$i]));} // end if... else...} // end for$dblist = $true_dblist;unset($true_dblist, $i, $dbl_val);$only_db_check = true;} // end if// 'only_db' is empty for the current user...else {$only_db_check = false;} // end if (!$dblist_cnt)if (isset($dblist_full) && !count($dblist_full)) {$dblist = PMA_safe_db_list($only_db_check, $controllink,$dblist_cnt, $userlink, $cfg, $dblist);}unset($only_db_check, $dblist_full);} // end server connecting// Kanji encoding convert feature appended by Y.Kawada (2002/2/20)if (@function_exists('mb_convert_encoding')&& strpos(' ' . $lang, 'ja-')&& file_exists('./libraries/kanji-encoding.lib.php')) {require_once './libraries/kanji-encoding.lib.php';define('PMA_MULTIBYTE_ENCODING', 1);} // end if/*** save some settings in cookies*/PMA_setCookie('pma_lang', $GLOBALS['lang']);PMA_setCookie('pma_charset', $GLOBALS['convcharset']);PMA_setCookie('pma_collation_connection', $GLOBALS['collation_connection']);$_SESSION['PMA_Theme_Manager']->setThemeCookie();} // end if !defined('PMA_MINIMUM_COMMON')if (!empty($__redirect) && in_array($__redirect, $goto_whitelist)) {// to handle bug #1388167if (isset($_GET['is_js_confirmed'])) {$is_js_confirmed = 1;}require $__redirect;exit();}?>