Вход Регистрация
Файл: Tools/phpmyadmin/libraries/common.lib.php
Строк: 4040
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
 * Misc functions used all over the scripts.
 *
 * @package PhpMyAdmin
 */

/**
 * Detects which function to use for PMA_pow.
 *
 * @return string Function name.
 */
function PMA_detect_pow()
{
    if (
function_exists('bcpow')) {
        
// BCMath Arbitrary Precision Mathematics Function
        
return 'bcpow';
    } elseif (
function_exists('gmp_pow')) {
        
// GMP Function
        
return 'gmp_pow';
    } else {
        
// PHP function
        
return 'pow';
    }
}

/**
 * Exponential expression / raise number into power
 *
 * @param string $base         base to raise
 * @param string $exp          exponent to use
 * @param mixed  $use_function pow function to use, or false for auto-detect
 *
 * @return mixed string or float
 */
function PMA_pow($base$exp$use_function false)
{
    static 
$pow_function null;

    if (
null == $pow_function) {
        
$pow_function PMA_detect_pow();
    }

    if (! 
$use_function) {
        
$use_function $pow_function;
    }

    if (
$exp && 'pow' != $use_function) {
        return 
false;
    }
    switch (
$use_function) {
    case 
'bcpow' :
        
// bcscale() needed for testing PMA_pow() with base values < 1
        
bcscale(10);
        
$pow bcpow($base$exp);
        break;
    case 
'gmp_pow' :
         
$pow gmp_strval(gmp_pow($base$exp));
        break;
    case 
'pow' :
        
$base = (float) $base;
        
$exp = (int) $exp;
        
$pow pow($base$exp);
        break;
    default:
        
$pow $use_function($base$exp);
    }

    return 
$pow;
}

/**
 * Returns an HTML IMG tag for a particular icon from a theme,
 * which may be an actual file or an icon from a sprite.
 * This function takes into account the PropertiesIconic
 * configuration setting and wraps the image tag in a span tag.
 *
 * @param string  $icon       name of icon file
 * @param string  $alternate  alternate text
 * @param boolean $force_text whether to force alternate text to be displayed
 *
 * @return string an html snippet
 */
function PMA_getIcon($icon$alternate ''$force_text false)
{
    
// $cfg['PropertiesIconic'] is true or both
    
$include_icon = ($GLOBALS['cfg']['PropertiesIconic'] !== false);
    
// $cfg['PropertiesIconic'] is false or both
    // OR we have no $include_icon
    
$include_text = ($force_text || true !== $GLOBALS['cfg']['PropertiesIconic']);

    
// Always use a span (we rely on this in js/sql.js)
    
$button '<span class="nowrap">';
    if (
$include_icon) {
        
$button .= PMA_getImage($icon$alternate);
    }
    if (
$include_icon && $include_text) {
        
$button .= ' ';
    }
    if (
$include_text) {
        
$button .= $alternate;
    }
    
$button .= '</span>';

    return 
$button;
}

/**
 * Returns an HTML IMG tag for a particular image from a theme,
 * which may be an actual file or an icon from a sprite
 *
 * @param string $image      The name of the file to get
 * @param string $alternate  Used to set 'alt' and 'title' attributes of the image
 * @param array  $attributes An associative array of other attributes
 *
 * @return string an html IMG tag
 */
function PMA_getImage($image$alternate ''$attributes = array())
{
    static 
$sprites// cached list of available sprites (if any)

    
$url       '';
    
$is_sprite false;
    
$alternate htmlspecialchars($alternate);

    
// If it's the first time this function is called
    
if (! isset($sprites)) {
        
// Try to load the list of sprites
        
if (is_readable($_SESSION['PMA_Theme']->getPath() . '/sprites.lib.php')) {
            include_once 
$_SESSION['PMA_Theme']->getPath() . '/sprites.lib.php';
            
$sprites PMA_sprites();
        } else {
            
// No sprites are available for this theme
            
$sprites = array();
        }
    }
    
// Check if we have the requested image as a sprite
    //  and set $url accordingly
    
$class str_replace(array('.gif','.png'), ''$image);
    if (
array_key_exists($class$sprites)) {
        
$is_sprite true;
        
$url 'themes/dot.gif';
    } else {
        
$url $GLOBALS['pmaThemeImage'] . $image;
    }
    
// set class attribute
    
if ($is_sprite) {
        if (isset(
$attributes['class'])) {
            
$attributes['class'] = "icon ic_$class " $attributes['class'];
        } else {
            
$attributes['class'] = "icon ic_$class";
        }
    }
    
// set all other attributes
    
$attr_str '';
    foreach (
$attributes as $key => $value) {
        if (! 
in_array($key, array('alt''title'))) {
            
$attr_str .= $key="$value"";
        }
    }
    
// override the alt attribute
    
if (isset($attributes['alt'])) {
        
$alt $attributes['alt'];
    } else {
        
$alt $alternate;
    }
    
// override the title attribute
    
if (isset($attributes['title'])) {
        
$title $attributes['title'];
    } else {
        
$title $alternate;
    }
    
// generate the IMG tag
    
$template '<img src="%s" title="%s" alt="%s"%s />';
    
$retval sprintf($template$url$title$alt$attr_str);

    return 
$retval;
}

/**
 * Displays the maximum size for an upload
 *
 * @param integer $max_upload_size the size
 *
 * @return string the message
 *
 * @access  public
 */
function PMA_displayMaximumUploadSize($max_upload_size)
{
    
// I have to reduce the second parameter (sensitiveness) from 6 to 4
    // to avoid weird results like 512 kKib
    
list($max_size$max_unit) = PMA_formatByteDown($max_upload_size4);
    return 
'(' sprintf(__('Max: %s%s'), $max_size$max_unit) . ')';
}

/**
 * Generates a hidden field which should indicate to the browser
 * the maximum size for upload
 *
 * @param integer $max_size 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 $a_string the string to slash
 * @param bool   $is_like  whether the string will be used in a 'LIKE' clause
 *                         (it then requires two more escaped sequences) or not
 * @param bool   $crlf     whether to treat cr/lfs as escape-worthy entities
 *                         (converts n to \n, r to \r)
 * @param bool   $php_code 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 = strtr(
            $a_string,
            array("n" => '
n', "r" => 'r', "t" => 't')
        );
    }

    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 $name the string to escape
 *
 * @return string the escaped string
 *
 * @access  public
 */
function PMA_escape_mysql_wildcards($name)
{
    return strtr($name, array('
_' => '\_', '%' => '\%'));
} // 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)
{
    return strtr($name, array('
\_' => '_', '\%' => '%'));
} // end of the '
PMA_unescape_mysql_wildcards()' function

/**
 * removes quotes ('
,",`) from a quoted string
 *
 * checks if the sting is quoted and removes this quotes
 *
 * @param string 
$quoted_string string to remove quotes from
 * @param string 
$quote         type of quote to remove
 *
 * @return string unqoted string
 */
function PMA_unQuote(
$quoted_string$quote = null)
{
    
$quotes = array();

    if (null === 
$quote) {
        
$quotes[] = '`';
        
$quotes[] = '"';
        $quotes[] = "'";
    } else {
        
$quotes[] = $quote;
    }

    foreach (
$quotes as $quote) {
        if (substr(
$quoted_string, 0, 1) === $quote
            && substr(
$quoted_string, -1, 1) === $quote
        ) {
            
$unquoted_string = substr($quoted_string, 1, -1);
            // replace escaped quotes
            
$unquoted_string = str_replace(
                
$quote . $quote,
                
$quote,
                
$unquoted_string
            );
            return 
$unquoted_string;
        }
    }

    return 
$quoted_string;
}

/**
 * format sql strings
 *
 * @param mixed  
$parsed_sql   pre-parsed SQL structure
 * @param string 
$unparsed_sql raw SQL string
 *
 * @return string  the formatted sql
 *
 * @global  array    the configuration array
 * @global  boolean  whether the current statement is a multiple one or not
 *
 * @access  public
 * @todo    move into PMA_Sql
 */
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 error
    if (PMA_SQP_isError()) {
        return htmlspecialchars(
$parsed_sql['raw']);
    }
    // then check for an array
    if (! 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";
        if (
$cfg['SQP']['fmtType'] == 'none' && $unparsed_sql != '') {
            
$formatted_sql .= $unparsed_sql;
        } else {
            
$formatted_sql .= $parsed_sql;
        }
        
$formatted_sql .= "n</pre>";
        return 
$formatted_sql;
    }

    
$formatted_sql        = '';

    switch (
$cfg['SQP']['fmtType']) {
    case 'none':
        if (
$unparsed_sql != '') {
            
$formatted_sql = '<span class="inner_sql"><pre>' . "n"
                . PMA_SQP_formatNone(array('raw' => 
$unparsed_sql)) . "n"
                . '</pre></span>';
        } 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_formatHtml($parsed_sql, 'text');
        break;
    default:
        break;
    } // end switch

    return 
$formatted_sql;
} // end of the "
PMA_formatSql()" function


/**
 * Displays a link to the official MySQL documentation
 *
 * @param string 
$chapter   chapter of "HTMLone page per chapter" documentation
 * @param string 
$link      contains name of page/anchor that is being linked
 * @param bool   
$big_icon  whether to use big icon (like in left frame)
 * @param string 
$anchor    anchor to page part
 * @param bool   
$just_open whether only the opening <a> tag should be returned
 *
 * @return  string  the html link
 *
 * @access  public
 */
function PMA_showMySQLDocu(
$chapter$link$big_icon = false, $anchor = '', $just_open = 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';
        }
        if (empty(
$anchor)) {
            
$anchor = $link;
        }
        
$url = $cfg['MySQLManualBase'] . '/' . $chapter . '.html#' . $anchor;
        break;
    case 'big':
        if (empty(
$anchor)) {
            
$anchor = $link;
        }
        
$url = $cfg['MySQLManualBase'] . '#' . $anchor;
        break;
    case 'searchable':
        if (empty(
$link)) {
            
$link = 'index';
        }
        
$url = $cfg['MySQLManualBase'] . '/' . $link . '.html';
        if (!empty(
$anchor)) {
            
$url .= '#' . $anchor;
        }
        break;
    case 'viewable':
    default:
        if (empty(
$link)) {
            
$link = 'index';
        }
        
$mysql = '5.0';
        
$lang = 'en';
        if (defined('PMA_MYSQL_INT_VERSION')) {
            if (PMA_MYSQL_INT_VERSION >= 50500) {
                
$mysql = '5.5';
                /* l10n: Please check that translation actually exists. */
                
$lang = _pgettext('MySQL 5.5 documentation language', 'en');
            } else if (PMA_MYSQL_INT_VERSION >= 50100) {
                
$mysql = '5.1';
                /* l10n: Please check that translation actually exists. */
                
$lang = _pgettext('MySQL 5.1 documentation language', 'en');
            } else {
                
$mysql = '5.0';
                /* l10n: Please check that translation actually exists. */
                
$lang = _pgettext('MySQL 5.0 documentation language', 'en');
            }
        }
        
$url = $cfg['MySQLManualBase'] . '/' . $mysql . '/' . $lang . '/' . $link . '.html';
        if (!empty(
$anchor)) {
            
$url .= '#' . $anchor;
        }
        break;
    }

    
$open_link = '<a href="' . PMA_linkURL($url) . '" target="mysql_doc">';
    if (
$just_open) {
        return 
$open_link;
    } elseif (
$big_icon) {
        return 
$open_link . PMA_getImage('b_sqlhelp.png', __('Documentation')) . '</a>';
    } elseif (
$GLOBALS['cfg']['ReplaceHelpImg']) {
        return 
$open_link . PMA_getImage('b_help.png', __('Documentation')) . '</a>';
    } else {
        return '[' . 
$open_link . __('Documentation') . '</a>]';
    }
} // end of the 'PMA_showMySQLDocu()' function


/**
 * Displays a link to the phpMyAdmin documentation
 *
 * @param string 
$anchor anchor in documentation
 *
 * @return  string  the html link
 *
 * @access  public
 */
function PMA_showDocu(
$anchor)
{
    if (
$GLOBALS['cfg']['ReplaceHelpImg']) {
        return '<a href="
Documentation.html#' . $anchor . '" target="documentation">'
             
PMA_getImage('b_help.png'__('Documentation'))
             . 
'</a>';
    } else {
        return 
'[<a href="Documentation.html#' $anchor '" target="documentation">'
        
__('Documentation') . '</a>]';
    }
// end of the 'PMA_showDocu()' function

/**
 * Displays a link to the PHP documentation
 *
 * @param string $target anchor in documentation
 *
 * @return string  the html link
 *
 * @access  public
 */
function PMA_showPHPDocu($target)
{
    
$url PMA_getPHPDocLink($target);

    if (
$GLOBALS['cfg']['ReplaceHelpImg']) {
        return 
'<a href="' $url '" target="documentation">'
             
PMA_getImage('b_help.png'__('Documentation'))
             . 
'</a>';
    } else {
        return 
'[<a href="' $url '" target="documentation">' __('Documentation') . '</a>]';
    }
// end of the 'PMA_showPHPDocu()' function

/**
 * returns HTML for a footnote marker and add the messsage to the footnotes
 *
 * @param string $message the error message
 * @param bool   $bbcode
 * @param string $type    message types
 *
 * @return  string html code for a footnote marker
 *
 * @access  public
 */
function PMA_showHint($message$bbcode false$type 'notice')
{
    if (
$message instanceof PMA_Message) {
        
$key $message->getHash();
        
$type $message->getLevel();
    } else {
        
$key md5($message);
    }

    if (! isset(
$GLOBALS['footnotes'][$key])) {
        if (empty(
$GLOBALS['footnotes']) || ! is_array($GLOBALS['footnotes'])) {
            
$GLOBALS['footnotes'] = array();
        }
        
$nr count($GLOBALS['footnotes']) + 1;
        
$GLOBALS['footnotes'][$key] = array(
            
'note'      => $message,
            
'type'      => $type,
            
'nr'        => $nr,
        );
    } else {
        
$nr $GLOBALS['footnotes'][$key]['nr'];
    }

    if (
$bbcode) {
        return 
'[sup]' $nr '[/sup]';
    }

    
// footnotemarker used in js/tooltip.js
    
return '<sup class="footnotemarker">' $nr '</sup>' .
           
PMA_getImage('b_help.png''', array('class' => 'footnotemarker footnote_' $nr));
}

/**
 * Displays a MySQL error message in the right frame.
 *
 * @param string $error_message  the error message
 * @param string $the_query      the sql query that failed
 * @param bool   $is_modify_link whether to show a "modify" link or not
 * @param string $back_url       the "back" link url (full path is not required)
 * @param bool   $exit           EXIT the page?
 *
 * @global  string    the curent table
 * @global  string    the current db
 *
 * @access  public
 */
function PMA_mysqlDie($error_message ''$the_query '',
$is_modify_link true$back_url ''$exit true)
{
    global 
$table$db;

    
/**
     * start http output, display html headers
     */
    
include_once './libraries/header.inc.php';

    
$error_msg_output '';

    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
    
if (!function_exists('PMA_SQP_isError') || PMA_SQP_isError()) {
        
$formatted_sql htmlspecialchars($the_query);
    } elseif (empty(
$the_query) || trim($the_query) == '') {
        
$formatted_sql '';
    } else {
        if (
strlen($the_query) > $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) {
            
$formatted_sql htmlspecialchars(substr($the_query0$GLOBALS['cfg']['MaxCharactersInDisplayedSQL'])) . '[...]';
        } else {
            
$formatted_sql PMA_formatSql(PMA_SQP_parse($the_query), $the_query);
        }
    }
    
// ---
    
$error_msg_output .= "n" '<!-- PMA-SQL-ERROR -->' "n";
    
$error_msg_output .= '    <div class="error"><h1>' __('Error') . '</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/password
    
if (!empty($the_query) && !strstr($the_query'connect')) {
        
// --- Added to solve bug #641765
        
if (function_exists('PMA_SQP_isError') && PMA_SQP_isError()) {
            
$error_msg_output .= PMA_SQP_getErrorString() . "n";
            
$error_msg_output .= '<br />' "n";
        }
        
// ---
        // modified to show the help on sql errors
        
$error_msg_output .= '    <p><strong>' __('SQL query') . ':</strong>' "n";
        if (
strstr(strtolower($formatted_sql), 'select')) {
            
// please show me help to the error on select
            
$error_msg_output .= PMA_showMySQLDocu('SQL-Syntax''SELECT');
        }
        if (
$is_modify_link) {
            
$_url_params = array(
                
'sql_query' => $the_query,
                
'show_query' => 1,
            );
            if (
strlen($table)) {
                
$_url_params['db'] = $db;
                
$_url_params['table'] = $table;
                
$doedit_goto '<a href="tbl_sql.php' PMA_generate_common_url($_url_params) . '">';
            } elseif (
strlen($db)) {
                
$_url_params['db'] = $db;
                
$doedit_goto '<a href="db_sql.php' PMA_generate_common_url($_url_params) . '">';
            } else {
                
$doedit_goto '<a href="server_sql.php' PMA_generate_common_url($_url_params) . '">';
            }

            
$error_msg_output .= $doedit_goto
               
PMA_getIcon('b_edit.png'__('Edit'))
               . 
'</a>';
        } 
// end if
        
$error_msg_output .= '    </p>' "n"
            
.'    <p>' "n"
            
.'        ' $formatted_sql "n"
            
.'    </p>' "n";
    } 
// end if

    
if (! empty($error_message)) {
        
$error_message preg_replace(
            
"@((1512)|(15)|(12)){3,}@",
            
"nn",
            
$error_message
        
);
    }
    
// modified to show the help on error-returns
    // (now error-messages-server)
    
$error_msg_output .= '<p>' "n"
            
'    <strong>' __('MySQL said: ') . '</strong>'
            
PMA_showMySQLDocu('Error-messages-server''Error-messages-server')
            . 
"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('  ''&nbsp;&nbsp;'$error_message);
    
// Replace TAB-characters with their HTML-counterpart
    
$error_message str_replace("t"'&nbsp;&nbsp;&nbsp;&nbsp;'$error_message);
    
// Replace linebreaks
    
$error_message nl2br($error_message);

    
$error_msg_output .= '<code>' "n"
        
$error_message "n"
        
'</code><br />' "n";
    
$error_msg_output .= '</div>';

    
$_SESSION['Import_message']['message'] = $error_msg_output;

    if (
$exit) {
        
/**
         * If in an Ajax request
         * - avoid displaying a Back link
         * - use PMA_ajaxResponse() to transmit the message and exit
         */
        
if ($GLOBALS['is_ajax_request'] == true) {
            
PMA_ajaxResponse($error_msg_outputfalse);
        }
        if (! empty(
$back_url)) {
            if (
strstr($back_url'?')) {
                
$back_url .= '&amp;no_history=true';
            } else {
                
$back_url .= '?no_history=true';
            }

            
$_SESSION['Import_message']['go_back_url'] = $back_url;

            
$error_msg_output .= '<fieldset class="tblFooters">';
            
$error_msg_output .= '[ <a href="' $back_url '">' __('Back') . '</a> ]';
            
$error_msg_output .= '</fieldset>' "nn";
        }

        echo 
$error_msg_output;
        
/**
         * display footer and exit
         */
        
include './libraries/footer.inc.php';
    } else {
        echo 
$error_msg_output;
    }
// end of the 'PMA_mysqlDie()' function

/**
 * returns array with tables of given db with extended information and grouped
 *
 * @param string   $db           name of db
 * @param string   $tables       name of tables
 * @param integer  $limit_offset list offset
 * @param int|bool $limit_count  max tables to return
 *
 * @return  array    (recursive) grouped table list
 */
function PMA_getTableList($db$tables null$limit_offset 0$limit_count false)
{
    
$sep $GLOBALS['cfg']['LeftFrameTableSeparator'];

    if (
null === $tables) {
        
$tables PMA_DBI_get_tables_full($dbfalsefalsenull$limit_offset$limit_count);
        if (
$GLOBALS['cfg']['NaturalOrder']) {
            
uksort($tables'strnatcasecmp');
        }
    }

    if (
count($tables) < 1) {
        return 
$tables;
    }

    
$default = array(
        
'Name'      => '',
        
'Rows'      => 0,
        
'Comment'   => '',
        
'disp_name' => '',
    );

    
$table_groups = array();

    
// for blobstreaming - list of blobstreaming tables

    // load PMA configuration
    
$PMA_Config $GLOBALS['PMA_Config'];

    foreach (
$tables as $table_name => $table) {
        
// if BS tables exist
        
if (PMA_BS_IsHiddenTable($table_name)) {
            continue;
        }

        
// check for correct row count
        
if (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 or the
            // information_schema database
            // since PMA_Table::countRecords() returns a limited row count
            // in this case.

            // set this because PMA_Table::countRecords() can use it
            
$tbl_is_view $table['TABLE_TYPE'] == 'VIEW';

            if (
$tbl_is_view || PMA_is_system_schema($db)) {
                
$table['Rows'] = PMA_Table::countRecords($db$table['Name'], falsetrue);
            }
        }

        
// in $group we save the reference to the place in $table_groups
        // where to store the table info
        
if ($GLOBALS['cfg']['LeftFrameDBTree']
            && 
$sep && strstr($table_name$sep)
        ) {
            
$parts explode($sep$table_name);

            
$group =& $table_groups;
            
$i 0;
            
$group_name_full '';
            
$parts_cnt count($parts) - 1;
            while (
$i $parts_cnt
                    
&& $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'
            
&& $table['Comment'// do not switch if the comment is empty
            
&& $table['Comment'] != 'VIEW' // happens in MySQL 5.1
        
) {
            
// switch tooltip and name
            
$table['disp_name'] = $table['Comment'];
            
$table['Comment'] = $table['Name'];
        } 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
 *
 * example:
 * <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
 *
 * @access  public
 */
function PMA_backquote($a_name$do_it true)
{
    if (
is_array($a_name)) {
        foreach (
$a_name as &$data) {
            
$data PMA_backquote($data$do_it);
        }
        return 
$a_name;
    }

    if (! 
$do_it) {
        global 
$PMA_SQPdata_forbidden_word;

        if (! 
in_array(strtoupper($a_name), $PMA_SQPdata_forbidden_word)) {
            return 
$a_name;
        }
    }

    
// '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

/**
 * Defines the <CR><LF> value depending on the user OS.
 *
 * @return  string   the <CR><LF> value to use
 *
 * @access  public
 */
function PMA_whichCrlf()
{
    
// The 'PMA_USR_OS' constant is defined in "./libraries/Config.class.php"
    // Win case
    
if (PMA_USR_OS == 'Win') {
        
$the_crlf "rn";
    } else {
        
// Others
        
$the_crlf "n";
    }

    return 
$the_crlf;
// end of the 'PMA_whichCrlf()' function

/**
 * Reloads navigation if needed.
 *
 * @param bool $jsonly prints out pure JavaScript
 *
 * @access  public
 */
function PMA_reloadNavigation($jsonly=false)
{
    
// Reloads the navigation frame via JavaScript if required
    
if (isset($GLOBALS['reload']) && $GLOBALS['reload']) {
        
// one of the reasons for a reload is when a table is dropped
        // in this case, get rid of the table limit offset, otherwise
        // we have a problem when dropping a table on the last page
        // and the offset becomes greater than the total number of tables
        
unset($_SESSION['tmp_user_values']['table_limit_offset']);
        echo 
"n";
        
$reload_url './navigation.php?' PMA_generate_common_url($GLOBALS['db'], '''&');
        if (!
$jsonly) {
            echo 
'<script type="text/javascript">' PHP_EOL;
        }
    
?>
//<![CDATA[
if (typeof(window.parent) != 'undefined'
    && typeof(window.parent.frame_navigation) != 'undefined'
    && window.parent.goTo) {
    window.parent.goTo('<?php echo $reload_url?>');
}
//]]>
<?php
        
if (!$jsonly) {
            echo 
'</script>' PHP_EOL;
        }

        unset(
$GLOBALS['reload']);
    }
}

/**
 * displays the message and the query
 * usually the message is the result of the query executed
 *
 * @param string  $message   the message to display
 * @param string  $sql_query the query to display
 * @param string  $type      the type (level) of the message
 * @param boolean $is_view   is this a message after a VIEW operation?
 *
 * @return  string
 *
 * @access  public
 */
function PMA_showMessage($message$sql_query null$type 'notice'$is_view false)
{
    
/*
     * PMA_ajaxResponse uses this function to collect the string of HTML generated
     * for showing the message.  Use output buffering to collect it and return it
     * in a string.  In some special cases on sql.php, buffering has to be disabled
     * and hence we check with $GLOBALS['buffer_message']
     */
    
if ( $GLOBALS['is_ajax_request'] == true && ! isset($GLOBALS['buffer_message']) ) {
        
ob_start();
    }
    global 
$cfg;

    if (
null === $sql_query) {
        if (! empty(
$GLOBALS['display_query'])) {
            
$sql_query $GLOBALS['display_query'];
        } elseif (
$cfg['SQP']['fmtType'] == 'none' && ! empty($GLOBALS['unparsed_sql'])) {
            
$sql_query $GLOBALS['unparsed_sql'];
        } elseif (! empty(
$GLOBALS['sql_query'])) {
            
$sql_query $GLOBALS['sql_query'];
        } else {
            
$sql_query '';
        }
    }

    if (isset(
$GLOBALS['using_bookmark_message'])) {
        
$GLOBALS['using_bookmark_message']->display();
        unset(
$GLOBALS['using_bookmark_message']);
    }

    
// Corrects the tooltip text via JS if required
    // @todo this is REALLY the wrong place to do this - very unexpected here
    
if (! $is_view && strlen($GLOBALS['table']) && $cfg['ShowTooltip']) {
        
$tooltip PMA_Table::sGetToolTip($GLOBALS['db'], $GLOBALS['table']);
        
$uni_tbl PMA_jsFormat($GLOBALS['db'] . '.' $GLOBALS['table'], false);
        echo 
"n";
        echo 
'<script type="text/javascript">' "n";
        echo 
'//<![CDATA[' "n";
        echo 
"if (window.parent.updateTableTitle) window.parent.updateTableTitle('"
            
$uni_tbl "', '" PMA_jsFormat($tooltipfalse) . "');" "n";
        echo 
'//]]>' "n";
        echo 
'</script>' "n";
    } 
// end if ... elseif

    // Checks if the table needs to be repaired after a TRUNCATE query.
    // @todo what about $GLOBALS['display_query']???
    // @todo this is REALLY the wrong place to do this - very unexpected here
    
if (strlen($GLOBALS['table'])
        && 
$GLOBALS['sql_query'] == 'TRUNCATE TABLE ' PMA_backquote($GLOBALS['table'])
    ) {
        if (
PMA_Table::sGetStatusInfo($GLOBALS['db'], $GLOBALS['table'], 'Index_length') > 1024 && !PMA_DRIZZLE) {
            
PMA_DBI_try_query('REPAIR TABLE ' PMA_backquote($GLOBALS['table']));
        }
    }
    unset(
$tbl_status);

    
// In an Ajax request, $GLOBALS['cell_align_left'] may not be defined. Hence,
    // check for it's presence before using it
    
echo '<div id="result_query" align="'
        
. ( isset($GLOBALS['cell_align_left']) ? $GLOBALS['cell_align_left'] : '' )
        . 
'">' "n";

    if (
$message instanceof PMA_Message) {
        if (isset(
$GLOBALS['special_message'])) {
            
$message->addMessage($GLOBALS['special_message']);
            unset(
$GLOBALS['special_message']);
        }
        
$message->display();
        
$type $message->getLevel();
    } else {
        echo 
'<div class="' $type '">';
        echo 
PMA_sanitize($message);
        if (isset(
$GLOBALS['special_message'])) {
            echo 
PMA_sanitize($GLOBALS['special_message']);
            unset(
$GLOBALS['special_message']);
        }
        echo 
'</div>';
    }

    if (
$cfg['ShowSQL'] == true && ! empty($sql_query)) {
        
// Html format the query to be displayed
        // 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 '\n"<br />' "n"
                
'&nbsp;&nbsp;&nbsp;&nbsp;. "';
            
$query_base htmlspecialchars(addslashes($sql_query));
            
$query_base preg_replace('/((1512)|(15)|(12))/'$new_line$query_base);
        } else {
            
$query_base $sql_query;
        }

        
$query_too_big false;

        if (
strlen($query_base) > $cfg['MaxCharactersInDisplayedSQL']) {
            
// when the query is large (for example an INSERT of binary
            // data), the parser chokes; so avoid parsing the query
            
$query_too_big true;
            
$shortened_query_base nl2br(
                
htmlspecialchars(
                    
substr($sql_query0$cfg['MaxCharactersInDisplayedSQL']) . '[...]'
                
)
            );
        } elseif (! empty(
$GLOBALS['parsed_sql'])
         && 
$query_base == $GLOBALS['parsed_sql']['raw']) {
            
// (here, use "! empty" because when deleting a bookmark,
            // $GLOBALS['parsed_sql'] is set but empty
            
$parsed_sql $GLOBALS['parsed_sql'];
        } else {
            
// Parse SQL if needed
            
$parsed_sql PMA_SQP_parse($query_base);
        }

        
// Analyze it
        
if (isset($parsed_sql) && ! PMA_SQP_isError()) {
            
$analyzed_display_query PMA_SQP_analyze($parsed_sql);

            
// Same as below (append LIMIT), append the remembered ORDER BY
            
if ($GLOBALS['cfg']['RememberSorting']
                && isset(
$analyzed_display_query[0]['queryflags']['select_from'])
                && isset(
$GLOBALS['sql_order_to_append'])
            ) {
                
$query_base $analyzed_display_query[0]['section_before_limit']
                    . 
"n" $GLOBALS['sql_order_to_append']
                    . 
$analyzed_display_query[0]['limit_clause'] . ' '
                    
$analyzed_display_query[0]['section_after_limit'];

                
// Need to reparse query
                
$parsed_sql PMA_SQP_parse($query_base);
                
// update the $analyzed_display_query
                
$analyzed_display_query[0]['section_before_limit'] .= $GLOBALS['sql_order_to_append'];
                
$analyzed_display_query[0]['order_by_clause'] = $GLOBALS['sorted_col'];
            }

            
// Here we append the LIMIT added for navigation, to
            // enable its display. Adding it higher in the code
            // to $sql_query would create a problem when
            // using the Refresh or Edit links.

            // Only append it on SELECTs.

            /**
             * @todo 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'])) {
            try {
                
$query_base PMA_validateSQL($query_base);
            } catch (
Exception $e) {
                
PMA_Message::error(__('Failed to connect to SQL validator!'))->display();
            }
        } elseif (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)

        // Basic url query part
        
$url_params = array();
        if (! isset(
$GLOBALS['db'])) {
            
$GLOBALS['db'] = '';
        }
        if (
strlen($GLOBALS['db'])) {
            
$url_params['db'] = $GLOBALS['db'];
            if (
strlen($GLOBALS['table'])) {
                
$url_params['table'] = $GLOBALS['table'];
                
$edit_link 'tbl_sql.php';
            } else {
                
$edit_link 'db_sql.php';
            }
        } else {
            
$edit_link 'server_sql.php';
        }

        
// Want to have the query explained
        // but only explain a SELECT (that has not been explained)
        /* SQL-Parser-Analyzer */
        
$explain_link '';
        
$is_select false;
        if (! empty(
$cfg['SQLQuery']['Explain']) && ! $query_too_big) {
            
$explain_params $url_params;
            
// Detect if we are validating as well
            // To preserve the validate uRL data
            
if (! empty($GLOBALS['validatequery'])) {
                
$explain_params['validatequery'] = 1;
            }
            if (
preg_match('@^SELECT[[:space:]]+@i'$sql_query)) {
                
$explain_params['sql_query'] = 'EXPLAIN ' $sql_query;
                
$_message __('Explain SQL');
                
$is_select true;
            } elseif (
preg_match('@^EXPLAIN[[:space:]]+SELECT[[:space:]]+@i'$sql_query)) {
                
$explain_params['sql_query'] = substr($sql_query8);
                
$_message __('Skip Explain SQL');
            }
            if (isset(
$explain_params['sql_query'])) {
                
$explain_link 'import.php' PMA_generate_common_url($explain_params);
                
$explain_link ' [' PMA_linkOrButton($explain_link$_message) . ']';
            }
        } 
//show explain

        
$url_params['sql_query']  = $sql_query;
        
$url_params['show_query'] = 1;

        
// even if the query is big and was truncated, offer the chance
        // to edit it (unless it's enormous, see PMA_linkOrButton() )
        
if (! empty($cfg['SQLQuery']['Edit'])) {
            if (
$cfg['EditInWindow'] == true) {
                
$onclick 'window.parent.focus_querywindow(''
                    . PMA_jsFormat($sql_query, false) . ''); return false;'
;
            } else {
                
$onclick '';
            }

            
$edit_link .= PMA_generate_common_url($url_params) . '#querybox';
            
$edit_link ' [' PMA_linkOrButton($edit_link__('Edit'), array('onclick' => $onclick)) . ']';
        } else {
            
$edit_link '';
        }

        
$url_qpart PMA_generate_common_url($url_params);

        
// Also we would like to get the SQL formed in some nice
        // php-code
        
if (! empty($cfg['SQLQuery']['ShowAsPHP']) && ! $query_too_big) {
            
$php_params $url_params;

            if (! empty(
$GLOBALS['show_as_php'])) {
                
$_message __('Without PHP Code');
            } else {
                
$php_params['show_as_php'] = 1;
                
$_message __('Create PHP Code');
            }

            
$php_link 'import.php' PMA_generate_common_url($php_params);
            
$php_link ' [' PMA_linkOrButton($php_link$_message) . ']';

            if (isset(
$GLOBALS['show_as_php'])) {
                
$runquery_link 'import.php' PMA_generate_common_url($url_params);
                
$php_link .= ' [' PMA_linkOrButton($runquery_link__('Submit Query')) . ']';
            }
        } else {
            
$php_link '';
        } 
//show as php

        // Refresh query
        
if (! empty($cfg['SQLQuery']['Refresh'])
            && ! isset(
$GLOBALS['show_as_php']) // 'Submit query' does the same
            
&& preg_match('@^(SELECT|SHOW)[[:space:]]+@i'$sql_query)
        ) {
            
$refresh_link 'import.php' PMA_generate_common_url($url_params);
            
$refresh_link ' [' PMA_linkOrButton($refresh_link__('Refresh')) . ']';
        } else {
            
$refresh_link '';
        } 
//refresh

        
if (! empty($cfg['SQLValidator']['use'])
            && ! empty(
$cfg['SQLQuery']['Validate'])
        ) {
            
$validate_params $url_params;
            if (!empty(
$GLOBALS['validatequery'])) {
                
$validate_message __('Skip Validate SQL');
            } else {
                
$validate_params['validatequery'] = 1;
                
$validate_message __('Validate SQL');
            }

            
$validate_link 'import.php' PMA_generate_common_url($validate_params);
            
$validate_link ' [' PMA_linkOrButton($validate_link$validate_message) . ']';
        } else {
            
$validate_link '';
        } 
//validator

        
if (!empty($GLOBALS['validatequery'])) {
            echo 
'<div class="sqlvalidate">';
        } else {
            echo 
'<code class="sql">';
        }
        if (
$query_too_big) {
            echo 
$shortened_query_base;
        } else {
            echo 
$query_base;
        }

        
//Clean up the end of the PHP
        
if (! empty($GLOBALS['show_as_php'])) {
            echo 
'";';
        }
        if (!empty(
$GLOBALS['validatequery'])) {
            echo 
'</div>';
        } else {
            echo 
'</code>';
        }

        echo 
'<div class="tools">';
        
// avoid displaying a Profiling checkbox that could
        // be checked, which would reexecute an INSERT, for example
        
if (! empty($refresh_link)) {
            
PMA_profilingCheckbox($sql_query);
        }
        
// if needed, generate an invisible form that contains controls for the
        // Inline link; this way, the behavior of the Inline link does not
        // depend on the profiling support or on the refresh link
        
if (empty($refresh_link) || ! PMA_profilingSupported()) {
            echo 
'<form action="sql.php" method="post">';
            echo 
PMA_generate_common_hidden_inputs($GLOBALS['db'], $GLOBALS['table']);
            echo 
'<input type="hidden" name="sql_query" value="'
                
htmlspecialchars($sql_query) . '" />';
            echo 
'</form>';
        }

        
// in the tools div, only display the Inline link when not in ajax
        // mode because 1) it currently does not work and 2) we would
        // have two similar mechanisms on the page for the same goal
        
if ($is_select
            
|| $GLOBALS['is_ajax_request'] === false
            
&& ! $query_too_big
        
) {
            
// see in js/functions.js the jQuery code attached to id inline_edit
            // document.write conflicts with jQuery, hence used $().append()
            
echo "<script type="text/javascript">n" .
                
"//<![CDATA[n" .
                
"$('.tools form').last().after('[<a href="#" title="" .
                
PMA_escapeJsString(__('Inline edit of this query')) .
                
"" class="inline_edit_sql">" .
                PMA_escapeJsString(_pgettext('Inline edit query', 'Inline')) .
                "
</a>]');n" .
                "//]]>n" .
                "</script>";
        }
        echo $edit_link . $explain_link . $php_link . $refresh_link . $validate_link;
        echo '
</div>';
    }
    echo '
</div>';
    if ($GLOBALS['
is_ajax_request'] === false) {
        echo '
<br class="clearfloat" />';
    }

    // If we are in an Ajax request, we have most probably been called in
    // PMA_ajaxResponse().  Hence, collect the buffer contents and return it
    // to PMA_ajaxResponse(), which will encode it for JSON.
    if ($GLOBALS['
is_ajax_request'] == true
        && ! isset($GLOBALS['
buffer_message'])
    ) {
        $buffer_contents =  ob_get_contents();
        ob_end_clean();
        return $buffer_contents;
    }
    return null;
} // end of the '
PMA_showMessage()' function

/**
 * Verifies if current MySQL server supports profiling
 *
 * @access  public
 *
 * @return  boolean whether profiling is supported
 */
function PMA_profilingSupported()
{
    if (! PMA_cacheExists('
profiling_supported', true)) {
        // 5.0.37 has profiling but for example, 5.1.20 does not
        // (avoid a trip to the server for MySQL before 5.0.37)
        // and do not set a constant as we might be switching servers
        if (defined('
PMA_MYSQL_INT_VERSION')
            && PMA_MYSQL_INT_VERSION >= 50037
            && PMA_DBI_fetch_value("SHOW VARIABLES LIKE '
profiling'")
        ) {
            PMA_cacheSet('
profiling_supported', true, true);
        } else {
            PMA_cacheSet('
profiling_supported', false, true);
        }
    }

    return PMA_cacheGet('
profiling_supported', true);
}

/**
 * Displays a form with the Profiling checkbox
 *
 * @param string $sql_query sql query
 *
 * @access  public
 */
function PMA_profilingCheckbox($sql_query)
{
    if (PMA_profilingSupported()) {
        echo '
<form action="sql.php" method="post">' . "n";
        echo PMA_generate_common_hidden_inputs($GLOBALS['
db'], $GLOBALS['table']);
        echo '
<input type="hidden" name="sql_query" value="' . htmlspecialchars($sql_query) . '" />' . "n";
        echo '
<input type="hidden" name="profiling_form" value="1" />' . "n";
        PMA_display_html_checkbox('
profiling', __('Profiling'), isset($_SESSION['profiling']), true);
        echo '
<noscript><input type="submit" value="' . __('Go') . '" /></noscript>' . "n";
        echo '
</form>' . "n";
    }
}

/**
 * Formats $value to byte view
 *
 * @param double $value the value to format
 * @param int    $limes the sensitiveness
 * @param int    $comma the number of decimals to retain
 *
 * @return   array    the formatted value and its unit
 *
 * @access  public
 */
function PMA_formatByteDown($value, $limes = 6, $comma = 0)
{
    if ($value === null) {
        return null;
    }

    $byteUnits = array(
        /* l10n: shortcuts for Byte */
        __('B'),
        /* l10n: shortcuts for Kilobyte */
        __('
KiB'),
        /* l10n: shortcuts for Megabyte */
        __('
MiB'),
        /* l10n: shortcuts for Gigabyte */
        __('
GiB'),
        /* l10n: shortcuts for Terabyte */
        __('
TiB'),
        /* l10n: shortcuts for Petabyte */
        __('
PiB'),
        /* l10n: shortcuts for Exabyte */
        __('
EiB')
        );

    $dh   = PMA_pow(10, $comma);
    $li   = PMA_pow(10, $limes);
    $unit = $byteUnits[0];

    for ($d = 6, $ex = 15; $d >= 1; $d--, $ex-=3) {
        if (isset($byteUnits[$d]) && $value >= $li * PMA_pow(10, $ex)) {
            // use 1024.0 to avoid integer overflow on 64-bit machines
            $value = round($value / (PMA_pow(1024, $d) / $dh)) /$dh;
            $unit = $byteUnits[$d];
            break 1;
        } // end if
    } // end for

    if ($unit != $byteUnits[0]) {
        // if the unit is not bytes (as represented in current language)
        // reformat with max length of 5
        // 4th parameter=true means do not reformat if value < 1
        $return_value = PMA_formatNumber($value, 5, $comma, true);
    } else {
        // do not reformat, just handle the locale
        $return_value = PMA_formatNumber($value, 0);
    }

    return array(trim($return_value), $unit);
} // end of the '
PMA_formatByteDown' function

/**
 * Changes thousands and decimal separators to locale specific values.
 *
 * @param string $value the value
 *
 * @return string
 */
function PMA_localizeNumber($value)
{
    return str_replace(
        array('
,', '.'),
        array(
            /* l10n: Thousands separator */
            __('
,'),
            /* l10n: Decimal separator */
            __('
.'),
            ),
        $value
    );
}

/**
 * Formats $value to the given length and appends SI prefixes
 * with a $length of 0 no truncation occurs, number is only formated
 * to the current locale
 *
 * examples:
 * <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 $digits_left    number of digits left of the comma
 * @param integer $digits_right   number of digits right of the comma
 * @param boolean $only_down      do not reformat numbers below 1
 * @param boolean $noTrailingZero removes trailing zeros right of the comma
 *                                (default: true)
 *
 * @return  string   the formatted value and its unit
 *
 * @access  public
 */
function PMA_formatNumber($value, $digits_left = 3, $digits_right = 0,
$only_down = false, $noTrailingZero = true)
{
    if ($value==0) {
        return '
0';
    }

    $originalValue = $value;
    //number_format is not multibyte safe, str_replace is safe
    if ($digits_left === 0) {
        $value = number_format($value, $digits_right);
        if ($originalValue != 0 && floatval($value) == 0) {
            $value = ' 
<' . (1 / PMA_pow(10, $digits_right));
        }

        return PMA_localizeNumber($value);
    }

    // this units needs no translation, ISO
    $units = array(
        -8 => '
y',
        -7 => '
z',
        -6 => '
a',
        -5 => '
f',
        -4 => '
p',
        -3 => '
n',
        -2 => '
&micro;',
        -1 => '
m',
        0 => ' ',
        1 => '
k',
        2 => '
M',
        3 => '
G',
        4 => '
T',
        5 => '
P',
        6 => '
E',
        7 => '
Z',
        8 => '
Y'
    );

    // check for negative value to retain sign
    if ($value < 0) {
        $sign = '
-';
        $value = abs($value);
    } else {
        $sign = '';
    }

    $dh = PMA_pow(10, $digits_right);

    /*
     * This gives us the right SI prefix already,
     * but $digits_left parameter not incorporated
     */
    $d = floor(log10($value) / 3);
    /*
     * Lowering the SI prefix by 1 gives us an additional 3 zeros
     * So if we have 3,6,9,12.. free digits ($digits_left - $cur_digits)
     * to use, then lower the SI prefix
     */
    $cur_digits = floor(log10($value / PMA_pow(1000, $d, '
pow'))+1);
    if ($digits_left > $cur_digits) {
        $d-= floor(($digits_left - $cur_digits)/3);
    }

    if ($d<0 && $only_down) {
        $d=0;
    }

    $value = round($value / (PMA_pow(1000, $d, '
pow') / $dh)) /$dh;
    $unit = $units[$d];

    // If we dont want any zeros after the comma just add the thousand seperator
    if ($noTrailingZero) {
        $value = PMA_localizeNumber(
            preg_replace('
/(?<=d)(?=(d{3})+(?!d))/', ',', $value)
        );
    } else {
        //number_format is not multibyte safe, str_replace is safe
        $value = PMA_localizeNumber(number_format($value, $digits_right));
    }

    if ($originalValue!=0 && floatval($value) == 0) {
        return ' 
<' . (1 / PMA_pow(10, $digits_right)) . ' ' . $unit;
    }

    return $sign . $value . ' ' . $unit;
} // end of the '
PMA_formatNumber' function

/**
 * Returns the number of bytes when a formatted size is given
 *
 * @param string $formatted_size the size expression (for example 8MB)
 *
 * @return  integer  The numerical part of the expression (for example 8)
 */
function PMA_extractValueFromFormattedSize($formatted_size)
{
    $return_value = -1;

    if (preg_match('
/^[0-9]+GB$/', $formatted_size)) {
        $return_value = substr($formatted_size, 0, -2) * PMA_pow(1024, 3);
    } elseif (preg_match('
/^[0-9]+MB$/', $formatted_size)) {
        $return_value = substr($formatted_size, 0, -2) * PMA_pow(1024, 2);
    } elseif (preg_match('
/^[0-9]+K$/', $formatted_size)) {
        $return_value = substr($formatted_size, 0, -1) * PMA_pow(1024, 1);
    }
    return $return_value;
}// end of the '
PMA_extractValueFromFormattedSize' function

/**
 * Writes localised date
 *
 * @param string $timestamp the current timestamp
 * @param string $format    format
 *
 * @return  string   the formatted date
 *
 * @access  public
 */
function PMA_localisedDate($timestamp = -1, $format = '')
{
    $month = array(
        /* l10n: Short month name */
        __('
Jan'),
        /* l10n: Short month name */
        __('
Feb'),
        /* l10n: Short month name */
        __('
Mar'),
        /* l10n: Short month name */
        __('
Apr'),
        /* l10n: Short month name */
        _pgettext('
Short month name', 'May'),
        /* l10n: Short month name */
        __('
Jun'),
        /* l10n: Short month name */
        __('
Jul'),
        /* l10n: Short month name */
        __('
Aug'),
        /* l10n: Short month name */
        __('
Sep'),
        /* l10n: Short month name */
        __('
Oct'),
        /* l10n: Short month name */
        __('
Nov'),
        /* l10n: Short month name */
        __('
Dec'));
    $day_of_week = array(
        /* l10n: Short week day name */
        _pgettext('
Short week day name', 'Sun'),
        /* l10n: Short week day name */
        __('
Mon'),
        /* l10n: Short week day name */
        __('
Tue'),
        /* l10n: Short week day name */
        __('
Wed'),
        /* l10n: Short week day name */
        __('
Thu'),
        /* l10n: Short week day name */
        __('
Fri'),
        /* l10n: Short week day name */
        __('
Sat'));

    if ($format == '') {
        /* l10n: See http://www.php.net/manual/en/function.strftime.php */
        $format = __('
%%d, %Y at %I:%%p');
    }

    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
 *
 * @param array $tab        array with all options
 * @param array $url_params
 *
 * @return  string  html code for one tab, a link if valid otherwise a span
 *
 * @access  public
 */
function PMA_generate_html_tab($tab, $url_params = array(), $base_dir='')
{
    // default values
    $defaults = array(
        '
text'      => '',
        '
class'     => '',
        '
active'    => null,
        '
link'      => '',
        '
sep'       => '?',
        '
attr'      => '',
        '
args'      => '',
        '
warning'   => '',
        '
fragment'  => '',
        '
id'        => '',
    );

    $tab = array_merge($defaults, $tab);

    // determine additionnal style-class
    if (empty($tab['
class'])) {
        if (! empty($tab['
active'])
            || PMA_isValid($GLOBALS['
active_page'], 'identical', $tab['link'])
        ) {
            $tab['
class'] = 'active';
        } elseif (is_null($tab['
active']) && empty($GLOBALS['active_page'])
          && basename($GLOBALS['
PMA_PHP_SELF']) == $tab['link']
          && empty($tab['
warning'])) {
            $tab['
class'] = 'active';
        }
    }

    if (!empty($tab['
warning'])) {
        $tab['
class'] .= ' error';
        $tab['
attr'] .= ' title="' . htmlspecialchars($tab['warning']) . '"';
    }

    // If there are any tab specific URL parameters, merge those with
    // the general URL parameters
    if (! empty($tab['
url_params']) && is_array($tab['url_params'])) {
        $url_params = array_merge($url_params, $tab['
url_params']);
    }

    // build the link
    if (!empty($tab['
link'])) {
        $tab['
link'] = htmlentities($tab['link']);
        $tab['
link'] = $tab['link'] . PMA_generate_common_url($url_params);
        if (! empty($tab['
args'])) {
            foreach ($tab['
args'] as $param => $value) {
                $tab['
link'] .= PMA_get_arg_separator('html') . urlencode($param)
                    . '
=' . urlencode($value);
            }
        }
    }

    if (! empty($tab['
fragment'])) {
        $tab['
link'] .= $tab['fragment'];
    }

    // display icon, even if iconic is disabled but the link-text is missing
    if (($GLOBALS['
cfg']['MainPageIconic'] || empty($tab['text']))
        && isset($tab['
icon'])
    ) {
        // avoid generating an alt tag, because it only illustrates
        // the text that follows and if browser does not display
        // images, the text is duplicated
        $tab['
text'] = PMA_getImage(htmlentities($tab['icon'])) . $tab['text'];

    } elseif (empty($tab['
text'])) {
        // check to not display an empty link-text
        $tab['
text'] = '?';
        trigger_error(
            '
empty linktext in function ' . __FUNCTION__ . '()',
            E_USER_NOTICE
        );
    }

    //Set the id for the tab, if set in the params
    $id_string = ( empty($tab['
id']) ? '' : ' id="'.$tab['id'].'" ' );
    $out = '
<li' . ($tab['class'] == 'active' ? ' class="active"' : '') . '>';

    if (!empty($tab['
link'])) {
        $out .= '
<class="tab' . htmlentities($tab['class']) . '"'
            .$id_string
            .' 
href="' . $tab['link'] . '" ' . $tab['attr'] . '>'
            . $tab['
text'] . '</a>';
    } else {
        $out .= '
<span class="tab' . htmlentities($tab['class']) . '"'.$id_string.'>'
            . $tab['
text'] . '</span>';
    }

    $out .= '
</li>';
    return $out;
} // end of the '
PMA_generate_html_tab()' function

/**
 * returns html-code for a tab navigation
 *
 * @param array  $tabs       one element per tab
 * @param string $url_params
 * @param string $base_dir
 * @param string $menu_id
 *
 * @return  string  html-code for tab-navigation
 */
function PMA_generate_html_tabs($tabs, $url_params, $base_dir='', $menu_id='
topmenu')
{
    $tab_navigation = '
<div id="' . htmlentities($menu_id) . 'container" class="menucontainer">'
        .'
<ul id="' . htmlentities($menu_id) . '">';

    foreach ($tabs as $tab) {
        $tab_navigation .= PMA_generate_html_tab($tab, $url_params, $base_dir);
    }

    $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 largeto
 
accommodate some browsers' limitations
 *
 * @param string  $url        the URL
 * @param string  $message    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
 * @param boolean $strip_img  whether to strip the image
 * @param string  $target     target
 *
 * @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 = '')
{
    $url_length = strlen($url);
    // with this we should be able to catch case of image upload
    // into a (MEDIUM) BLOB; not worth generating even a form for these
    if ($url_length > $GLOBALS['
cfg']['LinkLengthLimit'] * 100) {
        return '';
    }


    if (! is_array($tag_params)) {
        $tmp = $tag_params;
        $tag_params = array();
        if (!empty($tmp)) {
            $tag_params['
onclick'] = 'return confirmLink(this'' PMA_escapeJsString($tmp) . '')';
        }
        unset($tmp);
    }
    if (! empty($target)) {
        $tag_params['
target'] = htmlentities($target);
    }

    $tag_params_strings = array();
    foreach ($tag_params as $par_name => $par_value) {
        // htmlspecialchars() only on non javascript
        $par_value = substr($par_name, 0, 2) == '
on'
            ? $par_value
            : htmlspecialchars($par_value);
        $tag_params_strings[] = $par_name . '
="' . $par_value . '"';
    }

    $displayed_message = '';
    // Add text if not already added
    if (stristr($message, '
<img')
        && (!$strip_img || $GLOBALS['
cfg']['PropertiesIconic'] === true)
        && strip_tags($message)==$message
    ) {
        $displayed_message = '
<span>'
        . htmlspecialchars(
            preg_replace('
/^.*salt="([^"]*)".*$/si', '1', $message)
        )
        . '</span>';
    }

    // Suhosin: Check that each query parameter is not above maximum
    
$in_suhosin_limits = true;
    if (
$url_length <= $GLOBALS['cfg']['LinkLengthLimit']) {
        if (
$suhosin_get_MaxValueLength = ini_get('suhosin.get.max_value_length')) {
            
$query_parts = PMA_splitURLQuery($url);
            foreach (
$query_parts as $query_pair) {
                list(
$eachvar$eachval) = explode('=', $query_pair);
                if (strlen(
$eachval) > $suhosin_get_MaxValueLength) {
                    
$in_suhosin_limits = false;
                    break;
                }
            }
        }
    }

    if (
$url_length <= $GLOBALS['cfg']['LinkLengthLimit'] && $in_suhosin_limits) {
        // no whitespace within an <a> else Safari will make it part of the link
        
$ret = "n" . '<a href="' . $url . '" '
            . implode(' ', 
$tag_params_strings) . '>'
            . 
$message . $displayed_message . '</a>' . "n";
    } else {
        // no spaces (linebreaks) at all
        // or after the hidden fields
        // IE will display them all

        // add class=link to submit button
        if (empty(
$tag_params['class'])) {
            
$tag_params['class'] = 'link';
        }

        if (! isset(
$query_parts)) {
            
$query_parts = PMA_splitURLQuery($url);
        }
        
$url_parts   = parse_url($url);

        if (
$new_form) {
            
$ret = '<form action="' . $url_parts['path'] . '" class="link"'
                 . ' method="
post"' . $target . ' style="displayinline;">';
            
$subname_open   = '';
            
$subname_close  = '';
            
$submit_link    = '#';
        } 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_link    = '#usesubform[' . $GLOBALS['subform_counter'] . ']=1';
        }
        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 while

        
$ret .= "n" . '<a href="' . $submit_link . '" class="formLinkSubmit" '
        . implode(' ', 
$tag_params_strings) . '>'
        . 
$message . ' ' . $displayed_message . '</a>' . "n";

        if (
$new_form) {
            
$ret .= '</form>';
        }
    } // end if... else...

    return 
$ret;
} // end of the 'PMA_linkOrButton()' function


/**
 * Splits a URL string by parameter
 *
 * @param string 
$url the URL
 *
 * @return array  the parameter/value pairs, for example [0] db=sakila
 */
function PMA_splitURLQuery(
$url)
{
    // decode encoded url separators
    
$separator   = PMA_get_arg_separator();
    // on most places separator is still hard coded ...
    if (
$separator !== '&') {
        // ... so always replace & with 
$separator
        
$url         = str_replace(htmlentities('&'), $separator$url);
        
$url         = str_replace('&', $separator$url);
    }
    
$url         = str_replace(htmlentities($separator), $separator$url);
    // end decode

    
$url_parts   = parse_url($url);
    return explode(
$separator$url_parts['query']);
}

/**
 * Returns a given timespan value in a readable format.
 *
 * @param int 
$seconds the timespan
 *
 * @return string  the formatted value
 */
function PMA_timespanFormat(
$seconds)
{
    
$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(
        __('%s days, %s hours, %s minutes and %s seconds'),
        (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 
$string    The string
 * @param string 
$Separator The Separator (defaults to "<br />n")
 *
 * @access  public
 * @todo    add a multibyte safe function PMA_STR_split()
 *
 * @return  string      The flipped string
 */
function PMA_flipstring(
$string$Separator = "<br />n")
{
    
$format_string = '';
    
$charbuff = false;

    for (
$i = 0, $str_len = strlen($string); $i < $str_len$i++) {
        
$char = $string{$i};
        
$append = false;

        if (
$char == '&') {
            
$format_string .= $charbuff;
            
$charbuff = $char;
        } elseif (
$char == ';' && !empty($charbuff)) {
            
$format_string .= $charbuff . $char;
            
$charbuff = false;
            
$append = true;
        } elseif (! empty(
$charbuff)) {
            
$charbuff .= $char;
        } else {
            
$format_string .= $char;
            
$append = true;
        }

        // do not add separator after the last character
        if (
$append && ($i != $str_len - 1)) {
            
$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 
$params  The names of the parameters needed by the calling script.
 * @param bool  
$die     Stop the execution?
 *                       (Set this manually to false in the calling script
 *                       until you know all needed parameters to check).
 * @param bool  
$request 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
 * @todo    use PMA_fatalError() if 
$die === true?
 */
function PMA_checkParameters(
$params$die = true, $request = true)
{
    global 
$checked_special;

    if (! isset(
$checked_special)) {
        
$checked_special = false;
    }

    
$reported_script_name = basename($GLOBALS['PMA_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
                . PMA_showDocu('faqmissingparameters')
                . '<br />';
            
$found_error = true;
        }
    }
    if (
$found_error) {
        /**
         * display html meta tags
         */
        include_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       current query result
 * @param integer  
$fields_cnt   number of fields
 * @param array    
$fields_meta  meta information about fields
 * @param array    
$row          current row
 * @param boolean  
$force_unique generate condition only on pk or unique
 *
 * @access  public
 *
 * @return  array     the calculated condition and whether condition is unique
 */
function PMA_getUniqueCondition(
$handle$fields_cnt$fields_meta$row$force_unique = false)
{
    
$primary_key          = '';
    
$unique_key           = '';
    
$nonprimary_condition = '';
    
$preferred_condition = '';
    
$primary_key_array    = array();
    
$unique_key_array     = array();
    
$nonprimary_condition_array = array();
    
$condition_array = array();

    for (
$i = 0; $i < $fields_cnt; ++$i) {
        
$condition   = '';
        
$con_key     = '';
        
$con_val     = '';
        
$field_flags = PMA_DBI_field_flags($handle$i);
        
$meta        = $fields_meta[$i];

        // do not use a column alias in a condition
        if (! isset(
$meta->orgname) || ! strlen($meta->orgname)) {
            
$meta->orgname = $meta->name;

            if (isset(
$GLOBALS['analyzed_sql'][0]['select_expr'])
                && is_array(
$GLOBALS['analyzed_sql'][0]['select_expr'])
            ) {
                foreach (
$GLOBALS['analyzed_sql'][0]['select_expr'] as $select_expr) {
                    // need (string) === (string)
                    // '' !== 0 but '' == 0
                    if ((string) 
$select_expr['alias'] === (string) $meta->name) {
                        
$meta->orgname = $select_expr['column'];
                        break;
                    } // end if
                } // end foreach
            }
        }

        // Do not use a table alias in a condition.
        // Test case is:
        // select * from galerie x WHERE
        //(select count(*) from galerie y where y.datum=x.datum)>1
        //
        // But orgtable is present only with mysqli extension so the
        // fix is only for mysqli.
        // Also, do not use the original table name if we are dealing with
        // a view because this view might be updatable.
        // (The isView() verification should not be costly in most cases
        // because there is some caching in the function).
        if (isset(
$meta->orgtable)
            && 
$meta->table != $meta->orgtable
            && ! PMA_Table::isView(
$GLOBALS['db'], $meta->table)
        ) {
            
$meta->table = $meta->orgtable;
        }

        // 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(fieldIS NULL"
        // that we need on the next "
if" will work)
        if (
$meta->type == 'real') {
            
$con_key = 'CONCAT(' . PMA_backquote($meta->table) . '.'
                . PMA_backquote(
$meta->orgname) . ')';
        } else {
            
$con_key = PMA_backquote($meta->table) . '.'
                . PMA_backquote(
$meta->orgname);
        } // end if... else...
        
$condition = ' ' . $con_key . ' ';

        if (! isset(
$row[$i]) || is_null($row[$i])) {
            
$con_val = 'IS NULL';
        } else {
            // timestamp is numeric on some MySQL 4.1
            // for real we use CONCAT above and it should compare to string
            if (
$meta->numeric
                && 
$meta->type != 'timestamp'
                && 
$meta->type != 'real'
            ) {
                
$con_val = '= ' . $row[$i];
            } elseif ((
$meta->type == 'blob' || $meta->type == 'string')
                // hexify only if this is a true not empty BLOB or a BINARY
                    && stristr(
$field_flags, 'BINARY')
                    && !empty(
$row[$i])) {
                // do not waste memory building a too big condition
                if (strlen(
$row[$i]) < 1000) {
                    // use a CAST if possible, to avoid problems
                    // if the field contains wildcard characters % or _
                    
$con_val = '= CAST(0x' . bin2hex($row[$i]) . ' AS BINARY)';
                } else {
                    // this blob won't be part of the final condition
                    
$con_val = null;
                }
            } elseif (in_array(
$meta->type, PMA_getGISDatatypes())
                && ! empty(
$row[$i])
            ) {
                // do not build a too big condition
                if (strlen(
$row[$i]) < 5000) {
                    
$condition .= '=0x' . bin2hex($row[$i]) . ' AND';
                } else {
                    
$condition = '';
                }
            } elseif (
$meta->type == 'bit') {
                
$con_val = "b'" . PMA_printable_bit_value($row[$i], $meta->length) . "'";
            } else {
                
$con_val = '= '' . PMA_sqlAddSlashes($row[$i], false, true) . ''';
            }
        }
        if (
$con_val != null) {
            
$condition .= $con_val . ' AND';
            if (
$meta->primary_key > 0) {
                
$primary_key .= $condition;
                
$primary_key_array[$con_key] = $con_val;
            } elseif (
$meta->unique_key > 0) {
                
$unique_key  .= $condition;
                
$unique_key_array[$con_key] = $con_val;
            }
            
$nonprimary_condition .= $condition;
            
$nonprimary_condition_array[$con_key] = $con_val;
        }
    } // end for

    // Correction University of Virginia 19991216:
    // prefer primary or unique keys for condition,
    // but use conjunction of all values if no primary key
    
$clause_is_unique = true;
    if (
$primary_key) {
        
$preferred_condition = $primary_key;
        
$condition_array = $primary_key_array;
    } elseif (
$unique_key) {
        
$preferred_condition = $unique_key;
        
$condition_array = $unique_key_array;
    } elseif (! 
$force_unique) {
        
$preferred_condition = $nonprimary_condition;
        
$condition_array = $nonprimary_condition_array;
        
$clause_is_unique = false;
    }

    
$where_clause = trim(preg_replace('|s?AND$|', '', $preferred_condition));
    return(array(
$where_clause$clause_is_unique$condition_array));
} // end function

/**
 * Generate a button or image tag
 *
 * @param string 
$button_name  name of button element
 * @param string 
$button_class class of button element
 * @param string 
$image_name   name of image element
 * @param string 
$text         text to display
 * @param string 
$image        image to display
 * @param string 
$value        value
 *
 * @access  public
 */
function PMA_buttonOrImage(
$button_name$button_class$image_name$text,
    
$image$value = '')
{
    if (
$value == '') {
        
$value = $text;
    }
    if (false === 
$GLOBALS['cfg']['PropertiesIconic']) {
        echo ' <input type="
submit" name="' . $button_name . '"'
                .' value="' . htmlspecialchars($value) . '"'
                .' title="' . htmlspecialchars($text) . '" />' . "
n";
        return;
    }

    /* 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="' . htmlspecialchars($value) . '"'
            .' title="' . htmlspecialchars($text) . '">' . "
n"
            . PMA_getIcon(
$image$text)
            .'</button>' . "
n";
    } else {
        echo '<input type="
image" name="' . $image_name
            . '" value="' . htmlspecialchars($value)
            . '" title="' . htmlspecialchars($text)
            . '" src="' . $GLOBALS['
pmaThemeImage']. $image . '" />'
            . (
$GLOBALS['cfg']['PropertiesIconic'] === 'both'
                ? '&nbsp;' . htmlspecialchars(
$text)
                : '') . "
n";
    }
} // end function

/**
 * Generate a pagination selector for browsing resultsets
 *
 * @param int    
$rows        Number of rows in the pagination set
 * @param int    
$pageNow     current page number
 * @param int    
$nbTotalPage number of total pages
 * @param int    
$showAll     If the number of pages is lower than this
 *                            variable, no pages will be omitted in pagination
 * @param int    
$sliceStart  How many rows at the beginning should always be shown?
 * @param int    
$sliceEnd    How many rows at the end should always be shown?
 * @param int    
$percent     Percentage of calculation page offsets to hop to a
 *                            next page
 * @param int    
$range       Near the current page, how many pages should
 *                            be considered "
nearby" and displayed as well?
 * @param string 
$prompt      The prompt to display (sometimes empty)
 *
 * @return string
 *
 * @access  public
 */
function PMA_pageselector(
$rows$pageNow = 1, $nbTotalPage = 1,
    
$showAll = 200, $sliceStart = 5, $sliceEnd = 5, $percent = 20,
    
$range = 10, $prompt = '')
{
    
$increment = floor($nbTotalPage / $percent);
    
$pageNowMinusRange = ($pageNow - $range);
    
$pageNowPlusRange = ($pageNow + $range);

    
$gotopage = $prompt . ' <select id="pageselector" ';
    if (
$GLOBALS['cfg']['AjaxEnable']) {
        
$gotopage .= ' class="ajax"';
    }
    
$gotopage .= ' name="pos" >' . "n";
    if (
$nbTotalPage < $showAll) {
        
$pages = range(1, $nbTotalPage);
    } else {
        
$pages = array();

        // Always show first X pages
        for (
$i = 1; $i <= $sliceStart$i++) {
            
$pages[] = $i;
        }

        // Always show last X pages
        for (
$i = $nbTotalPage - $sliceEnd$i <= $nbTotalPage$i++) {
            
$pages[] = $i;
        }

        // Based on the number of results we add the specified
        // 
$percent percentage to each page number,
        // so that we have a representing page number every now and then to
        // immediately 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 >= $pageNowMinusRange && $i <= $pageNowPlusRange) {
                // If our pageselector comes near the current page, we use 1
                // counter increments
                
$i++;
                
$met_boundary = true;
            } else {
                // We add the percentage increment to our current page to
                // hop to the next one in range
                
$i += $increment;

                // Make sure that we do not cross our boundaries.
                if (
$i > $pageNowMinusRange && ! $met_boundary) {
                    
$i = $pageNowMinusRange;
                }
            }

            if (
$i > 0 && $i <= $x) {
                
$pages[] = $i;
            }
        }

/*
    Add page numbers with "
geometrically increasing" distances.

    This helps me a lot when navigating through giant tables.

    Test case: table with 2.28 million sets, 76190 pages. Page of interest is
    between 72376 and 76190.
    Selecting page 72376.
    Now, old version enumerated only +/- 10 pages around 72376 and the
    percentage increment produced steps of about 3000.

    The following code adds page numbers +/- 2,4,8,16,32,64,128,256 etc.
    around the current page.
*/

        
$i = $pageNow;
        
$dist = 1;
        while (
$i < $x) {
            
$dist = 2 * $dist;
            
$i = $pageNow + $dist;
            if (
$i > 0 && $i <= $x) {
                
$pages[] = $i;
            }
        }

        
$i = $pageNow;
        
$dist = 1;
        while (
$i >0) {
            
$dist = 2 * $dist;
            
$i = $pageNow - $dist;
            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-weightbold"';
        } else {
            
$selected = '';
        }
        
$gotopage .= '                <option ' . $selected
            . ' value="' . (($i - 1) * $rows) . '">' . 
$i . '</option>' . "n";
    }

    
$gotopage .= ' </select><noscript><input type="submit" value="'
        . __('
Go') . '" /></noscript>';

    return 
$gotopage;
} // end function


/**
 * Generate navigation for a list
 *
 * @param int    
$count       number of elements in the list
 * @param int    
$pos         current position in the list
 * @param array  
$_url_params url parameters
 * @param string 
$script      script name for form target
 * @param string 
$frame       target frame
 * @param int    
$max_count   maximum number of elements to display from the list
 *
 * @access  public
 *
 * @todo    use 
$pos from $_url_params
 */
function PMA_listNavigator(
$count$pos$_url_params$script$frame$max_count)
{

    if (
$max_count < $count) {
        echo 'frame_navigation' == 
$frame
            ? '<div id="
navidbpageselector">' . "n"
            : '';
        echo __('Page number:');
        echo 'frame_navigation' == 
$frame ? '<br />' : ' ';

        // Move to the beginning or to the previous page
        if (
$pos > 0) {
            // patch #474210 - part 1
            if (
$GLOBALS['cfg']['NavigationBarIconic']) {
                
$caption1 = '&lt;&lt;';
                
$caption2 = ' &lt; ';
                
$title1   = ' title="' . _pgettext('First page', 'Begin') . '"';
                
$title2   = ' title="' . _pgettext('Previous page', 'Previous') . '"';
            } else {
                
$caption1 = _pgettext('First page', 'Begin') . ' &lt;&lt;';
                
$caption2 = _pgettext('Previous page', 'Previous') . ' &lt;';
                
$title1   = '';
                
$title2   = '';
            } // end if... else...
            
$_url_params['pos'] = 0;
            echo '<a' . 
$title1 . ' href="' . $script
                . PMA_generate_common_url($_url_params) . '" target="'
                . $frame . '">' . 
$caption1 . '</a>';
            
$_url_params['pos'] = $pos - $max_count;
            echo '<a' . 
$title2 . ' href="' . $script
                . PMA_generate_common_url($_url_params) . '" target="'
                . $frame . '">' . 
$caption2 . '</a>';
        }

        echo "
n", '<form action="./', basename($script), '" method="post" target="', $frame, '">', "n";
        echo PMA_generate_common_hidden_inputs(
$_url_params);
        echo PMA_pageselector(
            
$max_count,
            floor((
$pos + 1) / $max_count) + 1,
            ceil(
$count / $max_count)
        );
        echo '</form>';

        if (
$pos + $max_count < $count) {
            if (
$GLOBALS['cfg']['NavigationBarIconic']) {
                
$caption3 = ' &gt; ';
                
$caption4 = '&gt;&gt;';
                
$title3   = ' title="' . _pgettext('Next page', 'Next') . '"';
                
$title4   = ' title="' . _pgettext('Last page', 'End') . '"';
            } else {
                
$caption3 = '&gt; ' . _pgettext('Next page', 'Next');
                
$caption4 = '&gt;&gt; ' . _pgettext('Last page', 'End');
                
$title3   = '';
                
$title4   = '';
            } // end if... else...
            
$_url_params['pos'] = $pos + $max_count;
            echo '<a' . 
$title3 . ' href="' . $script
                . PMA_generate_common_url($_url_params) . '" target="'
                . $frame . '">' . 
$caption3 . '</a>';
            
$_url_params['pos'] = floor($count / $max_count) * $max_count;
            if (
$_url_params['pos'] == $count) {
                
$_url_params['pos'] = $count - $max_count;
            }
            echo '<a' . 
$title4 . ' href="' . $script
                . PMA_generate_common_url($_url_params) . '" target="'
                . $frame . '">' . 
$caption4 . '</a>';
        }
        echo "
n";
        if ('frame_navigation' == 
$frame) {
            echo '</div>' . "
n";
        }
    }
}

/**
 * replaces %u in given path with current user name
 *
 * example:
 * <code>
 * 
$user_dir = PMA_userDir('/var/pma_tmp/%u/'); // '/var/pma_tmp/root/'
 *
 * </code>
 *
 * @param string 
$dir with wildcard for user
 *
 * @return  string  per user directory
 */
function PMA_userDir(
$dir)
{
    // add trailing slash
    if (substr(
$dir, -1) != '/') {
        
$dir .= '/';
    }

    return str_replace('%u', 
$GLOBALS['cfg']['Server']['user'], $dir);
}

/**
 * returns html code for db link to default db page
 *
 * @param string 
$database 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'];
    } else {
        
$database = PMA_unescape_mysql_wildcards($database);
    }

    return '<a href="' . $GLOBALS['
cfg']['DefaultTabDatabase'] . '?'
        . PMA_generate_common_url($database) . '" title="'
        . sprintf(
            __('
Jump to database &quot;%s&quot;.'),
            htmlspecialchars($database)
        )
        . '">' . htmlspecialchars(
$database) . '</a>';
}

/**
 * Displays a lightbulb hint explaining a known external bug
 * that affects a functionality
 *
 * @param string 
$functionality   localized message explaining the func.
 * @param string 
$component       'mysql' (eventually, 'php')
 * @param string 
$minimum_version of this component
 * @param string 
$bugref          bug reference for this component
 */
function PMA_externalBug(
$functionality$component$minimum_version$bugref)
{
    if (
$component == 'mysql' && PMA_MYSQL_INT_VERSION < $minimum_version) {
        echo PMA_showHint(
            sprintf(
                __('The %s functionality is affected by a known bug, see %s'),
                
$functionality,
                PMA_linkURL('http://bugs.mysql.com/') . 
$bugref
            )
        );
    }
}

/**
 * Generates and echoes an HTML checkbox
 *
 * @param string  
$html_field_name the checkbox HTML field
 * @param string  
$label           label for checkbox
 * @param boolean 
$checked         is it initially checked?
 * @param boolean 
$onclick         should it submit the form on click?
 *
 * @return the HTML for the checkbox
 */
function PMA_display_html_checkbox(
$html_field_name$label$checked$onclick)
{

    echo '<input type="
checkbox" name="' . $html_field_name . '" id="'
        . $html_field_name . '"' . (
$checked ? ' checked="checked"' : '')
        . (
$onclick ? ' class="autosubmit"' : '') . ' /><label for="'
        . $html_field_name . '">' . 
$label . '</label>';
}

/**
 * Generates and echoes a set of radio HTML fields
 *
 * @param string  
$html_field_name the radio HTML field
 * @param array   
$choices         the choices values and labels
 * @param string  
$checked_choice  the choice to check by default
 * @param boolean 
$line_break      whether to add an HTML line break after a choice
 * @param boolean 
$escape_label    whether to use htmlspecialchars() on label
 * @param string  
$class           enclose each choice with a div of this class
 *
 * @return the HTML for the tadio buttons
 */
function PMA_display_html_radio(
$html_field_name$choices$checked_choice = '',
$line_break = true, $escape_label = true, $class='')
{
    foreach (
$choices as $choice_value => $choice_label) {
        if (! empty(
$class)) {
            echo '<div class="' . $class . '">';
        }
        
$html_field_id = $html_field_name . '_' . $choice_value;
        echo '<input type="
radio" name="' . $html_field_name . '" id="'
            . $html_field_id . '" value="' . htmlspecialchars($choice_value) . '"';
        if (
$choice_value == $checked_choice) {
            echo ' checked="
checked"';
        }
        echo ' />' . "
n";
        echo '<label for="' . $html_field_id . '">'
            . (
$escape_label ? htmlspecialchars($choice_label)  : $choice_label)
            . '</label>';
        if (
$line_break) {
            echo '<br />';
        }
        if (! empty(
$class)) {
            echo '</div>';
        }
        echo "
n";
    }
}

/**
 * Generates and returns an HTML dropdown
 *
 * @param string 
$select_name   name for the select element
 * @param array  
$choices       choices values
 * @param string 
$active_choice the choice to select by default
 * @param string 
$id            id of the select element; can be different in case
 *                              the dropdown is present more than once on the page
 *
 * @return string
 *
 * @todo    support titles
 */
function PMA_generate_html_dropdown(
$select_name$choices$active_choice$id)
{
    
$result = '<select name="' . htmlspecialchars($select_name) . '" id="'
        . htmlspecialchars($id) . '">';
    foreach (
$choices as $one_choice_value => $one_choice_label) {
        
$result .= '<option value="' . htmlspecialchars($one_choice_value) . '"';
        if (
$one_choice_value == $active_choice) {
            
$result .= ' selected="selected"';
        }
        
$result .= '>' . htmlspecialchars($one_choice_label) . '</option>';
    }
    
$result .= '</select>';
    return 
$result;
}

/**
 * Generates a slider effect (jQjuery)
 * Takes care of generating the initial <div> and the link
 * controlling the slider; you have to generate the </div> yourself
 * after the sliding section.
 *
 * @param string 
$id      the id of the <div> on which to apply the effect
 * @param string 
$message the message to show as a link
 */
function PMA_generate_slider_effect(
$id$message)
{
    if (
$GLOBALS['cfg']['InitialSlidersState'] == 'disabled') {
        echo '<div id="' . $id . '">';
        return;
    }
    /**
     * Bad hack on the next line. document.write() conflicts with jQuery, hence,
     * opening the <div> with PHP itself instead of JavaScript.
     *
     * @todo find a better solution that uses $.append(), the recommended method
     * maybe by using an additional param, the id of the div to append to
     */
    ?>
<div id="
<?php echo $id?><?php echo $GLOBALS['cfg']['InitialSlidersState'] == 'closed' ' style="display: none; overflow:auto;"' ''?> class="pma_auto_slider" title="<?php echo htmlspecialchars($message); ?>">
    <?php
}

/**
 * Creates an AJAX sliding toggle button
 * (or and equivalent form when AJAX is disabled)
 *
 * @param string $action      The URL for the request to be executed
 * @param string $select_name The name for the dropdown box
 * @param array  $options     An array of options (see rte_footer.lib.php)
 * @param string $callback    A JS snippet to execute when the request is
 *                            successfully processed
 *
 * @return   string   HTML code for the toggle button
 */
function PMA_toggleButton($action$select_name$options$callback)
{
    
// Do the logic first
    
$link_on "$action&amp;$select_name=" urlencode($options[1]['value']);
    
$link_off "$action&amp;$select_name=" urlencode($options[0]['value']);
    if (
$options[1]['selected'] == true) {
        
$state 'on';
    } else if (
$options[0]['selected'] == true) {
        
$state 'off';
    } else {
        
$state 'on';
    }
    
$selected1 '';
    
$selected0 '';
    if (
$options[1]['selected'] == true) {
        
$selected1 " selected='selected'";
    } else if (
$options[0]['selected'] == true) {
        
$selected0 " selected='selected'";
    }
    
// Generate output
    
$retval  "<!-- TOGGLE START -->n";
    if (
$GLOBALS['cfg']['AjaxEnable'] && is_readable($_SESSION['PMA_Theme']->getImgPath() . 'toggle-ltr.png')) {
        
$retval .= "<noscript>n";
    }
    
$retval .= "<div class='wrapper'>n";
    
$retval .= "    <form action='$action' method='post'>n";
    
$retval .= "        <select name='$select_name'>n";
    
$retval .= "            <option value='{$options[1]['value']}'$selected1>";
    
$retval .= "                {$options[1]['label']}n";
    
$retval .= "            </option>n";
    
$retval .= "            <option value='{$options[0]['value']}'$selected0>";
    
$retval .= "                {$options[0]['label']}n";
    
$retval .= "            </option>n";
    
$retval .= "        </select>n";
    
$retval .= "        <input type='submit' value='" __('Change') . "'/>n";
    
$retval .= "    </form>n";
    
$retval .= "</div>n";
    if (
$GLOBALS['cfg']['AjaxEnable'] && is_readable($_SESSION['PMA_Theme']->getImgPath() . 'toggle-ltr.png')) {
        
$retval .= "</noscript>n";
        
$retval .= "<div class='wrapper toggleAjax hide'>n";
        
$retval .= "    <div class='toggleButton'>n";
        
$retval .= "        <div title='" __('Click to toggle') . "' class='container $state'>n";
        
$retval .= "            <img src='{$GLOBALS['pmaThemeImage']}toggle-{$GLOBALS['text_dir']}.png'n";
        
$retval .= "                 alt='' />n";
        
$retval .= "            <table cellspacing='0' cellpadding='0'><tr>n";
        
$retval .= "                <tbody>n";
        
$retval .= "                <td class='toggleOn'>n";
        
$retval .= "                    <span class='hide'>$link_on</span>n";
        
$retval .= "                    <div>";
        
$retval .= str_replace(' ''&nbsp;'$options[1]['label']) . "</div>n";
        
$retval .= "                </td>n";
        
$retval .= "                <td><div>&nbsp;</div></td>n";
        
$retval .= "                <td class='toggleOff'>n";
        
$retval .= "                    <span class='hide'>$link_off</span>n";
        
$retval .= "                    <div>";
        
$retval .= str_replace(' ''&nbsp;'$options[0]['label']) . "</div>n";
        
$retval .= "                    </div>n";
        
$retval .= "                </tbody>n";
        
$retval .= "            </tr></table>n";
        
$retval .= "            <span class='hide callback'>$callback</span>n";
        
$retval .= "            <span class='hide text_direction'>{$GLOBALS['text_dir']}</span>n";
        
$retval .= "        </div>n";
        
$retval .= "    </div>n";
        
$retval .= "</div>n";
    }
    
$retval .= "<!-- TOGGLE END -->";

    return 
$retval;
// end PMA_toggleButton()

/**
 * Clears cache content which needs to be refreshed on user change.
 *
 * @return nothing
 */
function PMA_clearUserCache()
{
    
PMA_cacheUnset('is_superuser'true);
}

/**
 * Verifies if something is cached in the session
 *
 * @param string   $var    variable name
 * @param int|true $server server
 *
 * @return boolean
 */
function PMA_cacheExists($var$server 0)
{
    if (
true === $server) {
        
$server $GLOBALS['server'];
    }
    return isset(
$_SESSION['cache']['server_' $server][$var]);
}

/**
 * Gets cached information from the session
 *
 * @param string   $var    varibale name
 * @param int|true $server server
 *
 * @return mixed
 */
function PMA_cacheGet($var$server 0)
{
    if (
true === $server) {
        
$server $GLOBALS['server'];
    }
    if (isset(
$_SESSION['cache']['server_' $server][$var])) {
        return 
$_SESSION['cache']['server_' $server][$var];
    } else {
        return 
null;
    }
}

/**
 * Caches information in the session
 *
 * @param string   $var    variable name
 * @param mixed    $val    value
 * @param int|true $server server
 *
 * @return mixed
 */
function PMA_cacheSet($var$val null$server 0)
{
    if (
true === $server) {
        
$server $GLOBALS['server'];
    }
    
$_SESSION['cache']['server_' $server][$var] = $val;
}

/**
 * Removes cached information from the session
 *
 * @param string   $var    variable name
 * @param int|true $server server
 *
 * @return nothing
 */
function PMA_cacheUnset($var$server 0)
{
    if (
true === $server) {
        
$server $GLOBALS['server'];
    }
    unset(
$_SESSION['cache']['server_' $server][$var]);
}

/**
 * Converts a bit value to printable format;
 * in MySQL a BIT field can be from 1 to 64 bits so we need this
 * function because in PHP, decbin() supports only 32 bits
 *
 * @param numeric $value  coming from a BIT field
 * @param integer $length length
 *
 * @return  string  the printable value
 */
function PMA_printable_bit_value($value$length)
{
    
$printable '';
    for (
$i 0$len_ceiled ceil($length 8); $i $len_ceiled$i++) {
        
$printable .= sprintf('%08d'decbin(ord(substr($value$i1))));
    }
    
$printable substr($printable, -$length);
    return 
$printable;
}

/**
 * Verifies whether the value contains a non-printable character
 *
 * @param string $value value
 *
 * @return  boolean
 */
function PMA_contains_nonprintable_ascii($value)
{
    return 
preg_match('@[^[:print:]]@'$value);
}

/**
 * Converts a BIT type default value
 * for example, b'010' becomes 010
 *
 * @param string $bit_default_value value
 *
 * @return  string the converted value
 */
function PMA_convert_bit_default_value($bit_default_value)
{
    return 
strtr($bit_default_value, array("b" => """'" => ""));
}

/**
 * Extracts the various parts from a field type spec
 *
 * @param string $fieldspec Field specification
 *
 * @return  array associative array containing type, spec_in_brackets
 *          and possibly enum_set_values (another array)
 */
function PMA_extractFieldSpec($fieldspec)
{
    
$first_bracket_pos strpos($fieldspec'(');
    if (
$first_bracket_pos) {
        
$spec_in_brackets chop(
            
substr(
                
$fieldspec,
                
$first_bracket_pos 1,
                (
strrpos($fieldspec')') - $first_bracket_pos 1)
            )
        );
        
// convert to lowercase just to be sure
        
$type strtolower(chop(substr($fieldspec0$first_bracket_pos)));
    } else {
        
$type strtolower($fieldspec);
        
$spec_in_brackets '';
    }

    if (
'enum' == $type || 'set' == $type) {
        
// Define our working vars
        
$enum_set_values = array();
        
$working "";
        
$in_string false;
        
$index 0;

        
// While there is another character to process
        
while (isset($fieldspec[$index])) {
            
// Grab the char to look at
            
$char $fieldspec[$index];

            
// If it is a single quote, needs to be handled specially
            
if ($char == "'") {
                
// If we are not currently in a string, begin one
                
if (! $in_string) {
                    
$in_string true;
                    
$working "";
                } else {
                    
// Otherwise, it may be either an end of a string,
                    // or a 'double quote' which can be handled as-is
                    // Check out the next character (if possible)
                    
$has_next = isset($fieldspec[$index 1]);
                    
$next $has_next $fieldspec[$index 1] : null;

                    
//If we have reached the end of our 'working' string (because
                    //there are no more chars,or the next char is not another quote)
                    
if (! $has_next || $next != "'") {
                        
$enum_set_values[] = $working;
                        
$in_string false;

                    } elseif (
$next == "'") {
                        
// Otherwise, this is a 'double quote',
                        // and can be added to the working string
                        
$working .= "'";
                        
// Skip the next char; we already know what it is
                        
$index++;
                    }
                }
            } elseif (
'\' == $char
                && isset($fieldspec[$index + 1])
                && "'" == 
$fieldspec[$index + 1]
            ) {
                // escaping of a quote?
                
$working .= "'";
                $index++;
            } else {
                // Otherwise, add it to our working string like normal
                $working .= $char;
            }
            // Increment character index
            $index++;
        } // end while
        $printtype = $type . '
(' .  str_replace("','", "''", $spec_in_brackets) . ')';
        $binary = false;
        $unsigned = false;
        $zerofill = false;
    } else {
        $enum_set_values = array();

        /* Create printable type name */
        $printtype = strtolower($fieldspec);

        // Strip the "BINARY" attribute, except if we find "BINARY(" because
        // this would be a BINARY or VARBINARY field type;
        // by the way, a BLOB should not show the BINARY attribute
        // because this is not accepted in MySQL syntax.
        if (preg_match('
@binary@', $printtype) && ! preg_match('@binary[(]@', $printtype)) {
            $printtype = preg_replace('
@binary@', '', $printtype);
            $binary = true;
        } else {
            $binary = false;
        }
        $printtype = preg_replace('
@zerofill@', '', $printtype, -1, $zerofill_cnt);
        $zerofill = ($zerofill_cnt > 0);
        $printtype = preg_replace('
@unsigned@', '', $printtype, -1, $unsigned_cnt);
        $unsigned = ($unsigned_cnt > 0);
        $printtype = trim($printtype);

    }

    $attribute     = ' ';
    if ($binary) {
        $attribute = '
BINARY';
    }
    if ($unsigned) {
        $attribute = '
UNSIGNED';
    }
    if ($zerofill) {
        $attribute = '
UNSIGNED ZEROFILL';
    }

    return array(
        '
type' => $type,
        '
spec_in_brackets' => $spec_in_brackets,
        '
enum_set_values'  => $enum_set_values,
        '
print_type' => $printtype,
        '
binary' => $binary,
        '
unsigned' => $unsigned,
        '
zerofill' => $zerofill,
        '
attribute' => $attribute,
    );
}

/**
 * Verifies if this table'
s engine supports foreign keys
 
*
 * @
param string $engine engine
 
*
 * @return  
boolean
 
*/
function 
PMA_foreignkey_supported($engine)
{
    
$engine strtoupper($engine);
    if (
'INNODB' == $engine || 'PBXT' == $engine) {
        return 
true;
    } else {
        return 
false;
    }
}

/**
 * Replaces some characters by a displayable equivalent
 *
 * @param string $content content
 *
 * @return  string the content with characters replaced
 */
function PMA_replace_binary_contents($content)
{
    
$result str_replace("x00"''$content);
    
$result str_replace("x08"'b'$result);
    
$result str_replace("x0a"'n'$result);
    
$result str_replace("x0d"'r'$result);
    
$result str_replace("x1a"'Z'$result);
    return 
$result;
}

/**
 * Converts GIS data to Well Known Text format
 *
 * @param binary $data        GIS data
 * @param bool   $includeSRID Add SRID to the WKT
 *
 * @return GIS data in Well Know Text format
 */
function PMA_asWKT($data$includeSRID false)
{
    
// Convert to WKT format
    
$hex bin2hex($data);
    
$wktsql     "SELECT ASTEXT(x'" $hex "')";
    if (
$includeSRID) {
        
$wktsql .= ", SRID(x'" $hex "')";
    }
    
$wktresult  PMA_DBI_try_query($wktsqlnullPMA_DBI_QUERY_STORE);
    
$wktarr     PMA_DBI_fetch_row($wktresult0);
    
$wktval     $wktarr[0];
    if (
$includeSRID) {
        
$srid $wktarr[1];
        
$wktval "'" $wktval "'," $srid;
    }
    @
PMA_DBI_free_result($wktresult);
    return 
$wktval;
}

/**
 * If the string starts with a rn pair (0x0d0a) add an extra n
 *
 * @param string $string string
 *
 * @return  string with the chars replaced
 */

function PMA_duplicateFirstNewline($string)
{
    
$first_occurence strpos($string"rn");
    if (
$first_occurence === 0) {
        
$string "n".$string;
    }
    return 
$string;
}

/**
 * Get the action word corresponding to a script name
 * in order to display it as a title in navigation panel
 *
 * @param string $target a valid value for $cfg['LeftDefaultTabTable'],
 *                       $cfg['DefaultTabTable'] or $cfg['DefaultTabDatabase']
 *
 * @return array
 */
function PMA_getTitleForTarget($target)
{
    
$mapping = array(
        
// Values for $cfg['DefaultTabTable']
        
'tbl_structure.php' =>  __('Structure'),
        
'tbl_sql.php' => __('SQL'),
        
'tbl_select.php' =>__('Search'),
        
'tbl_change.php' =>__('Insert'),
        
'sql.php' => __('Browse'),

        
// Values for $cfg['DefaultTabDatabase']
        
'db_structure.php' => __('Structure'),
        
'db_sql.php' => __('SQL'),
        
'db_search.php' => __('Search'),
        
'db_operations.php' => __('Operations'),
    );
    return 
$mapping[$target];
}

/**
 * Formats user string, expanding @VARIABLES@, accepting strftime format string.
 *
 * @param string   $string  Text where to do expansion.
 * @param function $escape  Function to call for escaping variable values.
 * @param array    $updates Array with overrides for default parameters
 *                 (obtained from GLOBALS).
 *
 * @return string
 */
function PMA_expandUserString($string$escape null$updates = array())
{
    
/* Content */
    
$vars['http_host'] = PMA_getenv('HTTP_HOST') ? PMA_getenv('HTTP_HOST') : '';
    
$vars['server_name'] = $GLOBALS['cfg']['Server']['host'];
    
$vars['server_verbose'] = $GLOBALS['cfg']['Server']['verbose'];
    
$vars['server_verbose_or_name'] = ! empty($GLOBALS['cfg']['Server']['verbose'])
        ? 
$GLOBALS['cfg']['Server']['verbose']
        : 
$GLOBALS['cfg']['Server']['host'];
    
$vars['database'] = $GLOBALS['db'];
    
$vars['table'] = $GLOBALS['table'];
    
$vars['phpmyadmin_version'] = 'phpMyAdmin ' PMA_VERSION;

    
/* Update forced variables */
    
foreach ($updates as $key => $val) {
        
$vars[$key] = $val;
    }

    
/* Replacement mapping */
    /*
     * The __VAR__ ones are for backward compatibility, because user
     * might still have it in cookies.
     */
    
$replace = array(
        
'@HTTP_HOST@' => $vars['http_host'],
        
'@SERVER@' => $vars['server_name'],
        
'__SERVER__' => $vars['server_name'],
        
'@VERBOSE@' => $vars['server_verbose'],
        
'@VSERVER@' => $vars['server_verbose_or_name'],
        
'@DATABASE@' => $vars['database'],
        
'__DB__' => $vars['database'],
        
'@TABLE@' => $vars['table'],
        
'__TABLE__' => $vars['table'],
        
'@PHPMYADMIN@' => $vars['phpmyadmin_version'],
        );

    
/* Optional escaping */
    
if (!is_null($escape)) {
        foreach (
$replace as $key => $val) {
            
$replace[$key] = $escape($val);
        }
    }

    
/* Backward compatibility in 3.5.x */
    
if (strpos($string'@FIELDS@') !== false) {
        
$string strtr($string, array('@FIELDS@' => '@COLUMNS@'));
    }

    
/* Fetch columns list if required */
    
if (strpos($string'@COLUMNS@') !== false) {
        
$columns_list PMA_DBI_get_columns($GLOBALS['db'], $GLOBALS['table']);

        
$column_names = array();
        foreach (
$columns_list as $column) {
            if (! 
is_null($escape)) {
                
$column_names[] = $escape($column['Field']);
            } else {
                
$column_names[] = $field['Field'];
            }
        }

        
$replace['@COLUMNS@'] = implode(','$column_names);
    }

    
/* Do the replacement */
    
return strtr(strftime($string), $replace);
}

/**
 * function that generates a json output for an ajax request and ends script
 * execution
 *
 * @param PMA_Message|string $message    message string containing the
 *                                       html of the message
 * @param bool               $success    success whether the ajax request
 *                                       was successfull
 * @param array              $extra_data extra data  optional -
 *                                       any other data as part of the json request
 *
 * @return nothing
 */
function PMA_ajaxResponse($message$success true$extra_data = array())
{
    
$response = array();
    if ( 
$success == true ) {
        
$response['success'] = true;
        if (
$message instanceof PMA_Message) {
            
$response['message'] = $message->getDisplay();
        } else {
            
$response['message'] = $message;
        }
    } else {
        
$response['success'] = false;
        if (
$message instanceof PMA_Message) {
            
$response['error'] = $message->getDisplay();
        } else {
            
$response['error'] = $message;
        }
    }

    
// If extra_data has been provided, append it to the response array
    
if ( ! empty($extra_data) && count($extra_data) > ) {
        
$response array_merge($response$extra_data);
    }

    
// Set the Content-Type header to JSON so that jQuery parses the
    // response correctly.
    //
    // At this point, other headers might have been sent;
    // even if $GLOBALS['is_header_sent'] is true,
    // we have to send these additional headers.
    
header('Cache-Control: no-cache');
    
header("Content-Type: application/json");

    echo 
json_encode($response);

    if (!
defined('TESTSUITE'))
        exit;
}

/**
 * Display the form used to browse anywhere on the local server for a file to import
 *
 * @param string $max_upload_size maximum upload size
 *
 * @return nothing
 */
function PMA_browseUploadFile($max_upload_size)
{
    echo 
'<label for="radio_import_file">' __("Browse your computer:") . '</label>';
    echo 
'<div id="upload_form_status" style="display: none;"></div>';
    echo 
'<div id="upload_form_status_info" style="display: none;"></div>';
    echo 
'<input type="file" name="import_file" id="input_import_file" />';
    echo 
PMA_displayMaximumUploadSize($max_upload_size) . "n";
    
// some browsers should respect this :)
    
echo PMA_generateHiddenMaxFileSize($max_upload_size) . "n";
}

/**
 * Display the form used to select a file to import from the server upload directory
 *
 * @param array  $import_list array of import types
 * @param string $uploaddir   upload directory
 *
 * @return nothing
 */
function PMA_selectUploadFile($import_list$uploaddir)
{
    echo 
'<label for="radio_local_import_file">' sprintf(__("Select from the web server upload directory <b>%s</b>:"), htmlspecialchars(PMA_userDir($uploaddir))) . '</label>';
    
$extensions '';
    foreach (
$import_list as $key => $val) {
        if (!empty(
$extensions)) {
            
$extensions .= '|';
        }
        
$extensions .= $val['extension'];
    }
    
$matcher '@.(' $extensions ')(.('
        
PMA_supportedDecompressions() . '))?$@';

    
$active = (isset($timeout_passed) && $timeout_passed && isset($local_import_file))
        ? 
$local_import_file
        
'';
    
$files PMA_getFileSelectOptions(
        
PMA_userDir($uploaddir),
        
$matcher,
        
$active
    
);
    if (
$files === false) {
        
PMA_Message::error(
            
__('The directory you set for upload work cannot be reached')
        )->
display();
    } elseif (!empty(
$files)) {
        echo 
"n";
        echo 
'    <select style="margin: 5px" size="1" name="local_import_file" id="select_local_import_file">' "n";
        echo 
'        <option value="">&nbsp;</option>' "n";
        echo 
$files;
        echo 
'    </select>' "n";
    } elseif (empty (
$files)) {
        echo 
'<i>' __('There are no files to upload') . '</i>';
    }
}

/**
 * Build titles and icons for action links
 *
 * @return   array   the action titles
 */
function PMA_buildActionTitles()
{
    
$titles = array();

    
$titles['Browse']     = PMA_getIcon('b_browse.png'__('Browse'));
    
$titles['NoBrowse']   = PMA_getIcon('bd_browse.png'__('Browse'));
    
$titles['Search']     = PMA_getIcon('b_select.png'__('Search'));
    
$titles['NoSearch']   = PMA_getIcon('bd_select.png'__('Search'));
    
$titles['Insert']     = PMA_getIcon('b_insrow.png'__('Insert'));
    
$titles['NoInsert']   = PMA_getIcon('bd_insrow.png'__('Insert'));
    
$titles['Structure']  = PMA_getIcon('b_props.png'__('Structure'));
    
$titles['Drop']       = PMA_getIcon('b_drop.png'__('Drop'));
    
$titles['NoDrop']     = PMA_getIcon('bd_drop.png'__('Drop'));
    
$titles['Empty']      = PMA_getIcon('b_empty.png'__('Empty'));
    
$titles['NoEmpty']    = PMA_getIcon('bd_empty.png'__('Empty'));
    
$titles['Edit']       = PMA_getIcon('b_edit.png'__('Edit'));
    
$titles['NoEdit']     = PMA_getIcon('bd_edit.png'__('Edit'));
    
$titles['Export']     = PMA_getIcon('b_export.png'__('Export'));
    
$titles['NoExport']   = PMA_getIcon('bd_export.png'__('Export'));
    
$titles['Execute']    = PMA_getIcon('b_nextpage.png'__('Execute'));
    
$titles['NoExecute']  = PMA_getIcon('bd_nextpage.png'__('Execute'));
    return 
$titles;
}

/**
 * This function processes the datatypes supported by the DB, as specified in
 * $cfg['ColumnTypes'] and either returns an array (useful for quickly checking
 * if a datatype is supported) or an HTML snippet that creates a drop-down list.
 *
 * @param bool   $html     Whether to generate an html snippet or an array
 * @param string $selected The value to mark as selected in HTML mode
 *
 * @return  mixed   An HTML snippet or an array of datatypes.
 *
 */
function PMA_getSupportedDatatypes($html false$selected '')
{
    global 
$cfg;

    if (
$html) {
        
// NOTE: the SELECT tag in not included in this snippet.
        
$retval '';
        foreach (
$cfg['ColumnTypes'] as $key => $value) {
            if (
is_array($value)) {
                
$retval .= "<optgroup label='" htmlspecialchars($key) . "'>";
                foreach (
$value as $subvalue) {
                    if (
$subvalue == $selected) {
                        
$retval .= "<option selected='selected'>";
                        
$retval .= $subvalue;
                        
$retval .= "</option>";
                    } else if (
$subvalue === '-') {
                        
$retval .= "<option disabled='disabled'>";
                        
$retval .= $subvalue;
                        
$retval .= "</option>";
                    } else {
                        
$retval .= "<option>$subvalue</option>";
                    }
                }
                
$retval .= '</optgroup>';
            } else {
                if (
$selected == $value) {
                    
$retval .= "<option selected='selected'>$value</option>";
                } else {
                    
$retval .= "<option>$value</option>";
                }
            }
        }
    } else {
        
$retval = array();
        foreach (
$cfg['ColumnTypes'] as $value) {
            if (
is_array($value)) {
                foreach (
$value as $subvalue) {
                    if (
$subvalue !== '-') {
                        
$retval[] = $subvalue;
                    }
                }
            } else {
                if (
$value !== '-') {
                    
$retval[] = $value;
                }
            }
        }
    }

    return 
$retval;
// end PMA_getSupportedDatatypes()

/**
 * Returns a list of datatypes that are not (yet) handled by PMA.
 * Used by: tbl_change.php and libraries/db_routines.inc.php
 *
 * @return   array   list of datatypes
 */
function PMA_unsupportedDatatypes()
{
    
$no_support_types = array();
    return 
$no_support_types;
}

/**
 * Return GIS data types
 *
 * @param bool $upper_case whether to return values in upper case
 *
 * @return array GIS data types
 */
function PMA_getGISDatatypes($upper_case false)
{
    
$gis_data_types = array(
        
'geometry',
        
'point',
        
'linestring',
        
'polygon',
        
'multipoint',
        
'multilinestring',
        
'multipolygon',
        
'geometrycollection'
    
);
    if (
$upper_case) {
        for (
$i 0$i count($gis_data_types); $i++) {
            
$gis_data_types[$i] = strtoupper($gis_data_types[$i]);
        }
    }

    return 
$gis_data_types;
}

/**
 * Generates GIS data based on the string passed.
 *
 * @param string $gis_string GIS string
 *
 * @return GIS data enclosed in 'GeomFromText' function
 */
function PMA_createGISData($gis_string)
{
    
$gis_string =  trim($gis_string);
    
$geom_types '(POINT|MULTIPOINT|LINESTRING|MULTILINESTRING|'
        
'POLYGON|MULTIPOLYGON|GEOMETRYCOLLECTION)';
    if (
preg_match("/^'" $geom_types "(.*)',[0-9]*$/i"$gis_string)) {
        return 
'GeomFromText(' $gis_string ')';
    } elseif (
preg_match("/^" $geom_types "(.*)$/i"$gis_string)) {
        return 
"GeomFromText('" $gis_string "')";
    } else {
        return 
$gis_string;
    }
}

/**
 * Returns the names and details of the functions
 * that can be applied on geometry data typess.
 *
 * @param string $geom_type if provided the output is limited to the functions
 *                          that are applicable to the provided geometry type.
 * @param bool   $binary    if set to false functions that take two geometries
 *                          as arguments will not be included.
 * @param bool   $display   if set to true seperators will be added to the
 *                          output array.
 *
 * @return array names and details of the functions that can be applied on
 *               geometry data typess.
 */
function PMA_getGISFunctions($geom_type null$binary true$display false)
{
    
$funcs = array();
    if (
$display) {
        
$funcs[] = array('display' => ' ');
    }

    
// Unary functions common to all geomety types
    
$funcs['Dimension']    = array('params' => 1'type' => 'int');
    
$funcs['Envelope']     = array('params' => 1'type' => 'Polygon');
    
$funcs['GeometryType'] = array('params' => 1'type' => 'text');
    
$funcs['SRID']         = array('params' => 1'type' => 'int');
    
$funcs['IsEmpty']      = array('params' => 1'type' => 'int');
    
$funcs['IsSimple']     = array('params' => 1'type' => 'int');

    
$geom_type trim(strtolower($geom_type));
    if (
$display && $geom_type != 'geometry' && $geom_type != 'multipoint') {
        
$funcs[] = array('display' => '--------');
    }

    
// Unary functions that are specific to each geomety type
    
if ($geom_type == 'point') {
        
$funcs['X'] = array('params' => 1'type' => 'float');
        
$funcs['Y'] = array('params' => 1'type' => 'float');

    } elseif (
$geom_type == 'multipoint') {
        
// no fucntions here
    
} elseif ($geom_type == 'linestring') {
        
$funcs['EndPoint']   = array('params' => 1'type' => 'point');
        
$funcs['GLength']    = array('params' => 1'type' => 'float');
        
$funcs['NumPoints']  = array('params' => 1'type' => 'int');
        
$funcs['StartPoint'] = array('params' => 1'type' => 'point');
        
$funcs['IsRing']     = array('params' => 1'type' => 'int');

    } elseif (
$geom_type == 'multilinestring') {
        
$funcs['GLength']  = array('params' => 1'type' => 'float');
        
$funcs['IsClosed'] = array('params' => 1'type' => 'int');

    } elseif (
$geom_type == 'polygon') {
        
$funcs['Area']             = array('params' => 1'type' => 'float');
        
$funcs['ExteriorRing']     = array('params' => 1'type' => 'linestring');
        
$funcs['NumInteriorRings'] = array('params' => 1'type' => 'int');

    } elseif (
$geom_type == 'multipolygon') {
        
$funcs['Area']     = array('params' => 1'type' => 'float');
        
$funcs['Centroid'] = array('params' => 1'type' => 'point');
        
// Not yet implemented in MySQL
        //$funcs['PointOnSurface'] = array('params' => 1, 'type' => 'point');

    
} elseif ($geom_type == 'geometrycollection') {
        
$funcs['NumGeometries'] = array('params' => 1'type' => 'int');
    }

    
// If we are asked for binary functions as well
    
if ($binary) {
        
// section seperator
        
if ($display) {
            
$funcs[] = array('display' => '--------');
        }
        if (
PMA_MYSQL_INT_VERSION 50601) {
            
$funcs['Crosses']    = array('params' => 2'type' => 'int');
            
$funcs['Contains']   = array('params' => 2'type' => 'int');
            
$funcs['Disjoint']   = array('params' => 2'type' => 'int');
            
$funcs['Equals']     = array('params' => 2'type' => 'int');
            
$funcs['Intersects'] = array('params' => 2'type' => 'int');
            
$funcs['Overlaps']   = array('params' => 2'type' => 'int');
            
$funcs['Touches']    = array('params' => 2'type' => 'int');
            
$funcs['Within']     = array('params' => 2'type' => 'int');
        } else {
            
// If MySQl version is greaeter than or equal 5.6.1, use the ST_ prefix.
            
$funcs['ST_Crosses']    = array('params' => 2'type' => 'int');
            
$funcs['ST_Contains']   = array('params' => 2'type' => 'int');
            
$funcs['ST_Disjoint']   = array('params' => 2'type' => 'int');
            
$funcs['ST_Equals']     = array('params' => 2'type' => 'int');
            
$funcs['ST_Intersects'] = array('params' => 2'type' => 'int');
            
$funcs['ST_Overlaps']   = array('params' => 2'type' => 'int');
            
$funcs['ST_Touches']    = array('params' => 2'type' => 'int');
            
$funcs['ST_Within']     = array('params' => 2'type' => 'int');

        }

        if (
$display) {
            
$funcs[] = array('display' => '--------');
        }
        
// Minimum bounding rectangle functions
        
$funcs['MBRContains']   = array('params' => 2'type' => 'int');
        
$funcs['MBRDisjoint']   = array('params' => 2'type' => 'int');
        
$funcs['MBREquals']     = array('params' => 2'type' => 'int');
        
$funcs['MBRIntersects'] = array('params' => 2'type' => 'int');
        
$funcs['MBROverlaps']   = array('params' => 2'type' => 'int');
        
$funcs['MBRTouches']    = array('params' => 2'type' => 'int');
        
$funcs['MBRWithin']     = array('params' => 2'type' => 'int');
    }
    return 
$funcs;
}

/**
 * Creates a dropdown box with MySQL functions for a particular column.
 *
 * @param array $field       Data about the column for which
 *                           to generate the dropdown
 * @param bool  $insert_mode Whether the operation is 'insert'
 *
 * @global   array    $cfg            PMA configuration
 * @global   array    $analyzed_sql   Analyzed SQL query
 * @global   mixed    $data           (null/string) FIXME: what is this for?
 *
 * @return   string   An HTML snippet of a dropdown list with function
 *                    names appropriate for the requested column.
 */
function PMA_getFunctionsForField($field$insert_mode)
{
    global 
$cfg$analyzed_sql$data;

    
$selected '';
    
// Find the current type in the RestrictColumnTypes. Will result in 'FUNC_CHAR'
    // or something similar. Then directly look up the entry in the
    // RestrictFunctions array, which'll then reveal the available dropdown options
    
if (isset($cfg['RestrictColumnTypes'][strtoupper($field['True_Type'])])
        && isset(
$cfg['RestrictFunctions'][$cfg['RestrictColumnTypes'][strtoupper($field['True_Type'])]])
    ) {
        
$current_func_type  $cfg['RestrictColumnTypes'][strtoupper($field['True_Type'])];
        
$dropdown           $cfg['RestrictFunctions'][$current_func_type];
        
$default_function   $cfg['DefaultFunctions'][$current_func_type];
    } else {
        
$dropdown = array();
        
$default_function   '';
    }
    
$dropdown_built = array();
    
$op_spacing_needed false;
    
// what function defined as default?
    // for the first timestamp we don't set the default function
    // if there is a default value for the timestamp
    // (not including CURRENT_TIMESTAMP)
    // and the column does not have the
    // ON UPDATE DEFAULT TIMESTAMP attribute.
    
if ($field['True_Type'] == 'timestamp'
        
&& empty($field['Default'])
        && empty(
$data)
        && ! isset(
$analyzed_sql[0]['create_table_fields'][$field['Field']]['on_update_current_timestamp'])
    ) {
        
$default_function $cfg['DefaultFunctions']['first_timestamp'];
    }
    
// For primary keys of type char(36) or varchar(36) UUID if the default function
    // Only applies to insert mode, as it would silently trash data on updates.
    
if ($insert_mode
        
&& $field['Key'] == 'PRI'
        
&& ($field['Type'] == 'char(36)' || $field['Type'] == 'varchar(36)')
    ) {
         
$default_function $cfg['DefaultFunctions']['FUNC_UUID'];
    }
    
// this is set only when appropriate and is always true
    
if (isset($field['display_binary_as_hex'])) {
        
$default_function 'UNHEX';
    }

    
// Create the output
    
$retval '                <option></option>' "n";
    
// loop on the dropdown array and print all available options for that field.
    
foreach ($dropdown as $each_dropdown) {
        
$retval .= '                ';
        
$retval .= '<option';
        if (
$default_function === $each_dropdown) {
            
$retval .= ' selected="selected"';
        }
        
$retval .= '>' $each_dropdown '</option>' "n";
        
$dropdown_built[$each_dropdown] = 'true';
        
$op_spacing_needed true;
    }
    
// For compatibility's sake, do not let out all other functions. Instead
    // print a separator (blank) and then show ALL functions which weren't shown
    // yet.
    
$cnt_functions count($cfg['Functions']);
    for (
$j 0$j $cnt_functions$j++) {
        if (! isset(
$dropdown_built[$cfg['Functions'][$j]])
            || 
$dropdown_built[$cfg['Functions'][$j]] != 'true'
        
) {
            
// Is current function defined as default?
            
$selected = ($field['first_timestamp'] && $cfg['Functions'][$j] == $cfg['DefaultFunctions']['first_timestamp'])
                        || (! 
$field['first_timestamp'] && $cfg['Functions'][$j] == $default_function)
                      ? 
' selected="selected"'
                      
'';
            if (
$op_spacing_needed == true) {
                
$retval .= '                ';
                
$retval .= '<option value="">--------</option>' "n";
                
$op_spacing_needed false;
            }

            
$retval .= '                ';
            
$retval .= '<option' $selected '>' $cfg['Functions'][$j]
                . 
'</option>' "n";
        }
    } 
// end for

    
return $retval;
// end PMA_getFunctionsForField()

/**
 * Checks if the current user has a specific privilege and returns true if the
 * user indeed has that privilege or false if (s)he doesn't. This function must
 * only be used for features that are available since MySQL 5, because it
 * relies on the INFORMATION_SCHEMA database to be present.
 *
 * Example:   PMA_currentUserHasPrivilege('CREATE ROUTINE', 'mydb');
 *            // Checks if the currently logged in user has the global
 *            // 'CREATE ROUTINE' privilege or, if not, checks if the
 *            // user has this privilege on database 'mydb'.
 *
 * @param string $priv The privilege to check
 * @param mixed  $db   null, to only check global privileges
 *                     string, db name where to also check for privileges
 * @param mixed  $tbl  null, to only check global/db privileges
 *                     string, table name where to also check for privileges
 *
 * @return bool
 */
function PMA_currentUserHasPrivilege($priv$db null$tbl null)
{
    
// Get the username for the current user in the format
    // required to use in the information schema database.
    
$user PMA_DBI_fetch_value("SELECT CURRENT_USER();");
    if (
$user === false) {
        return 
false;
    }
    
$user explode('@'$user);
    
$username  "''";
    
$username .= str_replace("'""''"$user[0]);
    
$username .= "''@''";
    
$username .= str_replace("'""''"$user[1]);
    
$username .= "''";
    
// Prepage the query
    
$query "SELECT `PRIVILEGE_TYPE` FROM `INFORMATION_SCHEMA`.`%s` "
           
"WHERE GRANTEE='%s' AND PRIVILEGE_TYPE='%s'";
    
// Check global privileges first.
    
if (PMA_DBI_fetch_value(
        
sprintf(
            
$query,
            
'USER_PRIVILEGES',
            
$username,
            
$priv
        
)
    )
    ) {
        return 
true;
    }
    
// If a database name was provided and user does not have the
    // required global privilege, try database-wise permissions.
    
if ($db !== null) {
        
// need to escape wildcards in db and table names, see bug #3518484
        
$db str_replace(array('%''_'), array('%''_'), $db);
        
$query .= " AND TABLE_SCHEMA='%s'";
        if (
PMA_DBI_fetch_value(
            
sprintf(
                
$query,
                
'SCHEMA_PRIVILEGES',
                
$username,
                
$priv,
                
PMA_sqlAddSlashes($db)
            )
        )
        ) {
            return 
true;
        }
    } else {
        
// There was no database name provided and the user
        // does not have the correct global privilege.
        
return false;
    }
    
// If a table name was also provided and we still didn't
    // find any valid privileges, try table-wise privileges.
    
if ($tbl !== null) {
        
// need to escape wildcards in db and table names, see bug #3518484
        
$tbl str_replace(array('%''_'), array('%''_'), $tbl);
        
$query .= " AND TABLE_NAME='%s'";
        if (
$retval PMA_DBI_fetch_value(
            
sprintf(
                
$query,
                
'TABLE_PRIVILEGES',
                
$username,
                
$priv,
                
PMA_sqlAddSlashes($db),
                
PMA_sqlAddSlashes($tbl)
            )
        )
        ) {
            return 
true;
        }
    }
    
// If we reached this point, the user does not
    // have even valid table-wise privileges.
    
return false;
}

/**
 * Returns server type for current connection
 *
 * Known types are: Drizzle, MariaDB and MySQL (default)
 *
 * @return string
 */
function PMA_getServerType()
{
    
$server_type 'MySQL';
    if (
PMA_DRIZZLE) {
        
$server_type 'Drizzle';
    } else if (
strpos(PMA_MYSQL_STR_VERSION'mariadb') !== false) {
        
$server_type 'MariaDB';
    } else if (
stripos(PMA_MYSQL_VERSION_COMMENT'percona') !== false) {
        
$server_type 'Percona Server';
    }
    return 
$server_type;
}

/**
 * Analyzes the limit clause and return the start and length attributes of it.
 *
 * @param string $limit_clause limit clause
 *
 * @return array Start and length attributes of the limit clause
 */
function PMA_analyzeLimitClause($limit_clause)
{
    
$start_and_length explode(','str_ireplace('LIMIT'''$limit_clause));
    return array(
        
'start'  => trim($start_and_length[0]),
        
'length' => trim($start_and_length[1])
    );
}

/**
 * Outputs HTML code for print button.
 *
 * @return nothing
 */
function PMA_printButton()
{
    echo 
'<p class="print_ignore">';
    echo 
'<input type="button" id="print" value="' __('Print') . '" />';
    echo 
'</p>';
}
?>
Онлайн: 0
Реклама