home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / phpMyAdmin / libraries / common.lib.php < prev    next >
Encoding:
PHP Script  |  2008-06-23  |  80.0 KB  |  2,364 lines

  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4.  * Misc functions used all over the scripts.
  5.  *
  6.  * @version $Id: common.lib.php 11299 2008-06-01 13:02:12Z lem9 $
  7.  */
  8.  
  9. /**
  10.  * Exponential expression / raise number into power
  11.  *
  12.  * @uses    function_exists()
  13.  * @uses    bcpow()
  14.  * @uses    gmp_pow()
  15.  * @uses    gmp_strval()
  16.  * @uses    pow()
  17.  * @param   number  $base
  18.  * @param   number  $exp
  19.  * @param   string  pow function use, or false for auto-detect
  20.  * @return  mixed  string or float
  21.  */
  22. function PMA_pow($base, $exp, $use_function = false)
  23. {
  24.     static $pow_function = null;
  25.  
  26.     if ($exp < 0) {
  27.         return false;
  28.     }
  29.  
  30.     if (null == $pow_function) {
  31.         if (function_exists('bcpow')) {
  32.             // BCMath Arbitrary Precision Mathematics Function
  33.             $pow_function = 'bcpow';
  34.         } elseif (function_exists('gmp_pow')) {
  35.             // GMP Function
  36.             $pow_function = 'gmp_pow';
  37.         } else {
  38.             // PHP function
  39.             $pow_function = 'pow';
  40.         }
  41.     }
  42.  
  43.     if (! $use_function) {
  44.         $use_function = $pow_function;
  45.     }
  46.  
  47.     switch ($use_function) {
  48.         case 'bcpow' :
  49.             //bcscale(10);
  50.             $pow = bcpow($base, $exp);
  51.             break;
  52.         case 'gmp_pow' :
  53.              $pow = gmp_strval(gmp_pow($base, $exp));
  54.             break;
  55.         case 'pow' :
  56.             $base = (float) $base;
  57.             $exp = (int) $exp;
  58.             $pow = pow($base, $exp);
  59.             break;
  60.         default:
  61.             $pow = $use_function($base, $exp);
  62.     }
  63.  
  64.     return $pow;
  65. }
  66.  
  67. /**
  68.  * string PMA_getIcon(string $icon)
  69.  *
  70.  * @uses    $GLOBALS['pmaThemeImage']
  71.  * @param   $icon   name of icon
  72.  * @return          html img tag
  73.  */
  74. function PMA_getIcon($icon, $alternate = '')
  75. {
  76.     if ($GLOBALS['cfg']['PropertiesIconic']) {
  77.         return '<img src="' . $GLOBALS['pmaThemeImage'] . $icon . '"'
  78.             . ' title="' . $alternate . '" alt="' . $alternate . '"'
  79.             . ' class="icon" width="16" height="16" />';
  80.     } else {
  81.         return $alternate;
  82.     }
  83. }
  84.  
  85. /**
  86.  * Displays the maximum size for an upload
  87.  *
  88.  * @uses    $GLOBALS['strMaximumSize']
  89.  * @uses    PMA_formatByteDown()
  90.  * @uses    sprintf()
  91.  * @param   integer  the size
  92.  *
  93.  * @return  string   the message
  94.  *
  95.  * @access  public
  96.  */
  97. function PMA_displayMaximumUploadSize($max_upload_size)
  98. {
  99.     list($max_size, $max_unit) = PMA_formatByteDown($max_upload_size);
  100.     return '(' . sprintf($GLOBALS['strMaximumSize'], $max_size, $max_unit) . ')';
  101. }
  102.  
  103. /**
  104.  * Generates a hidden field which should indicate to the browser
  105.  * the maximum size for upload
  106.  *
  107.  * @param   integer  the size
  108.  *
  109.  * @return  string   the INPUT field
  110.  *
  111.  * @access  public
  112.  */
  113.  function PMA_generateHiddenMaxFileSize($max_size)
  114.  {
  115.      return '<input type="hidden" name="MAX_FILE_SIZE" value="' .$max_size . '" />';
  116.  }
  117.  
  118. /**
  119.  * Add slashes before "'" and "\" characters so a value containing them can
  120.  * be used in a sql comparison.
  121.  *
  122.  * @uses    str_replace()
  123.  * @param   string   the string to slash
  124.  * @param   boolean  whether the string will be used in a 'LIKE' clause
  125.  *                   (it then requires two more escaped sequences) or not
  126.  * @param   boolean  whether to treat cr/lfs as escape-worthy entities
  127.  *                   (converts \n to \\n, \r to \\r)
  128.  *
  129.  * @param   boolean  whether this function is used as part of the
  130.  *                   "Create PHP code" dialog
  131.  *
  132.  * @return  string   the slashed string
  133.  *
  134.  * @access  public
  135.  */
  136. function PMA_sqlAddslashes($a_string = '', $is_like = false, $crlf = false, $php_code = false)
  137. {
  138.     if ($is_like) {
  139.         $a_string = str_replace('\\', '\\\\\\\\', $a_string);
  140.     } else {
  141.         $a_string = str_replace('\\', '\\\\', $a_string);
  142.     }
  143.  
  144.     if ($crlf) {
  145.         $a_string = str_replace("\n", '\n', $a_string);
  146.         $a_string = str_replace("\r", '\r', $a_string);
  147.         $a_string = str_replace("\t", '\t', $a_string);
  148.     }
  149.  
  150.     if ($php_code) {
  151.         $a_string = str_replace('\'', '\\\'', $a_string);
  152.     } else {
  153.         $a_string = str_replace('\'', '\'\'', $a_string);
  154.     }
  155.  
  156.     return $a_string;
  157. } // end of the 'PMA_sqlAddslashes()' function
  158.  
  159.  
  160. /**
  161.  * Add slashes before "_" and "%" characters for using them in MySQL
  162.  * database, table and field names.
  163.  * Note: This function does not escape backslashes!
  164.  *
  165.  * @uses    str_replace()
  166.  * @param   string   the string to escape
  167.  *
  168.  * @return  string   the escaped string
  169.  *
  170.  * @access  public
  171.  */
  172. function PMA_escape_mysql_wildcards($name)
  173. {
  174.     $name = str_replace('_', '\\_', $name);
  175.     $name = str_replace('%', '\\%', $name);
  176.  
  177.     return $name;
  178. } // end of the 'PMA_escape_mysql_wildcards()' function
  179.  
  180. /**
  181.  * removes slashes before "_" and "%" characters
  182.  * Note: This function does not unescape backslashes!
  183.  *
  184.  * @uses    str_replace()
  185.  * @param   string   $name  the string to escape
  186.  * @return  string   the escaped string
  187.  * @access  public
  188.  */
  189. function PMA_unescape_mysql_wildcards($name)
  190. {
  191.     $name = str_replace('\\_', '_', $name);
  192.     $name = str_replace('\\%', '%', $name);
  193.  
  194.     return $name;
  195. } // end of the 'PMA_unescape_mysql_wildcards()' function
  196.  
  197. /**
  198.  * removes quotes (',",`) from a quoted string
  199.  *
  200.  * checks if the sting is quoted and removes this quotes
  201.  *
  202.  * @uses    str_replace()
  203.  * @uses    substr()
  204.  * @param   string  $quoted_string  string to remove quotes from
  205.  * @param   string  $quote          type of quote to remove
  206.  * @return  string  unqoted string
  207.  */
  208. function PMA_unQuote($quoted_string, $quote = null)
  209. {
  210.     $quotes = array();
  211.  
  212.     if (null === $quote) {
  213.         $quotes[] = '`';
  214.         $quotes[] = '"';
  215.         $quotes[] = "'";
  216.     } else {
  217.         $quotes[] = $quote;
  218.     }
  219.  
  220.     foreach ($quotes as $quote) {
  221.         if (substr($quoted_string, 0, 1) === $quote
  222.          && substr($quoted_string, -1, 1) === $quote) {
  223.              $unquoted_string = substr($quoted_string, 1, -1);
  224.              // replace escaped quotes
  225.              $unquoted_string = str_replace($quote . $quote, $quote, $unquoted_string);
  226.              return $unquoted_string;
  227.          }
  228.     }
  229.  
  230.     return $quoted_string;
  231. }
  232.  
  233. /**
  234.  * format sql strings
  235.  *
  236.  * @todo    move into PMA_Sql
  237.  * @uses    PMA_SQP_isError()
  238.  * @uses    PMA_SQP_formatHtml()
  239.  * @uses    PMA_SQP_formatNone()
  240.  * @uses    is_array()
  241.  * @param   mixed    pre-parsed SQL structure
  242.  *
  243.  * @return  string   the formatted sql
  244.  *
  245.  * @global  array    the configuration array
  246.  * @global  boolean  whether the current statement is a multiple one or not
  247.  *
  248.  * @access  public
  249.  *
  250.  * @author  Robin Johnson <robbat2@users.sourceforge.net>
  251.  */
  252. function PMA_formatSql($parsed_sql, $unparsed_sql = '')
  253. {
  254.     global $cfg;
  255.  
  256.     // Check that we actually have a valid set of parsed data
  257.     // well, not quite
  258.     // first check for the SQL parser having hit an error
  259.     if (PMA_SQP_isError()) {
  260.         return $parsed_sql;
  261.     }
  262.     // then check for an array
  263.     if (!is_array($parsed_sql)) {
  264.         // We don't so just return the input directly
  265.         // This is intended to be used for when the SQL Parser is turned off
  266.         $formatted_sql = '<pre>' . "\n"
  267.                         . (($cfg['SQP']['fmtType'] == 'none' && $unparsed_sql != '') ? $unparsed_sql : $parsed_sql) . "\n"
  268.                         . '</pre>';
  269.         return $formatted_sql;
  270.     }
  271.  
  272.     $formatted_sql        = '';
  273.  
  274.     switch ($cfg['SQP']['fmtType']) {
  275.         case 'none':
  276.             if ($unparsed_sql != '') {
  277.                 $formatted_sql = "<pre>\n" . PMA_SQP_formatNone(array('raw' => $unparsed_sql)) . "\n</pre>";
  278.             } else {
  279.                 $formatted_sql = PMA_SQP_formatNone($parsed_sql);
  280.             }
  281.             break;
  282.         case 'html':
  283.             $formatted_sql = PMA_SQP_formatHtml($parsed_sql, 'color');
  284.             break;
  285.         case 'text':
  286.             //$formatted_sql = PMA_SQP_formatText($parsed_sql);
  287.             $formatted_sql = PMA_SQP_formatHtml($parsed_sql, 'text');
  288.             break;
  289.         default:
  290.             break;
  291.     } // end switch
  292.  
  293.     return $formatted_sql;
  294. } // end of the "PMA_formatSql()" function
  295.  
  296.  
  297. /**
  298.  * Displays a link to the official MySQL documentation
  299.  *
  300.  * @uses    $cfg['MySQLManualType']
  301.  * @uses    $cfg['MySQLManualBase']
  302.  * @uses    $cfg['ReplaceHelpImg']
  303.  * @uses    $GLOBALS['mysql_4_1_doc_lang']
  304.  * @uses    $GLOBALS['mysql_5_1_doc_lang']
  305.  * @uses    $GLOBALS['mysql_5_0_doc_lang']
  306.  * @uses    $GLOBALS['strDocu']
  307.  * @uses    $GLOBALS['pmaThemeImage']
  308.  * @uses    PMA_MYSQL_INT_VERSION
  309.  * @uses    strtolower()
  310.  * @uses    str_replace()
  311.  * @param string  chapter of "HTML, one page per chapter" documentation
  312.  * @param string  contains name of page/anchor that is being linked
  313.  * @param bool    whether to use big icon (like in left frame)
  314.  *
  315.  * @return  string  the html link
  316.  *
  317.  * @access  public
  318.  */
  319. function PMA_showMySQLDocu($chapter, $link, $big_icon = false)
  320. {
  321.     global $cfg;
  322.  
  323.     if ($cfg['MySQLManualType'] == 'none' || empty($cfg['MySQLManualBase'])) {
  324.         return '';
  325.     }
  326.  
  327.     // Fixup for newly used names:
  328.     $chapter = str_replace('_', '-', strtolower($chapter));
  329.     $link = str_replace('_', '-', strtolower($link));
  330.  
  331.     switch ($cfg['MySQLManualType']) {
  332.         case 'chapters':
  333.             if (empty($chapter)) {
  334.                 $chapter = 'index';
  335.             }
  336.             $url = $cfg['MySQLManualBase'] . '/' . $chapter . '.html#' . $link;
  337.             break;
  338.         case 'big':
  339.             $url = $cfg['MySQLManualBase'] . '#' . $link;
  340.             break;
  341.         case 'searchable':
  342.             if (empty($link)) {
  343.                 $link = 'index';
  344.             }
  345.             $url = $cfg['MySQLManualBase'] . '/' . $link . '.html';
  346.             break;
  347.         case 'viewable':
  348.         default:
  349.             if (empty($link)) {
  350.                 $link = 'index';
  351.             }
  352.             $mysql = '5.0';
  353.             $lang = 'en';
  354.             if (defined('PMA_MYSQL_INT_VERSION')) {
  355.                 if (PMA_MYSQL_INT_VERSION < 50000) {
  356.                     $mysql = '4.1';
  357.                     if (!empty($GLOBALS['mysql_4_1_doc_lang'])) {
  358.                         $lang = $GLOBALS['mysql_4_1_doc_lang'];
  359.                     }
  360.                 } elseif (PMA_MYSQL_INT_VERSION >= 50100) {
  361.                     $mysql = '5.1';
  362.                     if (!empty($GLOBALS['mysql_5_1_doc_lang'])) {
  363.                         $lang = $GLOBALS['mysql_5_1_doc_lang'];
  364.                     }
  365.                 } elseif (PMA_MYSQL_INT_VERSION >= 50000) {
  366.                     $mysql = '5.0';
  367.                     if (!empty($GLOBALS['mysql_5_0_doc_lang'])) {
  368.                         $lang = $GLOBALS['mysql_5_0_doc_lang'];
  369.                     }
  370.                 }
  371.             }
  372.             $url = $cfg['MySQLManualBase'] . '/' . $mysql . '/' . $lang . '/' . $link . '.html';
  373.             break;
  374.     }
  375.  
  376.     if ($big_icon) {
  377.         return '<a href="' . $url . '" target="mysql_doc"><img class="icon" src="' . $GLOBALS['pmaThemeImage'] . 'b_sqlhelp.png" width="16" height="16" alt="' . $GLOBALS['strDocu'] . '" title="' . $GLOBALS['strDocu'] . '" /></a>';
  378.     } elseif ($GLOBALS['cfg']['ReplaceHelpImg']) {
  379.         return '<a href="' . $url . '" target="mysql_doc"><img class="icon" src="' . $GLOBALS['pmaThemeImage'] . 'b_help.png" width="11" height="11" alt="' . $GLOBALS['strDocu'] . '" title="' . $GLOBALS['strDocu'] . '" /></a>';
  380.     } else {
  381.         return '[<a href="' . $url . '" target="mysql_doc">' . $GLOBALS['strDocu'] . '</a>]';
  382.     }
  383. } // end of the 'PMA_showMySQLDocu()' function
  384.  
  385. /**
  386.  * Displays a hint icon, on mouse over show the hint
  387.  *
  388.  * @uses    $GLOBALS['pmaThemeImage']
  389.  * @uses    PMA_jsFormat()
  390.  * @param   string   the error message
  391.  *
  392.  * @access  public
  393.  */
  394. function PMA_showHint($hint_message)
  395. {
  396.     //return '<img class="lightbulb" src="' . $GLOBALS['pmaThemeImage'] . 'b_tipp.png" width="16" height="16" border="0" alt="' . $hint_message . '" title="' . $hint_message . '" align="middle" onclick="alert(\'' . PMA_jsFormat($hint_message, false) . '\');" />';
  397.     return '<img class="lightbulb" src="' . $GLOBALS['pmaThemeImage']
  398.         . 'b_tipp.png" width="16" height="16" alt="Tip" title="Tip" onmouseover="pmaTooltip(\''
  399.         .  PMA_jsFormat($hint_message, false) . '\'); return false;" onmouseout="swapTooltip(\'default\'); return false;" />';
  400. }
  401.  
  402. /**
  403.  * Displays a MySQL error message in the right frame.
  404.  *
  405.  * @uses    footer.inc.php
  406.  * @uses    header.inc.php
  407.  * @uses    $GLOBALS['sql_query']
  408.  * @uses    $GLOBALS['strError']
  409.  * @uses    $GLOBALS['strSQLQuery']
  410.  * @uses    $GLOBALS['pmaThemeImage']
  411.  * @uses    $GLOBALS['strEdit']
  412.  * @uses    $GLOBALS['strMySQLSaid']
  413.  * @uses    $GLOBALS['cfg']['PropertiesIconic'] 
  414.  * @uses    $GLOBALS['cfg']['MaxCharactersInDisplayedSQL'] 
  415.  * @uses    PMA_backquote()
  416.  * @uses    PMA_DBI_getError()
  417.  * @uses    PMA_formatSql()
  418.  * @uses    PMA_generate_common_hidden_inputs()
  419.  * @uses    PMA_generate_common_url()
  420.  * @uses    PMA_showMySQLDocu()
  421.  * @uses    PMA_sqlAddslashes()
  422.  * @uses    PMA_SQP_isError()
  423.  * @uses    PMA_SQP_parse()
  424.  * @uses    PMA_SQP_getErrorString()
  425.  * @uses    strtolower()
  426.  * @uses    urlencode()
  427.  * @uses    str_replace()
  428.  * @uses    nl2br()
  429.  * @uses    substr()
  430.  * @uses    preg_replace()
  431.  * @uses    preg_match()
  432.  * @uses    explode()
  433.  * @uses    implode()
  434.  * @uses    is_array()
  435.  * @uses    function_exists()
  436.  * @uses    htmlspecialchars()
  437.  * @uses    trim()
  438.  * @uses    strstr()
  439.  * @param   string   the error message
  440.  * @param   string   the sql query that failed
  441.  * @param   boolean  whether to show a "modify" link or not
  442.  * @param   string   the "back" link url (full path is not required)
  443.  * @param   boolean  EXIT the page?
  444.  *
  445.  * @global  string    the curent table
  446.  * @global  string    the current db
  447.  *
  448.  * @access  public
  449.  */
  450. function PMA_mysqlDie($error_message = '', $the_query = '',
  451.                         $is_modify_link = true, $back_url = '', $exit = true)
  452. {
  453.     global $table, $db;
  454.  
  455.     /**
  456.      * start http output, display html headers
  457.      */
  458.     require_once './libraries/header.inc.php';
  459.  
  460.     if (!$error_message) {
  461.         $error_message = PMA_DBI_getError();
  462.     }
  463.     if (!$the_query && !empty($GLOBALS['sql_query'])) {
  464.         $the_query = $GLOBALS['sql_query'];
  465.     }
  466.  
  467.     // --- Added to solve bug #641765
  468.     // Robbat2 - 12 January 2003, 9:46PM
  469.     // Revised, Robbat2 - 13 January 2003, 2:59PM
  470.     if (!function_exists('PMA_SQP_isError') || PMA_SQP_isError()) {
  471.         $formatted_sql = htmlspecialchars($the_query);
  472.     } elseif (empty($the_query) || trim($the_query) == '') {
  473.         $formatted_sql = '';
  474.     } else {
  475.         if (strlen($the_query) > $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) {
  476.             $formatted_sql = substr($the_query, 0, $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) . '[...]';
  477.         } else {
  478.             $formatted_sql = PMA_formatSql(PMA_SQP_parse($the_query), $the_query);
  479.         }
  480.     }
  481.     // ---
  482.     echo "\n" . '<!-- PMA-SQL-ERROR -->' . "\n";
  483.     echo '    <div class="error"><h1>' . $GLOBALS['strError'] . '</h1>' . "\n";
  484.     // if the config password is wrong, or the MySQL server does not
  485.     // respond, do not show the query that would reveal the
  486.     // username/password
  487.     if (!empty($the_query) && !strstr($the_query, 'connect')) {
  488.         // --- Added to solve bug #641765
  489.         // Robbat2 - 12 January 2003, 9:46PM
  490.         // Revised, Robbat2 - 13 January 2003, 2:59PM
  491.         if (function_exists('PMA_SQP_isError') && PMA_SQP_isError()) {
  492.             echo PMA_SQP_getErrorString() . "\n";
  493.             echo '<br />' . "\n";
  494.         }
  495.         // ---
  496.         // modified to show me the help on sql errors (Michael Keck)
  497.         echo '    <p><strong>' . $GLOBALS['strSQLQuery'] . ':</strong>' . "\n";
  498.         if (strstr(strtolower($formatted_sql), 'select')) { // please show me help to the error on select
  499.             echo PMA_showMySQLDocu('SQL-Syntax', 'SELECT');
  500.         }
  501.         if ($is_modify_link && strlen($db)) {
  502.             if (strlen($table)) {
  503.                 $doedit_goto = '<a href="tbl_sql.php?' . PMA_generate_common_url($db, $table) . '&sql_query=' . urlencode($the_query) . '&show_query=1">';
  504.             } else {
  505.                 $doedit_goto = '<a href="db_sql.php?' . PMA_generate_common_url($db) . '&sql_query=' . urlencode($the_query) . '&show_query=1">';
  506.             }
  507.             if ($GLOBALS['cfg']['PropertiesIconic']) {
  508.                 echo $doedit_goto
  509.                    . '<img class="icon" src=" '. $GLOBALS['pmaThemeImage'] . 'b_edit.png" width="16" height="16" alt="' . $GLOBALS['strEdit'] .'" />'
  510.                    . '</a>';
  511.             } else {
  512.                 echo '    ['
  513.                    . $doedit_goto . $GLOBALS['strEdit'] . '</a>'
  514.                    . ']' . "\n";
  515.             }
  516.         } // end if
  517.         echo '    </p>' . "\n"
  518.             .'    <p>' . "\n"
  519.             .'        ' . $formatted_sql . "\n"
  520.             .'    </p>' . "\n";
  521.     } // end if
  522.  
  523.     $tmp_mysql_error = ''; // for saving the original $error_message
  524.     if (!empty($error_message)) {
  525.         $tmp_mysql_error = strtolower($error_message); // save the original $error_message
  526.         $error_message = htmlspecialchars($error_message);
  527.         $error_message = preg_replace("@((\015\012)|(\015)|(\012)){3,}@", "\n\n", $error_message);
  528.     }
  529.     // modified to show me the help on error-returns (Michael Keck)
  530.     // (now error-messages-server)
  531.     echo '<p>' . "\n"
  532.             . '    <strong>' . $GLOBALS['strMySQLSaid'] . '</strong>'
  533.             . PMA_showMySQLDocu('Error-messages-server', 'Error-messages-server')
  534.             . "\n"
  535.             . '</p>' . "\n";
  536.  
  537.     // The error message will be displayed within a CODE segment.
  538.     // To preserve original formatting, but allow wordwrapping, we do a couple of replacements
  539.  
  540.     // Replace all non-single blanks with their HTML-counterpart
  541.     $error_message = str_replace('  ', '  ', $error_message);
  542.     // Replace TAB-characters with their HTML-counterpart
  543.     $error_message = str_replace("\t", '    ', $error_message);
  544.     // Replace linebreaks
  545.     $error_message = nl2br($error_message);
  546.  
  547.     echo '<code>' . "\n"
  548.         . $error_message . "\n"
  549.         . '</code><br />' . "\n";
  550.     echo '</div>';
  551.     echo '<fieldset class="tblFooters">';
  552.  
  553.     if (!empty($back_url) && $exit) {
  554.         $goto_back_url='<a href="' . (strstr($back_url, '?') ? $back_url . '&no_history=true' : $back_url . '?no_history=true') . '">';
  555.         echo '[ ' . $goto_back_url . $GLOBALS['strBack'] . '</a> ]';
  556.     }
  557.     echo '    </fieldset>' . "\n\n";
  558.     if ($exit) {
  559.         /**
  560.          * display footer and exit
  561.          */
  562.         require_once './libraries/footer.inc.php';
  563.     }
  564. } // end of the 'PMA_mysqlDie()' function
  565.  
  566. /**
  567.  * Returns a string formatted with CONVERT ... USING
  568.  * if MySQL supports it
  569.  *
  570.  * @uses    PMA_MYSQL_INT_VERSION
  571.  * @uses    $GLOBALS['collation_connection']
  572.  * @uses    explode()
  573.  * @param   string  the string itself
  574.  * @param   string  the mode: quoted or unquoted (this one by default)
  575.  *
  576.  * @return  the formatted string
  577.  *
  578.  * @access  private
  579.  */
  580. function PMA_convert_using($string, $mode='unquoted', $force_utf8 = false)
  581. {
  582.     if ($mode == 'quoted') {
  583.         $possible_quote = "'";
  584.     } else {
  585.         $possible_quote = "";
  586.     }
  587.  
  588.     if (PMA_MYSQL_INT_VERSION >= 40100) {
  589.         if ($force_utf8) {
  590.             $charset = 'utf8';
  591.             $collate = ' COLLATE utf8_bin';
  592.         } else {
  593.             list($charset) = explode('_', $GLOBALS['collation_connection']);
  594.             $collate = '';
  595.         }
  596.         $converted_string = "CONVERT(" . $possible_quote . $string . $possible_quote . " USING " . $charset . ")" . $collate;
  597.     } else {
  598.         $converted_string = $possible_quote . $string . $possible_quote;
  599.     }
  600.     return $converted_string;
  601. } // end function
  602.  
  603. /**
  604.  * Send HTTP header, taking IIS limits into account (600 seems ok)
  605.  *
  606.  * @uses    PMA_IS_IIS
  607.  * @uses    PMA_COMING_FROM_COOKIE_LOGIN
  608.  * @uses    PMA_get_arg_separator()
  609.  * @uses    SID
  610.  * @uses    strlen()
  611.  * @uses    strpos()
  612.  * @uses    header()
  613.  * @uses    session_write_close()
  614.  * @uses    headers_sent()
  615.  * @uses    function_exists()
  616.  * @uses    debug_print_backtrace()
  617.  * @uses    trigger_error()
  618.  * @uses    defined()
  619.  * @param   string   $uri the header to send
  620.  * @return  boolean  always true
  621.  */
  622. function PMA_sendHeaderLocation($uri)
  623. {
  624.     if (PMA_IS_IIS && strlen($uri) > 600) {
  625.  
  626.         echo '<html><head><title>- - -</title>' . "\n";
  627.         echo '<meta http-equiv="expires" content="0">' . "\n";
  628.         echo '<meta http-equiv="Pragma" content="no-cache">' . "\n";
  629.         echo '<meta http-equiv="Cache-Control" content="no-cache">' . "\n";
  630.         echo '<meta http-equiv="Refresh" content="0;url=' .$uri . '">' . "\n";
  631.         echo '<script type="text/javascript">' . "\n";
  632.         echo '//<![CDATA[' . "\n";
  633.         echo 'setTimeout("window.location = unescape(\'"' . $uri . '"\')", 2000);' . "\n";
  634.         echo '//]]>' . "\n";
  635.         echo '</script>' . "\n";
  636.         echo '</head>' . "\n";
  637.         echo '<body>' . "\n";
  638.         echo '<script type="text/javascript">' . "\n";
  639.         echo '//<![CDATA[' . "\n";
  640.         echo 'document.write(\'<p><a href="' . $uri . '">' . $GLOBALS['strGo'] . '</a></p>\');' . "\n";
  641.         echo '//]]>' . "\n";
  642.         echo '</script></body></html>' . "\n";
  643.  
  644.     } else {
  645.         if (SID) {
  646.             if (strpos($uri, '?') === false) {
  647.                 header('Location: ' . $uri . '?' . SID);
  648.             } else {
  649.                 $separator = PMA_get_arg_separator();
  650.                 header('Location: ' . $uri . $separator . SID);
  651.             }
  652.         } else {
  653.             session_write_close();
  654.             if (headers_sent()) {
  655.                 if (function_exists('debug_print_backtrace')) {
  656.                     echo '<pre>';
  657.                     debug_print_backtrace();
  658.                     echo '</pre>';
  659.                 }
  660.                 trigger_error('PMA_sendHeaderLocation called when headers are already sent!', E_USER_ERROR);
  661.             }
  662.             // bug #1523784: IE6 does not like 'Refresh: 0', it
  663.             // results in a blank page
  664.             // but we need it when coming from the cookie login panel)
  665.             if (PMA_IS_IIS && defined('PMA_COMING_FROM_COOKIE_LOGIN')) {
  666.                 header('Refresh: 0; ' . $uri);
  667.             } else {
  668.                 header('Location: ' . $uri);
  669.             }
  670.         }
  671.     }
  672. }
  673.  
  674. /**
  675.  * returns array with tables of given db with extended information and grouped
  676.  *
  677.  * @uses    $cfg['LeftFrameTableSeparator']
  678.  * @uses    $cfg['LeftFrameTableLevel']
  679.  * @uses    $cfg['ShowTooltipAliasTB']
  680.  * @uses    $cfg['NaturalOrder']
  681.  * @uses    PMA_backquote()
  682.  * @uses    count()
  683.  * @uses    array_merge
  684.  * @uses    uksort()
  685.  * @uses    strstr()
  686.  * @uses    explode()
  687.  * @param   string  $db     name of db
  688.  * @param   string  $tables name of tables
  689.  * return   array   (recursive) grouped table list
  690.  */
  691. function PMA_getTableList($db, $tables = null, $limit_offset = 0, $limit_count = false)
  692. {
  693.     $sep = $GLOBALS['cfg']['LeftFrameTableSeparator'];
  694.  
  695.     if (null === $tables) {
  696.         $tables = PMA_DBI_get_tables_full($db, false, false, null, $limit_offset, $limit_count);
  697.         if ($GLOBALS['cfg']['NaturalOrder']) {
  698.             uksort($tables, 'strnatcasecmp');
  699.         }
  700.     }
  701.  
  702.     if (count($tables) < 1) {
  703.         return $tables;
  704.     }
  705.  
  706.     $default = array(
  707.         'Name'      => '',
  708.         'Rows'      => 0,
  709.         'Comment'   => '',
  710.         'disp_name' => '',
  711.     );
  712.  
  713.     $table_groups = array();
  714.  
  715.     foreach ($tables as $table_name => $table) {
  716.  
  717.         // check for correct row count
  718.         if (null === $table['Rows']) {
  719.             // Do not check exact row count here,
  720.             // if row count is invalid possibly the table is defect
  721.             // and this would break left frame;
  722.             // but we can check row count if this is a view,
  723.             // since PMA_Table::countRecords() returns a limited row count
  724.             // in this case.
  725.  
  726.             // set this because PMA_Table::countRecords() can use it
  727.             $tbl_is_view = PMA_Table::isView($db, $table['Name']);
  728.  
  729.             if ($tbl_is_view) {
  730.                 $table['Rows'] = PMA_Table::countRecords($db, $table['Name'],
  731.                     $return = true);
  732.             }
  733.         }
  734.  
  735.         // in $group we save the reference to the place in $table_groups
  736.         // where to store the table info
  737.         if ($GLOBALS['cfg']['LeftFrameDBTree']
  738.             && $sep && strstr($table_name, $sep))
  739.         {
  740.             $parts = explode($sep, $table_name);
  741.  
  742.             $group =& $table_groups;
  743.             $i = 0;
  744.             $group_name_full = '';
  745.             while ($i < count($parts) - 1
  746.               && $i < $GLOBALS['cfg']['LeftFrameTableLevel']) {
  747.                 $group_name = $parts[$i] . $sep;
  748.                 $group_name_full .= $group_name;
  749.  
  750.                 if (!isset($group[$group_name])) {
  751.                     $group[$group_name] = array();
  752.                     $group[$group_name]['is' . $sep . 'group'] = true;
  753.                     $group[$group_name]['tab' . $sep . 'count'] = 1;
  754.                     $group[$group_name]['tab' . $sep . 'group'] = $group_name_full;
  755.                 } elseif (!isset($group[$group_name]['is' . $sep . 'group'])) {
  756.                     $table = $group[$group_name];
  757.                     $group[$group_name] = array();
  758.                     $group[$group_name][$group_name] = $table;
  759.                     unset($table);
  760.                     $group[$group_name]['is' . $sep . 'group'] = true;
  761.                     $group[$group_name]['tab' . $sep . 'count'] = 1;
  762.                     $group[$group_name]['tab' . $sep . 'group'] = $group_name_full;
  763.                 } else {
  764.                     $group[$group_name]['tab' . $sep . 'count']++;
  765.                 }
  766.                 $group =& $group[$group_name];
  767.                 $i++;
  768.             }
  769.         } else {
  770.             if (!isset($table_groups[$table_name])) {
  771.                 $table_groups[$table_name] = array();
  772.             }
  773.             $group =& $table_groups;
  774.         }
  775.  
  776.  
  777.         if ($GLOBALS['cfg']['ShowTooltipAliasTB']
  778.           && $GLOBALS['cfg']['ShowTooltipAliasTB'] !== 'nested') {
  779.             // switch tooltip and name
  780.             $table['Comment'] = $table['Name'];
  781.             $table['disp_name'] = $table['Comment'];
  782.         } else {
  783.             $table['disp_name'] = $table['Name'];
  784.         }
  785.  
  786.         $group[$table_name] = array_merge($default, $table);
  787.     }
  788.  
  789.     return $table_groups;
  790. }
  791.  
  792. /* ----------------------- Set of misc functions ----------------------- */
  793.  
  794.  
  795. /**
  796.  * Adds backquotes on both sides of a database, table or field name.
  797.  * and escapes backquotes inside the name with another backquote
  798.  *
  799.  * example:
  800.  * <code>
  801.  * echo PMA_backquote('owner`s db'); // `owner``s db`
  802.  *
  803.  * </code>
  804.  *
  805.  * @uses    PMA_backquote()
  806.  * @uses    is_array()
  807.  * @uses    strlen()
  808.  * @uses    str_replace()
  809.  * @param   mixed    $a_name    the database, table or field name to "backquote"
  810.  *                              or array of it
  811.  * @param   boolean  $do_it     a flag to bypass this function (used by dump
  812.  *                              functions)
  813.  * @return  mixed    the "backquoted" database, table or field name if the
  814.  *                   current MySQL release is >= 3.23.6, the original one
  815.  *                   else
  816.  * @access  public
  817.  */
  818. function PMA_backquote($a_name, $do_it = true)
  819. {
  820.     if (! $do_it) {
  821.         return $a_name;
  822.     }
  823.  
  824.     if (is_array($a_name)) {
  825.          $result = array();
  826.          foreach ($a_name as $key => $val) {
  827.              $result[$key] = PMA_backquote($val);
  828.          }
  829.          return $result;
  830.     }
  831.  
  832.     // '0' is also empty for php :-(
  833.     if (strlen($a_name) && $a_name !== '*') {
  834.         return '`' . str_replace('`', '``', $a_name) . '`';
  835.     } else {
  836.         return $a_name;
  837.     }
  838. } // end of the 'PMA_backquote()' function
  839.  
  840.  
  841. /**
  842.  * Defines the <CR><LF> value depending on the user OS.
  843.  *
  844.  * @uses    PMA_USR_OS
  845.  * @return  string   the <CR><LF> value to use
  846.  *
  847.  * @access  public
  848.  */
  849. function PMA_whichCrlf()
  850. {
  851.     $the_crlf = "\n";
  852.  
  853.     // The 'PMA_USR_OS' constant is defined in "./libraries/Config.class.php"
  854.     // Win case
  855.     if (PMA_USR_OS == 'Win') {
  856.         $the_crlf = "\r\n";
  857.     }
  858.     // Others
  859.     else {
  860.         $the_crlf = "\n";
  861.     }
  862.  
  863.     return $the_crlf;
  864. } // end of the 'PMA_whichCrlf()' function
  865.  
  866. /**
  867.  * Reloads navigation if needed.
  868.  *
  869.  * @uses    $GLOBALS['reload']
  870.  * @uses    $GLOBALS['db']
  871.  * @uses    PMA_generate_common_url()
  872.  * @global  array  configuration
  873.  *
  874.  * @access  public
  875.  */
  876. function PMA_reloadNavigation()
  877. {
  878.     global $cfg;
  879.  
  880.     // Reloads the navigation frame via JavaScript if required
  881.     if (isset($GLOBALS['reload']) && $GLOBALS['reload']) {
  882.         // one of the reasons for a reload is when a table is dropped
  883.         // in this case, get rid of the table limit offset, otherwise
  884.         // we have a problem when dropping a table on the last page
  885.         // and the offset becomes greater than the total number of tables
  886.         unset($_SESSION['userconf']['table_limit_offset']);
  887.         echo "\n";
  888.         $reload_url = './navigation.php?' . PMA_generate_common_url($GLOBALS['db'], '', '&');
  889.         ?>
  890. <script type="text/javascript">
  891. //<![CDATA[
  892. if (typeof(window.parent) != 'undefined'
  893.     && typeof(window.parent.frame_navigation) != 'undefined') {
  894.     window.parent.goTo('<?php echo $reload_url; ?>');
  895. }
  896. //]]>
  897. </script>
  898.         <?php
  899.         unset($GLOBALS['reload']);
  900.     }
  901. }
  902.  
  903. /**
  904.  * displays the message and the query
  905.  * usually the message is the result of the query executed
  906.  *
  907.  * @param   string  $message    the message to display
  908.  * @param   string  $sql_query  the query to display
  909.  * @global  array   the configuration array
  910.  * @uses    $cfg
  911.  * @access  public
  912.  */
  913. function PMA_showMessage($message, $sql_query = null)
  914. {
  915.     global $cfg;
  916.     $query_too_big = false;
  917.  
  918.     if (null === $sql_query) {
  919.         if (! empty($GLOBALS['display_query'])) {
  920.             $sql_query = $GLOBALS['display_query'];
  921.         } elseif ($cfg['SQP']['fmtType'] == 'none' && ! empty($GLOBALS['unparsed_sql'])) {
  922.             $sql_query = $GLOBALS['unparsed_sql'];
  923.         } elseif (! empty($GLOBALS['sql_query'])) {
  924.             $sql_query = $GLOBALS['sql_query'];
  925.         } else {
  926.             $sql_query = '';
  927.         }
  928.     }
  929.  
  930.     // Corrects the tooltip text via JS if required
  931.     // @todo this is REALLY the wrong place to do this - very unexpected here
  932.     if (strlen($GLOBALS['table']) && $cfg['ShowTooltip']) {
  933.         $result = PMA_DBI_try_query('SHOW TABLE STATUS FROM ' . PMA_backquote($GLOBALS['db']) . ' LIKE \'' . PMA_sqlAddslashes($GLOBALS['table'], true) . '\'');
  934.         if ($result) {
  935.             $tbl_status = PMA_DBI_fetch_assoc($result);
  936.             $tooltip    = (empty($tbl_status['Comment']))
  937.                         ? ''
  938.                         : $tbl_status['Comment'] . ' ';
  939.             $tooltip .= '(' . PMA_formatNumber($tbl_status['Rows'], 0) . ' ' . $GLOBALS['strRows'] . ')';
  940.             PMA_DBI_free_result($result);
  941.             $uni_tbl = PMA_jsFormat($GLOBALS['db'] . '.' . $GLOBALS['table'], false);
  942.             echo "\n";
  943.             echo '<script type="text/javascript">' . "\n";
  944.             echo '//<![CDATA[' . "\n";
  945.             echo "window.parent.updateTableTitle('" . $uni_tbl . "', '" . PMA_jsFormat($tooltip, false) . "');" . "\n";
  946.             echo '//]]>' . "\n";
  947.             echo '</script>' . "\n";
  948.         } // end if
  949.     } // end if ... elseif
  950.  
  951.     // Checks if the table needs to be repaired after a TRUNCATE query.
  952.     // @todo what about $GLOBALS['display_query']???
  953.     // @todo this is REALLY the wrong place to do this - very unexpected here
  954.     if (strlen($GLOBALS['table'])
  955.      && $GLOBALS['sql_query'] == 'TRUNCATE TABLE ' . PMA_backquote($GLOBALS['table'])) {
  956.         if (!isset($tbl_status)) {
  957.             $result = @PMA_DBI_try_query('SHOW TABLE STATUS FROM ' . PMA_backquote($GLOBALS['db']) . ' LIKE \'' . PMA_sqlAddslashes($GLOBALS['table'], true) . '\'');
  958.             if ($result) {
  959.                 $tbl_status = PMA_DBI_fetch_assoc($result);
  960.                 PMA_DBI_free_result($result);
  961.             }
  962.         }
  963.         if (isset($tbl_status) && (int) $tbl_status['Index_length'] > 1024) {
  964.             PMA_DBI_try_query('REPAIR TABLE ' . PMA_backquote($GLOBALS['table']));
  965.         }
  966.     }
  967.     unset($tbl_status);
  968.     echo '<br />' . "\n";
  969.  
  970.     echo '<div align="' . $GLOBALS['cell_align_left'] . '">' . "\n";
  971.     if (!empty($GLOBALS['show_error_header'])) {
  972.         echo '<div class="error">' . "\n";
  973.         echo '<h1>' . $GLOBALS['strError'] . '</h1>' . "\n";
  974.     }
  975.  
  976.     echo '<div class="notice">';
  977.     echo PMA_sanitize($message);
  978.     if (isset($GLOBALS['special_message'])) {
  979.         echo PMA_sanitize($GLOBALS['special_message']);
  980.         unset($GLOBALS['special_message']);
  981.     }
  982.     echo '</div>';
  983.  
  984.     if (!empty($GLOBALS['show_error_header'])) {
  985.         echo '</div>';
  986.     }
  987.  
  988.     if ($cfg['ShowSQL'] == true && ! empty($sql_query)) {
  989.         // Basic url query part
  990.         $url_qpart = '?' . PMA_generate_common_url($GLOBALS['db'], $GLOBALS['table']);
  991.  
  992.         // Html format the query to be displayed
  993.         // The nl2br function isn't used because its result isn't a valid
  994.         // xhtml1.0 statement before php4.0.5 ("<br>" and not "<br />")
  995.         // If we want to show some sql code it is easiest to create it here
  996.          /* SQL-Parser-Analyzer */
  997.  
  998.         if (!empty($GLOBALS['show_as_php'])) {
  999.             $new_line = '\'<br />' . "\n" . '        . \' ';
  1000.         }
  1001.         if (isset($new_line)) {
  1002.              /* SQL-Parser-Analyzer */
  1003.             $query_base = PMA_sqlAddslashes(htmlspecialchars($sql_query), false, false, true);
  1004.              /* SQL-Parser-Analyzer */
  1005.             $query_base = preg_replace("@((\015\012)|(\015)|(\012))+@", $new_line, $query_base);
  1006.         } else {
  1007.             $query_base = $sql_query;
  1008.         }
  1009.  
  1010.         if (strlen($query_base) > $cfg['MaxCharactersInDisplayedSQL']) {
  1011.             $query_too_big = true; 
  1012.             $query_base = nl2br(htmlspecialchars($sql_query));
  1013.             unset($GLOBALS['parsed_sql']);
  1014.         }
  1015.  
  1016.         // Parse SQL if needed
  1017.         // (here, use "! empty" because when deleting a bookmark,
  1018.         // $GLOBALS['parsed_sql'] is set but empty
  1019.         if (! empty($GLOBALS['parsed_sql']) && $query_base == $GLOBALS['parsed_sql']['raw']) {
  1020.             $parsed_sql = $GLOBALS['parsed_sql'];
  1021.         } else {
  1022.             // when the query is large (for example an INSERT of binary
  1023.             // data), the parser chokes; so avoid parsing the query
  1024.             if (! $query_too_big) {
  1025.                 $parsed_sql = PMA_SQP_parse($query_base);
  1026.             }
  1027.         }
  1028.  
  1029.         // Analyze it
  1030.         if (isset($parsed_sql)) {
  1031.             $analyzed_display_query = PMA_SQP_analyze($parsed_sql);
  1032.         }
  1033.  
  1034.         // Here we append the LIMIT added for navigation, to
  1035.         // enable its display. Adding it higher in the code
  1036.         // to $sql_query would create a problem when
  1037.         // using the Refresh or Edit links.
  1038.  
  1039.         // Only append it on SELECTs.
  1040.  
  1041.         /**
  1042.          * @todo what would be the best to do when someone hits Refresh:
  1043.          * use the current LIMITs ?
  1044.          */
  1045.  
  1046.         if (isset($analyzed_display_query[0]['queryflags']['select_from'])
  1047.          && isset($GLOBALS['sql_limit_to_append'])) {
  1048.             $query_base  = $analyzed_display_query[0]['section_before_limit'] . "\n" . $GLOBALS['sql_limit_to_append'] . $analyzed_display_query[0]['section_after_limit'];
  1049.             // Need to reparse query
  1050.             $parsed_sql = PMA_SQP_parse($query_base);
  1051.         }
  1052.  
  1053.         if (!empty($GLOBALS['show_as_php'])) {
  1054.             $query_base = '$sql  = \'' . $query_base;
  1055.         } elseif (!empty($GLOBALS['validatequery'])) {
  1056.             $query_base = PMA_validateSQL($query_base);
  1057.         } else {
  1058.             if (isset($parsed_sql)) {
  1059.                 $query_base = PMA_formatSql($parsed_sql, $query_base);
  1060.             }
  1061.         }
  1062.  
  1063.         // Prepares links that may be displayed to edit/explain the query
  1064.         // (don't go to default pages, we must go to the page
  1065.         // where the query box is available)
  1066.  
  1067.         $edit_target = strlen($GLOBALS['db']) ? (strlen($GLOBALS['table']) ? 'tbl_sql.php' : 'db_sql.php') : 'server_sql.php';
  1068.  
  1069.         if (isset($cfg['SQLQuery']['Edit'])
  1070.             && ($cfg['SQLQuery']['Edit'] == true)
  1071.             && (!empty($edit_target))
  1072.             && ! $query_too_big) {
  1073.  
  1074.             if ($cfg['EditInWindow'] == true) {
  1075.                 $onclick = 'window.parent.focus_querywindow(\'' . PMA_jsFormat($sql_query, false) . '\'); return false;';
  1076.             } else {
  1077.                 $onclick = '';
  1078.             }
  1079.  
  1080.             $edit_link = $edit_target
  1081.                        . $url_qpart
  1082.                        . '&sql_query=' . urlencode($sql_query)
  1083.                        . '&show_query=1#querybox';
  1084.             $edit_link = ' [' . PMA_linkOrButton($edit_link, $GLOBALS['strEdit'], array('onclick' => $onclick)) . ']';
  1085.         } else {
  1086.             $edit_link = '';
  1087.         }
  1088.  
  1089.         // Want to have the query explained (Mike Beck 2002-05-22)
  1090.         // but only explain a SELECT (that has not been explained)
  1091.         /* SQL-Parser-Analyzer */
  1092.         if (isset($cfg['SQLQuery']['Explain'])
  1093.             && $cfg['SQLQuery']['Explain'] == true
  1094.             && ! $query_too_big) {
  1095.  
  1096.             // Detect if we are validating as well
  1097.             // To preserve the validate uRL data
  1098.             if (!empty($GLOBALS['validatequery'])) {
  1099.                 $explain_link_validate = '&validatequery=1';
  1100.             } else {
  1101.                 $explain_link_validate = '';
  1102.             }
  1103.  
  1104.             $explain_link = 'import.php'
  1105.                           . $url_qpart
  1106.                           . $explain_link_validate
  1107.                           . '&sql_query=';
  1108.  
  1109.             if (preg_match('@^SELECT[[:space:]]+@i', $sql_query)) {
  1110.                 $explain_link .= urlencode('EXPLAIN ' . $sql_query);
  1111.                 $message = $GLOBALS['strExplain'];
  1112.             } elseif (preg_match('@^EXPLAIN[[:space:]]+SELECT[[:space:]]+@i', $sql_query)) {
  1113.                 $explain_link .= urlencode(substr($sql_query, 8));
  1114.                 $message = $GLOBALS['strNoExplain'];
  1115.             } else {
  1116.                 $explain_link = '';
  1117.             }
  1118.             if (!empty($explain_link)) {
  1119.                 $explain_link = ' [' . PMA_linkOrButton($explain_link, $message) . ']';
  1120.             }
  1121.         } else {
  1122.             $explain_link = '';
  1123.         } //show explain
  1124.  
  1125.         // Also we would like to get the SQL formed in some nice
  1126.         // php-code (Mike Beck 2002-05-22)
  1127.         if (isset($cfg['SQLQuery']['ShowAsPHP'])
  1128.             && $cfg['SQLQuery']['ShowAsPHP'] == true
  1129.             && ! $query_too_big) {
  1130.             $php_link = 'import.php'
  1131.                       . $url_qpart
  1132.                       . '&show_query=1'
  1133.                       . '&sql_query=' . urlencode($sql_query)
  1134.                       . '&show_as_php=';
  1135.  
  1136.             if (!empty($GLOBALS['show_as_php'])) {
  1137.                 $php_link .= '0';
  1138.                 $message = $GLOBALS['strNoPhp'];
  1139.             } else {
  1140.                 $php_link .= '1';
  1141.                 $message = $GLOBALS['strPhp'];
  1142.             }
  1143.             $php_link = ' [' . PMA_linkOrButton($php_link, $message) . ']';
  1144.  
  1145.             if (isset($GLOBALS['show_as_php'])) {
  1146.                 $runquery_link
  1147.                      = 'import.php'
  1148.                      . $url_qpart
  1149.                      . '&show_query=1'
  1150.                      . '&sql_query=' . urlencode($sql_query);
  1151.                 $php_link .= ' [' . PMA_linkOrButton($runquery_link, $GLOBALS['strRunQuery']) . ']';
  1152.             }
  1153.  
  1154.         } else {
  1155.             $php_link = '';
  1156.         } //show as php
  1157.  
  1158.         // Refresh query
  1159.         if (isset($cfg['SQLQuery']['Refresh'])
  1160.             && $cfg['SQLQuery']['Refresh']
  1161.             && preg_match('@^(SELECT|SHOW)[[:space:]]+@i', $sql_query)) {
  1162.  
  1163.             $refresh_link = 'import.php'
  1164.                       . $url_qpart
  1165.                       . '&show_query=1'
  1166.                       . '&sql_query=' . urlencode($sql_query);
  1167.             $refresh_link = ' [' . PMA_linkOrButton($refresh_link, $GLOBALS['strRefresh']) . ']';
  1168.         } else {
  1169.             $refresh_link = '';
  1170.         } //show as php
  1171.  
  1172.         if (isset($cfg['SQLValidator']['use'])
  1173.             && $cfg['SQLValidator']['use'] == true
  1174.             && isset($cfg['SQLQuery']['Validate'])
  1175.             && $cfg['SQLQuery']['Validate'] == true) {
  1176.             $validate_link = 'import.php'
  1177.                            . $url_qpart
  1178.                            . '&show_query=1'
  1179.                            . '&sql_query=' . urlencode($sql_query)
  1180.                            . '&validatequery=';
  1181.             if (!empty($GLOBALS['validatequery'])) {
  1182.                 $validate_link .= '0';
  1183.                 $validate_message = $GLOBALS['strNoValidateSQL'] ;
  1184.             } else {
  1185.                 $validate_link .= '1';
  1186.                 $validate_message = $GLOBALS['strValidateSQL'] ;
  1187.             }
  1188.             $validate_link = ' [' . PMA_linkOrButton($validate_link, $validate_message) . ']';
  1189.         } else {
  1190.             $validate_link = '';
  1191.         } //validator
  1192.  
  1193.         // why this?
  1194.         //unset($sql_query);
  1195.  
  1196.         // Displays the message
  1197.         echo '<fieldset class="">' . "\n";
  1198.         echo '    <legend>' . $GLOBALS['strSQLQuery'] . ':</legend>';
  1199.         echo '    <div>';
  1200.         // when uploading a 700 Kio binary file into a LONGBLOB,
  1201.         // I get a white page, strlen($query_base) is 2 x 700 Kio
  1202.         // so put a hard limit here (let's say 1000)
  1203.         if ($query_too_big) {
  1204.             echo '    ' . substr($query_base, 0, $cfg['MaxCharactersInDisplayedSQL']) . '[...]';
  1205.         } else {
  1206.             echo '    ' . $query_base;
  1207.         }
  1208.  
  1209.         //Clean up the end of the PHP
  1210.         if (!empty($GLOBALS['show_as_php'])) {
  1211.             echo '\';';
  1212.         }
  1213.         echo '    </div>';
  1214.         echo '</fieldset>' . "\n";
  1215.  
  1216.         if (!empty($edit_target)) {
  1217.             echo '<fieldset class="tblFooters">';
  1218.             PMA_profilingCheckbox($sql_query);
  1219.             echo $edit_link . $explain_link . $php_link . $refresh_link . $validate_link;
  1220.             echo '</fieldset>';
  1221.         }
  1222.     }
  1223.     echo '</div><br />' . "\n";
  1224. } // end of the 'PMA_showMessage()' function
  1225.  
  1226.  
  1227. /**
  1228.  * Verifies if current MySQL server supports profiling 
  1229.  *
  1230.  * @access  public
  1231.  * @return  boolean whether profiling is supported 
  1232.  *
  1233.  * @author   Marc Delisle 
  1234.  */
  1235. function PMA_profilingSupported() {
  1236.     // 5.0.37 has profiling but for example, 5.1.20 does not
  1237.     // (avoid a trip to the server for MySQL before 5.0.37)
  1238.     // and do not set a constant as we might be switching servers
  1239.     if (defined('PMA_MYSQL_INT_VERSION') && PMA_MYSQL_INT_VERSION >= 50037 && PMA_DBI_fetch_value("SHOW VARIABLES LIKE 'profiling'")) {
  1240.         return true;
  1241.     } else {
  1242.         return false;
  1243.     }
  1244. }
  1245.  
  1246. /**
  1247.  * Displays a form with the Profiling checkbox 
  1248.  *
  1249.  * @param   string  $sql_query
  1250.  * @access  public
  1251.  *
  1252.  * @author   Marc Delisle 
  1253.  */
  1254. function PMA_profilingCheckbox($sql_query) {
  1255.     if (PMA_profilingSupported()) {
  1256.         echo '<form action="sql.php" method="post">' . "\n";
  1257.         echo PMA_generate_common_hidden_inputs($GLOBALS['db'], $GLOBALS['table']);
  1258.         echo '<input type="hidden" name="sql_query" value="' . htmlspecialchars($sql_query) . '" />' . "\n";
  1259.         echo '<input type="hidden" name="profiling_form" value="1" />' . "\n";
  1260.         echo '<input type="checkbox" name="profiling" id="profiling"' . (isset($_SESSION['profiling']) ? ' checked="checked"' : '') . ' onclick="this.form.submit();" /><label for="profiling">' . $GLOBALS['strProfiling'] . '</label>' . "\n";
  1261.         echo '<noscript><input type="submit" value="' . $GLOBALS['strGo'] . '" /></noscript>' . "\n";
  1262.         echo '</form>' . "\n";
  1263.     }
  1264. }
  1265.  
  1266. /**
  1267.  * Displays the results of SHOW PROFILE 
  1268.  *
  1269.  * @param    array   the results 
  1270.  * @access  public
  1271.  *
  1272.  * @author   Marc Delisle 
  1273.  */
  1274. function PMA_profilingResults($profiling_results) {
  1275.     echo '<fieldset><legend>' . $GLOBALS['strProfiling'] . '</legend>' . "\n";
  1276.     echo '<table>' . "\n";
  1277.     echo ' <tr>' .  "\n";
  1278.     echo '  <th>' . $GLOBALS['strStatus'] . '</th>' . "\n";
  1279.     echo '  <th>' . $GLOBALS['strTime'] . '</th>' . "\n";
  1280.     echo ' </tr>' .  "\n";
  1281.  
  1282.     foreach($profiling_results as $one_result) {
  1283.         echo ' <tr>' .  "\n";
  1284.         echo '<td>' . $one_result['Status'] . '</td>' .  "\n";
  1285.         echo '<td>' . $one_result['Duration'] . '</td>' .  "\n";
  1286.     }
  1287.     echo '</table>' . "\n";
  1288.     echo '</fieldset>' . "\n";
  1289. }
  1290.  
  1291. /**
  1292.  * Formats $value to byte view
  1293.  *
  1294.  * @param    double   the value to format
  1295.  * @param    integer  the sensitiveness
  1296.  * @param    integer  the number of decimals to retain
  1297.  *
  1298.  * @return   array    the formatted value and its unit
  1299.  *
  1300.  * @access  public
  1301.  *
  1302.  * @author   staybyte
  1303.  * @version  1.2 - 18 July 2002
  1304.  */
  1305. function PMA_formatByteDown($value, $limes = 6, $comma = 0)
  1306. {
  1307.     $dh           = PMA_pow(10, $comma);
  1308.     $li           = PMA_pow(10, $limes);
  1309.     $return_value = $value;
  1310.     $unit         = $GLOBALS['byteUnits'][0];
  1311.  
  1312.     for ($d = 6, $ex = 15; $d >= 1; $d--, $ex-=3) {
  1313.         if (isset($GLOBALS['byteUnits'][$d]) && $value >= $li * PMA_pow(10, $ex)) {
  1314.             // use 1024.0 to avoid integer overflow on 64-bit machines
  1315.             $value = round($value / (PMA_pow(1024, $d) / $dh)) /$dh;
  1316.             $unit = $GLOBALS['byteUnits'][$d];
  1317.             break 1;
  1318.         } // end if
  1319.     } // end for
  1320.  
  1321.     if ($unit != $GLOBALS['byteUnits'][0]) {
  1322.         // if the unit is not bytes (as represented in current language)
  1323.         // reformat with max length of 5
  1324.         // 4th parameter=true means do not reformat if value < 1
  1325.         $return_value = PMA_formatNumber($value, 5, $comma, true);
  1326.     } else {
  1327.         // do not reformat, just handle the locale
  1328.         $return_value = PMA_formatNumber($value, 0);
  1329.     }
  1330.  
  1331.     return array($return_value, $unit);
  1332. } // end of the 'PMA_formatByteDown' function
  1333.  
  1334. /**
  1335.  * Formats $value to the given length and appends SI prefixes
  1336.  * $comma is not substracted from the length
  1337.  * with a $length of 0 no truncation occurs, number is only formated
  1338.  * to the current locale
  1339.  *
  1340.  * examples:
  1341.  * <code>
  1342.  * echo PMA_formatNumber(123456789, 6);     // 123,457 k
  1343.  * echo PMA_formatNumber(-123456789, 4, 2); //    -123.46 M
  1344.  * echo PMA_formatNumber(-0.003, 6);        //      -3 m
  1345.  * echo PMA_formatNumber(0.003, 3, 3);      //       0.003
  1346.  * echo PMA_formatNumber(0.00003, 3, 2);    //       0.03 m
  1347.  * echo PMA_formatNumber(0, 6);             //       0
  1348.  *
  1349.  * </code>
  1350.  * @param   double   $value     the value to format
  1351.  * @param   integer  $length    the max length
  1352.  * @param   integer  $comma     the number of decimals to retain
  1353.  * @param   boolean  $only_down do not reformat numbers below 1
  1354.  *
  1355.  * @return  string   the formatted value and its unit
  1356.  *
  1357.  * @access  public
  1358.  *
  1359.  * @author  staybyte, sebastian mendel
  1360.  * @version 1.1.0 - 2005-10-27
  1361.  */
  1362. function PMA_formatNumber($value, $length = 3, $comma = 0, $only_down = false)
  1363. {
  1364.     //number_format is not multibyte safe, str_replace is safe
  1365.     if ($length === 0) {
  1366.         return str_replace(array(',', '.'),
  1367.                 array($GLOBALS['number_thousands_separator'], $GLOBALS['number_decimal_separator']),
  1368.                 number_format($value, $comma));
  1369.     }
  1370.  
  1371.     // this units needs no translation, ISO
  1372.     $units = array(
  1373.         -8 => 'y',
  1374.         -7 => 'z',
  1375.         -6 => 'a',
  1376.         -5 => 'f',
  1377.         -4 => 'p',
  1378.         -3 => 'n',
  1379.         -2 => 'µ',
  1380.         -1 => 'm',
  1381.         0 => ' ',
  1382.         1 => 'k',
  1383.         2 => 'M',
  1384.         3 => 'G',
  1385.         4 => 'T',
  1386.         5 => 'P',
  1387.         6 => 'E',
  1388.         7 => 'Z',
  1389.         8 => 'Y'
  1390.     );
  1391.  
  1392.     // we need at least 3 digits to be displayed
  1393.     if (3 > $length + $comma) {
  1394.         $length = 3 - $comma;
  1395.     }
  1396.  
  1397.     // check for negative value to retain sign
  1398.     if ($value < 0) {
  1399.         $sign = '-';
  1400.         $value = abs($value);
  1401.     } else {
  1402.         $sign = '';
  1403.     }
  1404.  
  1405.     $dh = PMA_pow(10, $comma);
  1406.     $li = PMA_pow(10, $length);
  1407.     $unit = $units[0];
  1408.  
  1409.     if ($value >= 1) {
  1410.         for ($d = 8; $d >= 0; $d--) {
  1411.             if (isset($units[$d]) && $value >= $li * PMA_pow(1000, $d-1)) {
  1412.                 $value = round($value / (PMA_pow(1000, $d) / $dh)) /$dh;
  1413.                 $unit = $units[$d];
  1414.                 break 1;
  1415.             } // end if
  1416.         } // end for
  1417.     } elseif (!$only_down && (float) $value !== 0.0) {
  1418.         for ($d = -8; $d <= 8; $d++) {
  1419.             if (isset($units[$d]) && $value <= $li * PMA_pow(1000, $d-1)) {
  1420.                 $value = round($value / (PMA_pow(1000, $d) / $dh)) /$dh;
  1421.                 $unit = $units[$d];
  1422.                 break 1;
  1423.             } // end if
  1424.         } // end for
  1425.     } // end if ($value >= 1) elseif (!$only_down && (float) $value !== 0.0)
  1426.  
  1427.     //number_format is not multibyte safe, str_replace is safe
  1428.     $value = str_replace(array(',', '.'),
  1429.                          array($GLOBALS['number_thousands_separator'], $GLOBALS['number_decimal_separator']),
  1430.                          number_format($value, $comma));
  1431.  
  1432.     return $sign . $value . ' ' . $unit;
  1433. } // end of the 'PMA_formatNumber' function
  1434.  
  1435. /**
  1436.  * Extracts ENUM / SET options from a type definition string
  1437.  *
  1438.  * @param   string   The column type definition
  1439.  *
  1440.  * @return  array    The options or
  1441.  *          boolean  false in case of an error.
  1442.  *
  1443.  * @author  rabus
  1444.  */
  1445. function PMA_getEnumSetOptions($type_def)
  1446. {
  1447.     $open = strpos($type_def, '(');
  1448.     $close = strrpos($type_def, ')');
  1449.     if (!$open || !$close) {
  1450.         return false;
  1451.     }
  1452.     $options = substr($type_def, $open + 2, $close - $open - 3);
  1453.     $options = explode('\',\'', $options);
  1454.     return $options;
  1455. } // end of the 'PMA_getEnumSetOptions' function
  1456.  
  1457. /**
  1458.  * Writes localised date
  1459.  *
  1460.  * @param   string   the current timestamp
  1461.  *
  1462.  * @return  string   the formatted date
  1463.  *
  1464.  * @access  public
  1465.  */
  1466. function PMA_localisedDate($timestamp = -1, $format = '')
  1467. {
  1468.     global $datefmt, $month, $day_of_week;
  1469.  
  1470.     if ($format == '') {
  1471.         $format = $datefmt;
  1472.     }
  1473.  
  1474.     if ($timestamp == -1) {
  1475.         $timestamp = time();
  1476.     }
  1477.  
  1478.     $date = preg_replace('@%[aA]@', $day_of_week[(int)strftime('%w', $timestamp)], $format);
  1479.     $date = preg_replace('@%[bB]@', $month[(int)strftime('%m', $timestamp)-1], $date);
  1480.  
  1481.     return strftime($date, $timestamp);
  1482. } // end of the 'PMA_localisedDate()' function
  1483.  
  1484.  
  1485. /**
  1486.  * returns a tab for tabbed navigation.
  1487.  * If the variables $link and $args ar left empty, an inactive tab is created
  1488.  *
  1489.  * @uses    $GLOBALS['PMA_PHP_SELF']
  1490.  * @uses    $GLOBALS['strEmpty']
  1491.  * @uses    $GLOBALS['strDrop']
  1492.  * @uses    $GLOBALS['active_page']
  1493.  * @uses    $GLOBALS['url_query']
  1494.  * @uses    $cfg['MainPageIconic']
  1495.  * @uses    $GLOBALS['pmaThemeImage']
  1496.  * @uses    PMA_generate_common_url()
  1497.  * @uses    E_USER_NOTICE
  1498.  * @uses    htmlentities()
  1499.  * @uses    urlencode()
  1500.  * @uses    sprintf()
  1501.  * @uses    trigger_error()
  1502.  * @uses    array_merge()
  1503.  * @uses    basename()
  1504.  * @param   array   $tab    array with all options
  1505.  * @return  string  html code for one tab, a link if valid otherwise a span
  1506.  * @access  public
  1507.  */
  1508. function PMA_getTab($tab)
  1509. {
  1510.     // default values
  1511.     $defaults = array(
  1512.         'text'      => '',
  1513.         'class'     => '',
  1514.         'active'    => false,
  1515.         'link'      => '',
  1516.         'sep'       => '?',
  1517.         'attr'      => '',
  1518.         'args'      => '',
  1519.         'warning'   => '',
  1520.         'fragment'  => '',
  1521.     );
  1522.  
  1523.     $tab = array_merge($defaults, $tab);
  1524.  
  1525.     // determine additionnal style-class
  1526.     if (empty($tab['class'])) {
  1527.         if ($tab['text'] == $GLOBALS['strEmpty']
  1528.             || $tab['text'] == $GLOBALS['strDrop']) {
  1529.             $tab['class'] = 'caution';
  1530.         } elseif (!empty($tab['active'])
  1531.           || (isset($GLOBALS['active_page'])
  1532.                && $GLOBALS['active_page'] == $tab['link'])
  1533.           || (basename($GLOBALS['PMA_PHP_SELF']) == $tab['link'] && empty($tab['warning'])))
  1534.         {
  1535.             $tab['class'] = 'active';
  1536.         }
  1537.     }
  1538.  
  1539.     if (!empty($tab['warning'])) {
  1540.         $tab['class'] .= ' warning';
  1541.         $tab['attr'] .= ' title="' . htmlspecialchars($tab['warning']) . '"';
  1542.     }
  1543.  
  1544.     // build the link
  1545.     if (!empty($tab['link'])) {
  1546.         $tab['link'] = htmlentities($tab['link']);
  1547.         $tab['link'] = $tab['link'] . $tab['sep']
  1548.             .(empty($GLOBALS['url_query']) ?
  1549.                 PMA_generate_common_url() : $GLOBALS['url_query']);
  1550.         if (!empty($tab['args'])) {
  1551.             foreach ($tab['args'] as $param => $value) {
  1552.                 $tab['link'] .= '&' . urlencode($param) . '='
  1553.                     . urlencode($value);
  1554.             }
  1555.         }
  1556.     }
  1557.  
  1558.     if (! empty($tab['fragment'])) {
  1559.         $tab['link'] .= $tab['fragment'];
  1560.     }
  1561.  
  1562.     // display icon, even if iconic is disabled but the link-text is missing
  1563.     if (($GLOBALS['cfg']['MainPageIconic'] || empty($tab['text']))
  1564.         && isset($tab['icon'])) {
  1565.         // avoid generating an alt tag, because it only illustrates
  1566.         // the text that follows and if browser does not display
  1567.         // images, the text is duplicated
  1568.         $image = '<img class="icon" src="' . htmlentities($GLOBALS['pmaThemeImage'])
  1569.             .'%1$s" width="16" height="16" alt="" />%2$s';
  1570.         $tab['text'] = sprintf($image, htmlentities($tab['icon']), $tab['text']);
  1571.     }
  1572.     // check to not display an empty link-text
  1573.     elseif (empty($tab['text'])) {
  1574.         $tab['text'] = '?';
  1575.         trigger_error('empty linktext in function ' . __FUNCTION__ . '()',
  1576.             E_USER_NOTICE);
  1577.     }
  1578.  
  1579.     $out = '<li' . ($tab['class'] == 'active' ? ' class="active"' : '') . '>';
  1580.  
  1581.     if (!empty($tab['link'])) {
  1582.         $out .= '<a class="tab' . htmlentities($tab['class']) . '"'
  1583.             .' href="' . $tab['link'] . '" ' . $tab['attr'] . '>'
  1584.             . $tab['text'] . '</a>';
  1585.     } else {
  1586.         $out .= '<span class="tab' . htmlentities($tab['class']) . '">'
  1587.             . $tab['text'] . '</span>';
  1588.     }
  1589.  
  1590.     $out .= '</li>';
  1591.     return $out;
  1592. } // end of the 'PMA_getTab()' function
  1593.  
  1594. /**
  1595.  * returns html-code for a tab navigation
  1596.  *
  1597.  * @uses    PMA_getTab()
  1598.  * @uses    htmlentities()
  1599.  * @param   array   $tabs   one element per tab
  1600.  * @param   string  $tag_id id used for the html-tag
  1601.  * @return  string  html-code for tab-navigation
  1602.  */
  1603. function PMA_getTabs($tabs, $tag_id = 'topmenu')
  1604. {
  1605.     $tab_navigation =
  1606.          '<div id="' . htmlentities($tag_id) . 'container">' . "\n"
  1607.         .'<ul id="' . htmlentities($tag_id) . '">' . "\n";
  1608.  
  1609.     foreach ($tabs as $tab) {
  1610.         $tab_navigation .= PMA_getTab($tab) . "\n";
  1611.     }
  1612.  
  1613.     $tab_navigation .=
  1614.          '</ul>' . "\n"
  1615.         .'<div class="clearfloat"></div>'
  1616.         .'</div>' . "\n";
  1617.  
  1618.     return $tab_navigation;
  1619. }
  1620.  
  1621.  
  1622. /**
  1623.  * Displays a link, or a button if the link's URL is too large, to
  1624.  * accommodate some browsers' limitations
  1625.  *
  1626.  * @param  string  the URL
  1627.  * @param  string  the link message
  1628.  * @param  mixed   $tag_params  string: js confirmation
  1629.  *                              array: additional tag params (f.e. style="")
  1630.  * @param  boolean $new_form    we set this to false when we are already in
  1631.  *                              a  form, to avoid generating nested forms
  1632.  *
  1633.  * @return string  the results to be echoed or saved in an array
  1634.  */
  1635. function PMA_linkOrButton($url, $message, $tag_params = array(),
  1636.     $new_form = true, $strip_img = false, $target = '')
  1637. {
  1638.     if (! is_array($tag_params)) {
  1639.         $tmp = $tag_params;
  1640.         $tag_params = array();
  1641.         if (!empty($tmp)) {
  1642.             $tag_params['onclick'] = 'return confirmLink(this, \'' . $tmp . '\')';
  1643.         }
  1644.         unset($tmp);
  1645.     }
  1646.     if (! empty($target)) {
  1647.         $tag_params['target'] = htmlentities($target);
  1648.     }
  1649.  
  1650.     $tag_params_strings = array();
  1651.     foreach ($tag_params as $par_name => $par_value) {
  1652.         // htmlspecialchars() only on non javascript
  1653.         $par_value = substr($par_name, 0, 2) == 'on'
  1654.             ? $par_value
  1655.             : htmlspecialchars($par_value);
  1656.         $tag_params_strings[] = $par_name . '="' . $par_value . '"';
  1657.     }
  1658.  
  1659.     // previously the limit was set to 2047, it seems 1000 is better
  1660.     if (strlen($url) <= 1000) {
  1661.         // no whitespace within an <a> else Safari will make it part of the link
  1662.         $ret = "\n" . '<a href="' . $url . '" '
  1663.             . implode(' ', $tag_params_strings) . '>'
  1664.             . $message . '</a>' . "\n";
  1665.     } else {
  1666.         // no spaces (linebreaks) at all
  1667.         // or after the hidden fields
  1668.         // IE will display them all
  1669.  
  1670.         // add class=link to submit button
  1671.         if (empty($tag_params['class'])) {
  1672.             $tag_params['class'] = 'link';
  1673.         }
  1674.  
  1675.         // decode encoded url separators
  1676.         $separator   = PMA_get_arg_separator();
  1677.         // on most places separator is still hard coded ...
  1678.         if ($separator !== '&') {
  1679.             // ... so always replace & with $separator
  1680.             $url         = str_replace(htmlentities('&'), $separator, $url);
  1681.             $url         = str_replace('&', $separator, $url);
  1682.         }
  1683.         $url         = str_replace(htmlentities($separator), $separator, $url);
  1684.         // end decode
  1685.  
  1686.         $url_parts   = parse_url($url);
  1687.         $query_parts = explode($separator, $url_parts['query']);
  1688.         if ($new_form) {
  1689.             $ret = '<form action="' . $url_parts['path'] . '" class="link"'
  1690.                  . ' method="post"' . $target . ' style="display: inline;">';
  1691.             $subname_open   = '';
  1692.             $subname_close  = '';
  1693.             $submit_name    = '';
  1694.         } else {
  1695.             $query_parts[] = 'redirect=' . $url_parts['path'];
  1696.             if (empty($GLOBALS['subform_counter'])) {
  1697.                 $GLOBALS['subform_counter'] = 0;
  1698.             }
  1699.             $GLOBALS['subform_counter']++;
  1700.             $ret            = '';
  1701.             $subname_open   = 'subform[' . $GLOBALS['subform_counter'] . '][';
  1702.             $subname_close  = ']';
  1703.             $submit_name    = ' name="usesubform[' . $GLOBALS['subform_counter'] . ']"';
  1704.         }
  1705.         foreach ($query_parts as $query_pair) {
  1706.             list($eachvar, $eachval) = explode('=', $query_pair);
  1707.             $ret .= '<input type="hidden" name="' . $subname_open . $eachvar
  1708.                 . $subname_close . '" value="'
  1709.                 . htmlspecialchars(urldecode($eachval)) . '" />';
  1710.         } // end while
  1711.  
  1712.         if (stristr($message, '<img')) {
  1713.             if ($strip_img) {
  1714.                 $message = trim(strip_tags($message));
  1715.                 $ret .= '<input type="submit"' . $submit_name . ' '
  1716.                     . implode(' ', $tag_params_strings)
  1717.                     . ' value="' . htmlspecialchars($message) . '" />';
  1718.             } else {
  1719.                 $ret .= '<input type="image"' . $submit_name . ' '
  1720.                     . implode(' ', $tag_params_strings)
  1721.                     . ' src="' . preg_replace(
  1722.                         '/^.*\ssrc="([^"]*)".*$/si', '\1', $message) . '"'
  1723.                     . ' value="' . htmlspecialchars(
  1724.                         preg_replace('/^.*\salt="([^"]*)".*$/si', '\1',
  1725.                             $message))
  1726.                     . '" />';
  1727.             }
  1728.         } else {
  1729.             $message = trim(strip_tags($message));
  1730.             $ret .= '<input type="submit"' . $submit_name . ' '
  1731.                 . implode(' ', $tag_params_strings)
  1732.                 . ' value="' . htmlspecialchars($message) . '" />';
  1733.         }
  1734.         if ($new_form) {
  1735.             $ret .= '</form>';
  1736.         }
  1737.     } // end if... else...
  1738.  
  1739.         return $ret;
  1740. } // end of the 'PMA_linkOrButton()' function
  1741.  
  1742.  
  1743. /**
  1744.  * Returns a given timespan value in a readable format.
  1745.  *
  1746.  * @uses    $GLOBALS['timespanfmt']
  1747.  * @uses    sprintf()
  1748.  * @uses    floor()
  1749.  * @param  int     the timespan
  1750.  *
  1751.  * @return string  the formatted value
  1752.  */
  1753. function PMA_timespanFormat($seconds)
  1754. {
  1755.     $return_string = '';
  1756.     $days = floor($seconds / 86400);
  1757.     if ($days > 0) {
  1758.         $seconds -= $days * 86400;
  1759.     }
  1760.     $hours = floor($seconds / 3600);
  1761.     if ($days > 0 || $hours > 0) {
  1762.         $seconds -= $hours * 3600;
  1763.     }
  1764.     $minutes = floor($seconds / 60);
  1765.     if ($days > 0 || $hours > 0 || $minutes > 0) {
  1766.         $seconds -= $minutes * 60;
  1767.     }
  1768.     return sprintf($GLOBALS['timespanfmt'], (string)$days, (string)$hours, (string)$minutes, (string)$seconds);
  1769. }
  1770.  
  1771. /**
  1772.  * Takes a string and outputs each character on a line for itself. Used
  1773.  * mainly for horizontalflipped display mode.
  1774.  * Takes care of special html-characters.
  1775.  * Fulfills todo-item
  1776.  * http://sf.net/tracker/?func=detail&aid=544361&group_id=23067&atid=377411
  1777.  *
  1778.  * @todo    add a multibyte safe function PMA_STR_split()
  1779.  * @uses    strlen
  1780.  * @param   string   The string
  1781.  * @param   string   The Separator (defaults to "<br />\n")
  1782.  *
  1783.  * @access  public
  1784.  * @author  Garvin Hicking <me@supergarv.de>
  1785.  * @return  string      The flipped string
  1786.  */
  1787. function PMA_flipstring($string, $Separator = "<br />\n")
  1788. {
  1789.     $format_string = '';
  1790.     $charbuff = false;
  1791.  
  1792.     for ($i = 0; $i < strlen($string); $i++) {
  1793.         $char = $string{$i};
  1794.         $append = false;
  1795.  
  1796.         if ($char == '&') {
  1797.             $format_string .= $charbuff;
  1798.             $charbuff = $char;
  1799.             $append = true;
  1800.         } elseif (!empty($charbuff)) {
  1801.             $charbuff .= $char;
  1802.         } elseif ($char == ';' && !empty($charbuff)) {
  1803.             $format_string .= $charbuff;
  1804.             $charbuff = false;
  1805.             $append = true;
  1806.         } else {
  1807.             $format_string .= $char;
  1808.             $append = true;
  1809.         }
  1810.  
  1811.         if ($append && ($i != strlen($string))) {
  1812.             $format_string .= $Separator;
  1813.         }
  1814.     }
  1815.  
  1816.     return $format_string;
  1817. }
  1818.  
  1819.  
  1820. /**
  1821.  * Function added to avoid path disclosures.
  1822.  * Called by each script that needs parameters, it displays
  1823.  * an error message and, by default, stops the execution.
  1824.  *
  1825.  * Not sure we could use a strMissingParameter message here,
  1826.  * would have to check if the error message file is always available
  1827.  *
  1828.  * @todo    localize error message
  1829.  * @todo    use PMA_fatalError() if $die === true?
  1830.  * @uses    PMA_getenv()
  1831.  * @uses    header_meta_style.inc.php
  1832.  * @uses    $GLOBALS['PMA_PHP_SELF']
  1833.  * basename
  1834.  * @param   array   The names of the parameters needed by the calling
  1835.  *                  script.
  1836.  * @param   boolean Stop the execution?
  1837.  *                  (Set this manually to false in the calling script
  1838.  *                   until you know all needed parameters to check).
  1839.  * @param   boolean Whether to include this list in checking for special params.
  1840.  * @global  string  path to current script
  1841.  * @global  boolean flag whether any special variable was required
  1842.  *
  1843.  * @access  public
  1844.  * @author  Marc Delisle (lem9@users.sourceforge.net)
  1845.  */
  1846. function PMA_checkParameters($params, $die = true, $request = true)
  1847. {
  1848.     global $checked_special;
  1849.  
  1850.     if (!isset($checked_special)) {
  1851.         $checked_special = false;
  1852.     }
  1853.  
  1854.     $reported_script_name = basename($GLOBALS['PMA_PHP_SELF']);
  1855.     $found_error = false;
  1856.     $error_message = '';
  1857.  
  1858.     foreach ($params as $param) {
  1859.         if ($request && $param != 'db' && $param != 'table') {
  1860.             $checked_special = true;
  1861.         }
  1862.  
  1863.         if (!isset($GLOBALS[$param])) {
  1864.             $error_message .= $reported_script_name
  1865.                 . ': Missing parameter: ' . $param
  1866.                 . ' <a href="./Documentation.html#faqmissingparameters"'
  1867.                 . ' target="documentation"> (FAQ 2.8)</a><br />';
  1868.             $found_error = true;
  1869.         }
  1870.     }
  1871.     if ($found_error) {
  1872.         /**
  1873.          * display html meta tags
  1874.          */
  1875.         require_once './libraries/header_meta_style.inc.php';
  1876.         echo '</head><body><p>' . $error_message . '</p></body></html>';
  1877.         if ($die) {
  1878.             exit();
  1879.         }
  1880.     }
  1881. } // end function
  1882.  
  1883. /**
  1884.  * Function to generate unique condition for specified row.
  1885.  *
  1886.  * @uses    PMA_MYSQL_INT_VERSION
  1887.  * @uses    $GLOBALS['analyzed_sql'][0]
  1888.  * @uses    PMA_DBI_field_flags()
  1889.  * @uses    PMA_backquote()
  1890.  * @uses    PMA_sqlAddslashes()
  1891.  * @uses    stristr()
  1892.  * @uses    bin2hex()
  1893.  * @uses    preg_replace()
  1894.  * @param   resource    $handle         current query result
  1895.  * @param   integer     $fields_cnt     number of fields
  1896.  * @param   array       $fields_meta    meta information about fields
  1897.  * @param   array       $row            current row
  1898.  * @param   boolean     $force_unique   generate condition only on pk or unique
  1899.  *
  1900.  * @access  public
  1901.  * @author  Michal Cihar (michal@cihar.com) and others...
  1902.  * @return  string      calculated condition
  1903.  */
  1904. function PMA_getUniqueCondition($handle, $fields_cnt, $fields_meta, $row, $force_unique=false)
  1905. {
  1906.     $primary_key          = '';
  1907.     $unique_key           = '';
  1908.     $nonprimary_condition = '';
  1909.     $preferred_condition = '';
  1910.  
  1911.     for ($i = 0; $i < $fields_cnt; ++$i) {
  1912.         $condition   = '';
  1913.         $field_flags = PMA_DBI_field_flags($handle, $i);
  1914.         $meta        = $fields_meta[$i];
  1915.  
  1916.         // do not use a column alias in a condition
  1917.         if (! isset($meta->orgname) || ! strlen($meta->orgname)) {
  1918.             $meta->orgname = $meta->name;
  1919.  
  1920.             if (isset($GLOBALS['analyzed_sql'][0]['select_expr'])
  1921.               && is_array($GLOBALS['analyzed_sql'][0]['select_expr'])) {
  1922.                 foreach ($GLOBALS['analyzed_sql'][0]['select_expr']
  1923.                   as $select_expr) {
  1924.                     // need (string) === (string)
  1925.                     // '' !== 0 but '' == 0
  1926.                     if ((string) $select_expr['alias'] === (string) $meta->name) {
  1927.                         $meta->orgname = $select_expr['column'];
  1928.                         break;
  1929.                     } // end if
  1930.                 } // end foreach
  1931.             }
  1932.         }
  1933.  
  1934.         // Do not use a table alias in a condition.
  1935.         // Test case is:
  1936.         // select * from galerie x WHERE
  1937.         //(select count(*) from galerie y where y.datum=x.datum)>1 
  1938.         //
  1939.         // But orgtable is present only with mysqli extension so the
  1940.         // fix is only for mysqli.
  1941.         if (isset($meta->orgtable) && $meta->table != $meta->orgtable) {
  1942.             $meta->table = $meta->orgtable;
  1943.         }
  1944.  
  1945.         // to fix the bug where float fields (primary or not)
  1946.         // can't be matched because of the imprecision of
  1947.         // floating comparison, use CONCAT
  1948.         // (also, the syntax "CONCAT(field) IS NULL"
  1949.         // that we need on the next "if" will work)
  1950.         if ($meta->type == 'real') {
  1951.             $condition = ' CONCAT(' . PMA_backquote($meta->table) . '.'
  1952.                 . PMA_backquote($meta->orgname) . ') ';
  1953.         } else {
  1954.             // string and blob fields have to be converted using
  1955.             // the system character set (always utf8) since
  1956.             // mysql4.1 can use different charset for fields.
  1957.             if (PMA_MYSQL_INT_VERSION >= 40100
  1958.               && ($meta->type == 'string' || $meta->type == 'blob')) {
  1959.                 $condition = ' CONVERT(' . PMA_backquote($meta->table) . '.'
  1960.                     . PMA_backquote($meta->orgname) . ' USING utf8) ';
  1961.             } else {
  1962.                 $condition = ' ' . PMA_backquote($meta->table) . '.'
  1963.                     . PMA_backquote($meta->orgname) . ' ';
  1964.             }
  1965.         } // end if... else...
  1966.  
  1967.         if (!isset($row[$i]) || is_null($row[$i])) {
  1968.             $condition .= 'IS NULL AND';
  1969.         } else {
  1970.             // timestamp is numeric on some MySQL 4.1
  1971.             if ($meta->numeric && $meta->type != 'timestamp') {
  1972.                 $condition .= '= ' . $row[$i] . ' AND';
  1973.             } elseif (($meta->type == 'blob' || $meta->type == 'string')
  1974.                 // hexify only if this is a true not empty BLOB or a BINARY
  1975.                  && stristr($field_flags, 'BINARY')
  1976.                  && !empty($row[$i])) {
  1977.                     // do not waste memory building a too big condition
  1978.                     if (strlen($row[$i]) < 1000) {
  1979.                         if (PMA_MYSQL_INT_VERSION < 40002) {
  1980.                             $condition .= 'LIKE 0x' . bin2hex($row[$i]) . ' AND';
  1981.                         } else {
  1982.                             // use a CAST if possible, to avoid problems
  1983.                             // if the field contains wildcard characters % or _
  1984.                             $condition .= '= CAST(0x' . bin2hex($row[$i])
  1985.                                 . ' AS BINARY) AND';
  1986.                         }
  1987.                     } else {
  1988.                         // this blob won't be part of the final condition
  1989.                         $condition = '';
  1990.                     }
  1991.             } else {
  1992.                 $condition .= '= \''
  1993.                     . PMA_sqlAddslashes($row[$i], false, true) . '\' AND';
  1994.             }
  1995.         }
  1996.         if ($meta->primary_key > 0) {
  1997.             $primary_key .= $condition;
  1998.         } elseif ($meta->unique_key > 0) {
  1999.             $unique_key  .= $condition;
  2000.         }
  2001.         $nonprimary_condition .= $condition;
  2002.     } // end for
  2003.  
  2004.     // Correction University of Virginia 19991216:
  2005.     // prefer primary or unique keys for condition,
  2006.     // but use conjunction of all values if no primary key
  2007.     if ($primary_key) {
  2008.         $preferred_condition = $primary_key;
  2009.     } elseif ($unique_key) {
  2010.         $preferred_condition = $unique_key;
  2011.     } elseif (! $force_unique) {
  2012.         $preferred_condition = $nonprimary_condition;
  2013.     }
  2014.  
  2015.     return preg_replace('|\s?AND$|', '', $preferred_condition);
  2016. } // end function
  2017.  
  2018. /**
  2019.  * Generate a button or image tag
  2020.  *
  2021.  * @uses    PMA_USR_BROWSER_AGENT
  2022.  * @uses    $GLOBALS['pmaThemeImage']
  2023.  * @uses    $GLOBALS['cfg']['PropertiesIconic']
  2024.  * @param   string      name of button element
  2025.  * @param   string      class of button element
  2026.  * @param   string      name of image element
  2027.  * @param   string      text to display
  2028.  * @param   string      image to display
  2029.  *
  2030.  * @access  public
  2031.  * @author  Michal Cihar (michal@cihar.com)
  2032.  */
  2033. function PMA_buttonOrImage($button_name, $button_class, $image_name, $text,
  2034.     $image)
  2035. {
  2036.     /* Opera has trouble with <input type="image"> */
  2037.     /* IE has trouble with <button> */
  2038.     if (PMA_USR_BROWSER_AGENT != 'IE') {
  2039.         echo '<button class="' . $button_class . '" type="submit"'
  2040.             .' name="' . $button_name . '" value="' . $text . '"'
  2041.             .' title="' . $text . '">' . "\n"
  2042.             .'<img class="icon" src="' . $GLOBALS['pmaThemeImage'] . $image . '"'
  2043.             .' title="' . $text . '" alt="' . $text . '" width="16"'
  2044.             .' height="16" />'
  2045.             .($GLOBALS['cfg']['PropertiesIconic'] === 'both' ? ' ' . $text : '') . "\n"
  2046.             .'</button>' . "\n";
  2047.     } else {
  2048.         echo '<input type="image" name="' . $image_name . '" value="'
  2049.             . $text . '" title="' . $text . '" src="' . $GLOBALS['pmaThemeImage']
  2050.             . $image . '" />'
  2051.             . ($GLOBALS['cfg']['PropertiesIconic'] === 'both' ? ' ' . $text : '') . "\n";
  2052.     }
  2053. } // end function
  2054.  
  2055. /**
  2056.  * Generate a pagination selector for browsing resultsets
  2057.  *
  2058.  * @uses    $GLOBALS['strPageNumber']
  2059.  * @uses    range()
  2060.  * @param   string      URL for the JavaScript
  2061.  * @param   string      Number of rows in the pagination set
  2062.  * @param   string      current page number
  2063.  * @param   string      number of total pages
  2064.  * @param   string      If the number of pages is lower than this
  2065.  *                      variable, no pages will be ommitted in
  2066.  *                      pagination
  2067.  * @param   string      How many rows at the beginning should always
  2068.  *                      be shown?
  2069.  * @param   string      How many rows at the end should always
  2070.  *                      be shown?
  2071.  * @param   string      Percentage of calculation page offsets to
  2072.  *                      hop to a next page
  2073.  * @param   string      Near the current page, how many pages should
  2074.  *                      be considered "nearby" and displayed as
  2075.  *                      well?
  2076.  * @param   string      The prompt to display (sometimes empty)
  2077.  *
  2078.  * @access  public
  2079.  * @author  Garvin Hicking (pma@supergarv.de)
  2080.  */
  2081. function PMA_pageselector($url, $rows, $pageNow = 1, $nbTotalPage = 1,
  2082.     $showAll = 200, $sliceStart = 5, $sliceEnd = 5, $percent = 20,
  2083.     $range = 10, $prompt = '')
  2084. {
  2085.     $gotopage = $prompt
  2086.               . ' <select name="pos" onchange="goToUrl(this, \''
  2087.               . $url . '\');">' . "\n";
  2088.     if ($nbTotalPage < $showAll) {
  2089.         $pages = range(1, $nbTotalPage);
  2090.     } else {
  2091.         $pages = array();
  2092.  
  2093.         // Always show first X pages
  2094.         for ($i = 1; $i <= $sliceStart; $i++) {
  2095.             $pages[] = $i;
  2096.         }
  2097.  
  2098.         // Always show last X pages
  2099.         for ($i = $nbTotalPage - $sliceEnd; $i <= $nbTotalPage; $i++) {
  2100.             $pages[] = $i;
  2101.         }
  2102.  
  2103.         // garvin: Based on the number of results we add the specified
  2104.         // $percent percentate to each page number,
  2105.         // so that we have a representing page number every now and then to
  2106.         // immideately jump to specific pages.
  2107.         // As soon as we get near our currently chosen page ($pageNow -
  2108.         // $range), every page number will be
  2109.         // shown.
  2110.         $i = $sliceStart;
  2111.         $x = $nbTotalPage - $sliceEnd;
  2112.         $met_boundary = false;
  2113.         while ($i <= $x) {
  2114.             if ($i >= ($pageNow - $range) && $i <= ($pageNow + $range)) {
  2115.                 // If our pageselector comes near the current page, we use 1
  2116.                 // counter increments
  2117.                 $i++;
  2118.                 $met_boundary = true;
  2119.             } else {
  2120.                 // We add the percentate increment to our current page to
  2121.                 // hop to the next one in range
  2122.                 $i = $i + floor($nbTotalPage / $percent);
  2123.  
  2124.                 // Make sure that we do not cross our boundaries.
  2125.                 if ($i > ($pageNow - $range) && !$met_boundary) {
  2126.                     $i = $pageNow - $range;
  2127.                 }
  2128.             }
  2129.  
  2130.             if ($i > 0 && $i <= $x) {
  2131.                 $pages[] = $i;
  2132.             }
  2133.         }
  2134.  
  2135.         // Since because of ellipsing of the current page some numbers may be double,
  2136.         // we unify our array:
  2137.         sort($pages);
  2138.         $pages = array_unique($pages);
  2139.     }
  2140.  
  2141.     foreach ($pages as $i) {
  2142.         if ($i == $pageNow) {
  2143.             $selected = 'selected="selected" style="font-weight: bold"';
  2144.         } else {
  2145.             $selected = '';
  2146.         }
  2147.         $gotopage .= '                <option ' . $selected . ' value="' . (($i - 1) * $rows) . '">' . $i . '</option>' . "\n";
  2148.     }
  2149.  
  2150.     $gotopage .= ' </select><noscript><input type="submit" value="' . $GLOBALS['strGo'] . '" /></noscript>';
  2151.  
  2152.  
  2153.     return $gotopage;
  2154. } // end function
  2155.  
  2156.  
  2157. /**
  2158.  * Generate navigation for a list
  2159.  *
  2160.  * @todo    use $pos from $_url_params
  2161.  * @uses    $GLOBALS['strPageNumber']
  2162.  * @uses    range()
  2163.  * @param   integer     number of elements in the list
  2164.  * @param   integer     current position in the list
  2165.  * @param   array       url parameters
  2166.  * @param   string      script name for form target
  2167.  * @param   string      target frame
  2168.  * @param   integer     maximum number of elements to display from the list
  2169.  *
  2170.  * @access  public
  2171.  */
  2172. function PMA_listNavigator($count, $pos, $_url_params, $script, $frame, $max_count) {
  2173.  
  2174.     if ($max_count < $count) {
  2175.         echo 'frame_navigation' == $frame ? '<div id="navidbpageselector">' . "\n" : '';
  2176.         echo $GLOBALS['strPageNumber'];
  2177.         echo 'frame_navigation' == $frame ? '<br />' : ' ';
  2178.  
  2179.         // Move to the beginning or to the previous page
  2180.         if ($pos > 0) {
  2181.             // loic1: patch #474210 from Gosha Sakovich - part 1
  2182.             if ($GLOBALS['cfg']['NavigationBarIconic']) {
  2183.                 $caption1 = '<<';
  2184.                 $caption2 = ' < ';
  2185.                 $title1   = ' title="' . $GLOBALS['strPos1'] . '"';
  2186.                 $title2   = ' title="' . $GLOBALS['strPrevious'] . '"';
  2187.             } else {
  2188.                 $caption1 = $GLOBALS['strPos1'] . ' <<';
  2189.                 $caption2 = $GLOBALS['strPrevious'] . ' <';
  2190.                 $title1   = '';
  2191.                 $title2   = '';
  2192.             } // end if... else...
  2193.             $_url_params['pos'] = 0;
  2194.             echo '<a' . $title1 . ' href="' . $script
  2195.                 . PMA_generate_common_url($_url_params) . '" target="' . $frame . '">'
  2196.                 . $caption1 . '</a>';
  2197.             $_url_params['pos'] = $pos - $max_count;
  2198.             echo '<a' . $title2 . ' href="' . $script
  2199.                 . PMA_generate_common_url($_url_params) . '" target="' . $frame . '">'
  2200.                 . $caption2 . '</a>';
  2201.         }
  2202.  
  2203.         echo "\n", '<form action="./', basename($script), '" method="post" target="', $frame, '">', "\n";
  2204.         echo PMA_generate_common_hidden_inputs($_url_params);
  2205.         echo PMA_pageselector(
  2206.             $script . PMA_generate_common_url($_url_params) . '&',
  2207.                 $max_count,
  2208.                 floor(($pos + 1) / $max_count) + 1,
  2209.                 ceil($count / $max_count));
  2210.         echo '</form>';
  2211.  
  2212.         if ($pos + $max_count < $count) {
  2213.             if ($GLOBALS['cfg']['NavigationBarIconic']) {
  2214.                 $caption3 = ' > ';
  2215.                 $caption4 = '>>';
  2216.                 $title3   = ' title="' . $GLOBALS['strNext'] . '"';
  2217.                 $title4   = ' title="' . $GLOBALS['strEnd'] . '"';
  2218.             } else {
  2219.                 $caption3 = '> ' . $GLOBALS['strNext'];
  2220.                 $caption4 = '>> ' . $GLOBALS['strEnd'];
  2221.                 $title3   = '';
  2222.                 $title4   = '';
  2223.             } // end if... else...
  2224.             $_url_params['pos'] = $pos + $max_count;
  2225.             echo '<a' . $title3 . ' href="' . $script
  2226.                 . PMA_generate_common_url($_url_params) . '" target="' . $frame . '">'
  2227.                 . $caption3 . '</a>';
  2228.             $_url_params['pos'] = floor($count / $max_count) * $max_count;
  2229.             if ($_url_params['pos'] == $count) {
  2230.                 $_url_params['pos'] = $count - $max_count;
  2231.             }
  2232.             echo '<a' . $title4 . ' href="' . $script
  2233.                 . PMA_generate_common_url($_url_params) . '" target="' . $frame . '">'
  2234.                 . $caption4 . '</a>';
  2235.         }
  2236.         echo "\n";
  2237.         if ('frame_navigation' == $frame) {
  2238.             echo '</div>' . "\n";
  2239.         }
  2240.     }
  2241. }
  2242.  
  2243. /**
  2244.  * replaces %u in given path with current user name
  2245.  *
  2246.  * example:
  2247.  * <code>
  2248.  * $user_dir = PMA_userDir('/var/pma_tmp/%u/'); // '/var/pma_tmp/root/'
  2249.  *
  2250.  * </code>
  2251.  * @uses    $cfg['Server']['user']
  2252.  * @uses    substr()
  2253.  * @uses    str_replace()
  2254.  * @param   string  $dir with wildcard for user
  2255.  * @return  string  per user directory
  2256.  */
  2257. function PMA_userDir($dir)
  2258. {
  2259.     // add trailing slash
  2260.     if (substr($dir, -1) != '/') {
  2261.         $dir .= '/';
  2262.     }
  2263.  
  2264.     return str_replace('%u', $GLOBALS['cfg']['Server']['user'], $dir);
  2265. }
  2266.  
  2267. /**
  2268.  * returns html code for db link to default db page
  2269.  *
  2270.  * @uses    $cfg['DefaultTabDatabase']
  2271.  * @uses    $GLOBALS['db']
  2272.  * @uses    $GLOBALS['strJumpToDB']
  2273.  * @uses    PMA_generate_common_url()
  2274.  * @uses    PMA_unescape_mysql_wildcards()
  2275.  * @uses    strlen()
  2276.  * @uses    sprintf()
  2277.  * @uses    htmlspecialchars()
  2278.  * @param   string  $database
  2279.  * @return  string  html link to default db page
  2280.  */
  2281. function PMA_getDbLink($database = null)
  2282. {
  2283.     if (!strlen($database)) {
  2284.         if (!strlen($GLOBALS['db'])) {
  2285.             return '';
  2286.         }
  2287.         $database = $GLOBALS['db'];
  2288.     } else {
  2289.         $database = PMA_unescape_mysql_wildcards($database);
  2290.     }
  2291.  
  2292.     return '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($database) . '"'
  2293.         .' title="' . sprintf($GLOBALS['strJumpToDB'], htmlspecialchars($database)) . '">'
  2294.         .htmlspecialchars($database) . '</a>';
  2295. }
  2296.  
  2297. /**
  2298.  * Displays a lightbulb hint explaining a known external bug
  2299.  * that affects a functionality
  2300.  *
  2301.  * @uses    PMA_MYSQL_INT_VERSION
  2302.  * @uses    $GLOBALS['strKnownExternalBug']
  2303.  * @uses    PMA_showHint()
  2304.  * @uses    sprintf()
  2305.  * @param   string  $functionality localized message explaining the func.
  2306.  * @param   string  $component  'mysql' (eventually, 'php')
  2307.  * @param   string  $minimum_version of this component
  2308.  * @param   string  $bugref  bug reference for this component
  2309.  */
  2310. function PMA_externalBug($functionality, $component, $minimum_version, $bugref)
  2311. {
  2312.     if ($component == 'mysql' && PMA_MYSQL_INT_VERSION < $minimum_version) {
  2313.         echo PMA_showHint(sprintf($GLOBALS['strKnownExternalBug'], $functionality, 'http://bugs.mysql.com/' . $bugref));
  2314.     }
  2315. }
  2316.  
  2317. /**
  2318.  * Converts a bit value to printable format;
  2319.  * in MySQL a BIT field can be from 1 to 64 bits so we need this
  2320.  * function because in PHP, decbin() supports only 32 bits
  2321.  *
  2322.  * @uses    ceil()
  2323.  * @uses    decbin()
  2324.  * @uses    ord()
  2325.  * @uses    substr()
  2326.  * @uses    sprintf()
  2327.  * @param   numeric $value coming from a BIT field
  2328.  * @param   integer $length 
  2329.  * @return  string  the printable value 
  2330.  */
  2331. function PMA_printable_bit_value($value, $length) {
  2332.     $printable = '';
  2333.     for ($i = 0; $i < ceil($length / 8); $i++) {
  2334.         $printable .= sprintf('%08d', decbin(ord(substr($value, $i, 1))));
  2335.     }
  2336.     $printable = substr($printable, -$length);
  2337.     return $printable;
  2338. }
  2339.  
  2340. /**
  2341.  * Extracts the true field type and length from a field type spec
  2342.  *
  2343.  * @uses    strpos()
  2344.  * @uses    chop()
  2345.  * @uses    substr()
  2346.  * @param   string $fieldspec 
  2347.  * @return  array associative array containing the type and length 
  2348.  */
  2349. function PMA_extract_type_length($fieldspec) {
  2350.     $first_bracket_pos = strpos($fieldspec, '(');
  2351.     if ($first_bracket_pos) {
  2352.         $length = chop(substr($fieldspec, $first_bracket_pos + 1, (strpos($fieldspec, ')') - $first_bracket_pos - 1)));
  2353.         $type = chop(substr($fieldspec, 0, $first_bracket_pos));
  2354.     } else {
  2355.         $type = $fieldspec;
  2356.         $length = '';
  2357.     }
  2358.     return array(
  2359.         'type' => $type,
  2360.         'length' => $length
  2361.     );
  2362. }
  2363. ?>
  2364.