Example #1
0
/**
 * Adds backquotes on both sides of a database, table or field name.
 * and escapes backquotes inside the name with another backquote
 *
 * example:
 * <code>
 * echo PMA_backquote('owner`s db'); // `owner``s db`
 *
 * </code>
 *
 * @uses    PMA_backquote()
 * @uses    is_array()
 * @uses    strlen()
 * @uses    str_replace()
 * @param   mixed    $a_name    the database, table or field name to "backquote"
 *                              or array of it
 * @param   boolean  $do_it     a flag to bypass this function (used by dump
 *                              functions)
 * @return  mixed    the "backquoted" database, table or field name if the
 *                   current MySQL release is >= 3.23.6, the original one
 *                   else
 * @access  public
 */
function PMA_backquote($a_name, $do_it = true)
{
    if (is_array($a_name)) {
        foreach ($a_name as &$data) {
            $data = PMA_backquote($data, $do_it);
        }
        return $a_name;
    }
    if (!$do_it) {
        global $PMA_SQPdata_forbidden_word;
        global $PMA_SQPdata_forbidden_word_cnt;
        if (!PMA_STR_binarySearchInArr(strtoupper($a_name), $PMA_SQPdata_forbidden_word, $PMA_SQPdata_forbidden_word_cnt)) {
            return $a_name;
        }
    }
    // '0' is also empty for php :-(
    if (strlen($a_name) && $a_name !== '*') {
        return '`' . str_replace('`', '``', $a_name) . '`';
    } else {
        return $a_name;
    }
}
 /**
  * Formats SQL queries to html
  *
  * @param  array   The SQL queries
  * @param  string  mode
  * @param  integer starting token
  * @param  integer number of tokens to format, -1 = all
  *
  * @return string  The formatted SQL queries
  *
  * @access public
  */
 function PMA_SQP_formatHtml($arr, $mode = 'color', $start_token = 0, $number_of_tokens = -1)
 {
     // then check for an array
     if (!is_array($arr)) {
         return htmlspecialchars($arr);
     }
     // first check for the SQL parser having hit an error
     if (PMA_SQP_isError()) {
         return htmlspecialchars($arr['raw']);
     }
     // else do it properly
     switch ($mode) {
         case 'color':
             $str = '<span class="syntax">';
             $html_line_break = '<br />';
             break;
         case 'query_only':
             $str = '';
             $html_line_break = "\n";
             break;
         case 'text':
             $str = '';
             $html_line_break = '<br />';
             break;
     }
     // end switch
     $indent = 0;
     $bracketlevel = 0;
     $functionlevel = 0;
     $infunction = FALSE;
     $space_punct_listsep = ' ';
     $space_punct_listsep_function_name = ' ';
     // $space_alpha_reserved_word = '<br />'."\n";
     $space_alpha_reserved_word = ' ';
     $keywords_with_brackets_1before = array('INDEX', 'KEY', 'ON', 'USING');
     $keywords_with_brackets_1before_cnt = 4;
     $keywords_with_brackets_2before = array('IGNORE', 'INDEX', 'INTO', 'KEY', 'PRIMARY', 'PROCEDURE', 'REFERENCES', 'UNIQUE', 'USE');
     // $keywords_with_brackets_2before_cnt = count($keywords_with_brackets_2before);
     $keywords_with_brackets_2before_cnt = 9;
     // These reserved words do NOT get a newline placed near them.
     $keywords_no_newline = array('AS', 'ASC', 'DESC', 'DISTINCT', 'HOUR', 'INTERVAL', 'IS', 'LIKE', 'NOT', 'NULL', 'ON', 'REGEXP');
     $keywords_no_newline_cnt = 12;
     // These reserved words introduce a privilege list
     $keywords_priv_list = array('GRANT', 'REVOKE');
     $keywords_priv_list_cnt = 2;
     if ($number_of_tokens == -1) {
         $arraysize = $arr['len'];
     } else {
         $arraysize = $number_of_tokens;
     }
     $typearr = array();
     if ($arraysize >= 0) {
         $typearr[0] = '';
         $typearr[1] = '';
         $typearr[2] = '';
         //$typearr[3] = $arr[0]['type'];
         $typearr[3] = $arr[$start_token]['type'];
     }
     $in_priv_list = FALSE;
     for ($i = $start_token; $i < $arraysize; $i++) {
         // DEBUG echo "<b>" . $arr[$i]['data'] . "</b> " . $arr[$i]['type'] . "<br />";
         $before = '';
         $after = '';
         $indent = 0;
         // array_shift($typearr);
         /*
         0 prev2
         1 prev
         2 current
         3 next
         */
         if ($i + 1 < $arraysize) {
             // array_push($typearr, $arr[$i + 1]['type']);
             $typearr[4] = $arr[$i + 1]['type'];
         } else {
             //array_push($typearr, NULL);
             $typearr[4] = '';
         }
         for ($j = 0; $j < 4; $j++) {
             $typearr[$j] = $typearr[$j + 1];
         }
         switch ($typearr[2]) {
             case 'white_newline':
                 $before = '';
                 break;
             case 'punct_bracket_open_round':
                 $bracketlevel++;
                 $infunction = FALSE;
                 // Make sure this array is sorted!
                 if ($typearr[1] == 'alpha_functionName' || $typearr[1] == 'alpha_columnType' || $typearr[1] == 'punct' || $typearr[3] == 'digit_integer' || $typearr[3] == 'digit_hex' || $typearr[3] == 'digit_float' || $typearr[0] == 'alpha_reservedWord' && PMA_STR_binarySearchInArr(strtoupper($arr[$i - 2]['data']), $keywords_with_brackets_2before, $keywords_with_brackets_2before_cnt) || $typearr[1] == 'alpha_reservedWord' && PMA_STR_binarySearchInArr(strtoupper($arr[$i - 1]['data']), $keywords_with_brackets_1before, $keywords_with_brackets_1before_cnt)) {
                     $functionlevel++;
                     $infunction = TRUE;
                     $after .= ' ';
                 } else {
                     $indent++;
                     $after .= $mode != 'query_only' ? '<div class="syntax_indent' . $indent . '">' : ' ';
                 }
                 break;
             case 'alpha_identifier':
                 if ($typearr[1] == 'punct_qualifier' || $typearr[3] == 'punct_qualifier') {
                     $after = '';
                     $before = '';
                 }
                 if ($typearr[3] == 'alpha_columnType' || $typearr[3] == 'alpha_identifier') {
                     $after .= ' ';
                 }
                 break;
             case 'punct_qualifier':
                 $before = '';
                 $after = '';
                 break;
             case 'punct_listsep':
                 if ($infunction == TRUE) {
                     $after .= $space_punct_listsep_function_name;
                 } else {
                     $after .= $space_punct_listsep;
                 }
                 break;
             case 'punct_queryend':
                 if ($typearr[3] != 'comment_mysql' && $typearr[3] != 'comment_ansi' && $typearr[3] != 'comment_c') {
                     $after .= $html_line_break;
                     $after .= $html_line_break;
                 }
                 $space_punct_listsep = ' ';
                 $space_punct_listsep_function_name = ' ';
                 $space_alpha_reserved_word = ' ';
                 $in_priv_list = FALSE;
                 break;
             case 'comment_mysql':
             case 'comment_ansi':
                 $after .= $html_line_break;
                 break;
             case 'punct':
                 $before .= ' ';
                 // workaround for
                 // select * from mytable limit 0,-1
                 // (a side effect of this workaround is that
                 // select 20 - 9
                 // becomes
                 // select 20 -9
                 // )
                 if ($typearr[3] != 'digit_integer') {
                     $after .= ' ';
                 }
                 break;
             case 'punct_bracket_close_round':
                 $bracketlevel--;
                 if ($infunction == TRUE) {
                     $functionlevel--;
                     $after .= ' ';
                     $before .= ' ';
                 } else {
                     $indent--;
                     $before .= $mode != 'query_only' ? '</div>' : ' ';
                 }
                 $infunction = $functionlevel > 0 ? TRUE : FALSE;
                 break;
             case 'alpha_columnType':
                 if ($typearr[3] == 'alpha_columnAttrib') {
                     $after .= ' ';
                 }
                 if ($typearr[1] == 'alpha_columnType') {
                     $before .= ' ';
                 }
                 break;
             case 'alpha_columnAttrib':
                 // ALTER TABLE tbl_name AUTO_INCREMENT = 1
                 // COLLATE LATIN1_GENERAL_CI DEFAULT
                 if ($typearr[1] == 'alpha_identifier' || $typearr[1] == 'alpha_charset') {
                     $before .= ' ';
                 }
                 if ($typearr[3] == 'alpha_columnAttrib' || $typearr[3] == 'quote_single' || $typearr[3] == 'digit_integer') {
                     $after .= ' ';
                 }
                 // workaround for
                 // select * from mysql.user where binary user="******"
                 // binary is marked as alpha_columnAttrib
                 // but should be marked as a reserved word
                 if (strtoupper($arr[$i]['data']) == 'BINARY' && $typearr[3] == 'alpha_identifier') {
                     $after .= ' ';
                 }
                 break;
             case 'alpha_reservedWord':
                 // do not uppercase the reserved word if we are calling
                 // this function in query_only mode, because we need
                 // the original query (otherwise we get problems with
                 // semi-reserved words like "storage" which is legal
                 // as an identifier name)
                 if ($mode != 'query_only') {
                     $arr[$i]['data'] = strtoupper($arr[$i]['data']);
                 }
                 if (($typearr[1] != 'alpha_reservedWord' || $typearr[1] == 'alpha_reservedWord' && PMA_STR_binarySearchInArr(strtoupper($arr[$i - 1]['data']), $keywords_no_newline, $keywords_no_newline_cnt)) && $typearr[1] != 'punct_level_plus' && !PMA_STR_binarySearchInArr($arr[$i]['data'], $keywords_no_newline, $keywords_no_newline_cnt)) {
                     // do not put a space before the first token, because
                     // we use a lot of eregi() checking for the first
                     // reserved word at beginning of query
                     // so do not put a newline before
                     //
                     // also we must not be inside a privilege list
                     if ($i > 0) {
                         // the alpha_identifier exception is there to
                         // catch cases like
                         // GRANT SELECT ON mydb.mytable TO myuser@localhost
                         // (else, we get mydb.mytableTO )
                         //
                         // the quote_single exception is there to
                         // catch cases like
                         // GRANT ... TO 'marc'@'domain.com' IDENTIFIED...
                         //
                         // TODO: fix all cases and find why this happens
                         if (!$in_priv_list || $typearr[1] == 'alpha_identifier' || $typearr[1] == 'quote_single' || $typearr[1] == 'white_newline') {
                             $before .= $space_alpha_reserved_word;
                         }
                     } else {
                         // on first keyword, check if it introduces a
                         // privilege list
                         if (PMA_STR_binarySearchInArr($arr[$i]['data'], $keywords_priv_list, $keywords_priv_list_cnt)) {
                             $in_priv_list = TRUE;
                         }
                     }
                 } else {
                     $before .= ' ';
                 }
                 switch ($arr[$i]['data']) {
                     case 'CREATE':
                         if (!$in_priv_list) {
                             $space_punct_listsep = $html_line_break;
                             $space_alpha_reserved_word = ' ';
                         }
                         break;
                     case 'EXPLAIN':
                     case 'DESCRIBE':
                     case 'SET':
                     case 'ALTER':
                     case 'DELETE':
                     case 'SHOW':
                     case 'DROP':
                     case 'UPDATE':
                     case 'TRUNCATE':
                     case 'ANALYZE':
                     case 'ANALYSE':
                         if (!$in_priv_list) {
                             $space_punct_listsep = $html_line_break;
                             $space_alpha_reserved_word = ' ';
                         }
                         break;
                     case 'INSERT':
                     case 'REPLACE':
                         if (!$in_priv_list) {
                             $space_punct_listsep = $html_line_break;
                             $space_alpha_reserved_word = $html_line_break;
                         }
                         break;
                     case 'VALUES':
                         $space_punct_listsep = ' ';
                         $space_alpha_reserved_word = $html_line_break;
                         break;
                     case 'SELECT':
                         $space_punct_listsep = ' ';
                         $space_alpha_reserved_word = $html_line_break;
                         break;
                     default:
                         break;
                 }
                 // end switch ($arr[$i]['data'])
                 $after .= ' ';
                 break;
             case 'digit_integer':
             case 'digit_float':
             case 'digit_hex':
                 //TODO: could there be other types preceding a digit?
                 if ($typearr[1] == 'alpha_reservedWord') {
                     $after .= ' ';
                 }
                 if ($infunction && $typearr[3] == 'punct_bracket_close_round') {
                     $after .= ' ';
                 }
                 if ($typearr[1] == 'alpha_columnAttrib') {
                     $before .= ' ';
                 }
                 break;
             case 'alpha_variable':
                 // other workaround for a problem similar to the one
                 // explained below for quote_single
                 if (!$in_priv_list) {
                     $after = ' ';
                 }
                 break;
             case 'quote_double':
             case 'quote_single':
                 // workaround: for the query
                 // REVOKE SELECT ON `base2\_db`.* FROM 'user'@'%'
                 // the @ is incorrectly marked as alpha_variable
                 // in the parser, and here, the '%' gets a blank before,
                 // which is a syntax error
                 if ($typearr[1] != 'alpha_variable') {
                     $before .= ' ';
                 }
                 if ($infunction && $typearr[3] == 'punct_bracket_close_round') {
                     $after .= ' ';
                 }
                 break;
             case 'quote_backtick':
                 if ($typearr[3] != 'punct_qualifier') {
                     $after .= ' ';
                 }
                 if ($typearr[1] != 'punct_qualifier') {
                     $before .= ' ';
                 }
                 break;
             default:
                 break;
         }
         // end switch ($typearr[2])
         /*
                     if ($typearr[3] != 'punct_qualifier') {
                         $after             .= ' ';
                     }
                     $after                 .= "\n";
         */
         $str .= $before . ($mode == 'color' ? PMA_SQP_formatHTML_colorize($arr[$i]) : $arr[$i]['data']) . $after;
     }
     // end for
     if ($mode == 'color') {
         $str .= '</span>';
     }
     return $str;
 }
Example #3
0
 /**
  * Formats SQL queries to html
  *
  * @param  array   The SQL queries
  * @param  string  mode
  * @param  integer starting token
  * @param  integer number of tokens to format, -1 = all
  *
  * @return string  The formatted SQL queries
  *
  * @access public
  */
 function PMA_SQP_formatHtml($arr, $mode = 'color', $start_token = 0, $number_of_tokens = -1)
 {
     //DEBUG echo 'in Format<pre>'; print_r($arr); echo '</pre>';
     // then check for an array
     if (!is_array($arr)) {
         return htmlspecialchars($arr);
     }
     // first check for the SQL parser having hit an error
     if (PMA_SQP_isError()) {
         return htmlspecialchars($arr['raw']);
     }
     // else do it properly
     switch ($mode) {
         case 'color':
             $str = '<span class="syntax">';
             $html_line_break = '<br />';
             $docu = TRUE;
             break;
         case 'query_only':
             $str = '';
             $html_line_break = "\n";
             $docu = FALSE;
             break;
         case 'text':
             $str = '';
             $html_line_break = '<br />';
             $docu = TRUE;
             break;
     }
     // end switch
     // inner_sql is a span that exists for all cases, except query_only
     // of $cfg['SQP']['fmtType'] to make possible a replacement
     // for inline editing
     if ($mode != 'query_only') {
         $str .= '<span class="inner_sql">';
     }
     $close_docu_link = false;
     $indent = 0;
     $bracketlevel = 0;
     $functionlevel = 0;
     $infunction = FALSE;
     $space_punct_listsep = ' ';
     $space_punct_listsep_function_name = ' ';
     // $space_alpha_reserved_word = '<br />'."\n";
     $space_alpha_reserved_word = ' ';
     $keywords_with_brackets_1before = array('INDEX', 'KEY', 'ON', 'USING');
     $keywords_with_brackets_1before_cnt = 4;
     $keywords_with_brackets_2before = array('IGNORE', 'INDEX', 'INTO', 'KEY', 'PRIMARY', 'PROCEDURE', 'REFERENCES', 'UNIQUE', 'USE');
     // $keywords_with_brackets_2before_cnt = count($keywords_with_brackets_2before);
     $keywords_with_brackets_2before_cnt = 9;
     // These reserved words do NOT get a newline placed near them.
     $keywords_no_newline = array('AS', 'ASC', 'DESC', 'DISTINCT', 'DUPLICATE', 'HOUR', 'INTERVAL', 'IS', 'LIKE', 'NOT', 'NULL', 'ON', 'REGEXP');
     $keywords_no_newline_cnt = 12;
     // These reserved words introduce a privilege list
     $keywords_priv_list = array('GRANT', 'REVOKE');
     $keywords_priv_list_cnt = 2;
     if ($number_of_tokens == -1) {
         $arraysize = $arr['len'];
     } else {
         $arraysize = $number_of_tokens;
     }
     $typearr = array();
     if ($arraysize >= 0) {
         $typearr[0] = '';
         $typearr[1] = '';
         $typearr[2] = '';
         //$typearr[3] = $arr[0]['type'];
         $typearr[3] = $arr[$start_token]['type'];
     }
     $in_priv_list = FALSE;
     for ($i = $start_token; $i < $arraysize; $i++) {
         // DEBUG echo "Loop format <strong>" . $arr[$i]['data'] . "</strong> " . $arr[$i]['type'] . "<br />";
         $before = '';
         $after = '';
         // array_shift($typearr);
         /*
         0 prev2
         1 prev
         2 current
         3 next
         */
         if ($i + 1 < $arraysize) {
             // array_push($typearr, $arr[$i + 1]['type']);
             $typearr[4] = $arr[$i + 1]['type'];
         } else {
             //array_push($typearr, null);
             $typearr[4] = '';
         }
         for ($j = 0; $j < 4; $j++) {
             $typearr[$j] = $typearr[$j + 1];
         }
         switch ($typearr[2]) {
             case 'alpha_bitfield_constant_introducer':
                 $before = ' ';
                 $after = '';
                 break;
             case 'white_newline':
                 $before = '';
                 break;
             case 'punct_bracket_open_round':
                 $bracketlevel++;
                 $infunction = FALSE;
                 // Make sure this array is sorted!
                 if ($typearr[1] == 'alpha_functionName' || $typearr[1] == 'alpha_columnType' || $typearr[1] == 'punct' || $typearr[3] == 'digit_integer' || $typearr[3] == 'digit_hex' || $typearr[3] == 'digit_float' || $typearr[0] == 'alpha_reservedWord' && PMA_STR_binarySearchInArr(strtoupper($arr[$i - 2]['data']), $keywords_with_brackets_2before, $keywords_with_brackets_2before_cnt) || $typearr[1] == 'alpha_reservedWord' && PMA_STR_binarySearchInArr(strtoupper($arr[$i - 1]['data']), $keywords_with_brackets_1before, $keywords_with_brackets_1before_cnt)) {
                     $functionlevel++;
                     $infunction = TRUE;
                     $after .= ' ';
                 } else {
                     $indent++;
                     $after .= $mode != 'query_only' ? '<div class="syntax_indent' . $indent . '">' : ' ';
                 }
                 break;
             case 'alpha_identifier':
                 if ($typearr[1] == 'punct_qualifier' || $typearr[3] == 'punct_qualifier') {
                     $after = '';
                     $before = '';
                 }
                 // for example SELECT 1 somealias
                 if ($typearr[1] == 'digit_integer') {
                     $before = ' ';
                 }
                 if ($typearr[3] == 'alpha_columnType' || $typearr[3] == 'alpha_identifier') {
                     $after .= ' ';
                 }
                 break;
             case 'punct_user':
             case 'punct_qualifier':
                 $before = '';
                 $after = '';
                 break;
             case 'punct_listsep':
                 if ($infunction == TRUE) {
                     $after .= $space_punct_listsep_function_name;
                 } else {
                     $after .= $space_punct_listsep;
                 }
                 break;
             case 'punct_queryend':
                 if ($typearr[3] != 'comment_mysql' && $typearr[3] != 'comment_ansi' && $typearr[3] != 'comment_c') {
                     $after .= $html_line_break;
                     $after .= $html_line_break;
                 }
                 $space_punct_listsep = ' ';
                 $space_punct_listsep_function_name = ' ';
                 $space_alpha_reserved_word = ' ';
                 $in_priv_list = FALSE;
                 break;
             case 'comment_mysql':
             case 'comment_ansi':
                 $after .= $html_line_break;
                 break;
             case 'punct':
                 $before .= ' ';
                 // workaround for
                 // select * from mytable limit 0,-1
                 // (a side effect of this workaround is that
                 // select 20 - 9
                 // becomes
                 // select 20 -9
                 // )
                 if ($typearr[3] != 'digit_integer') {
                     $after .= ' ';
                 }
                 break;
             case 'punct_bracket_close_round':
                 // only close bracket level when it was opened before
                 if ($bracketlevel > 0) {
                     $bracketlevel--;
                     if ($infunction == TRUE) {
                         $functionlevel--;
                         $after .= ' ';
                         $before .= ' ';
                     } else {
                         $indent--;
                         $before .= $mode != 'query_only' ? '</div>' : ' ';
                     }
                     $infunction = $functionlevel > 0 ? TRUE : FALSE;
                 }
                 break;
             case 'alpha_columnType':
                 if ($docu) {
                     switch ($arr[$i]['data']) {
                         case 'tinyint':
                         case 'smallint':
                         case 'mediumint':
                         case 'int':
                         case 'bigint':
                         case 'decimal':
                         case 'float':
                         case 'double':
                         case 'real':
                         case 'bit':
                         case 'boolean':
                         case 'serial':
                             $before .= PMA_showMySQLDocu('data-types', 'numeric-types', false, '', true);
                             $after = '</a>' . $after;
                             break;
                         case 'date':
                         case 'datetime':
                         case 'timestamp':
                         case 'time':
                         case 'year':
                             $before .= PMA_showMySQLDocu('data-types', 'date-and-time-types', false, '', true);
                             $after = '</a>' . $after;
                             break;
                         case 'char':
                         case 'varchar':
                         case 'tinytext':
                         case 'text':
                         case 'mediumtext':
                         case 'longtext':
                         case 'binary':
                         case 'varbinary':
                         case 'tinyblob':
                         case 'mediumblob':
                         case 'blob':
                         case 'longblob':
                         case 'enum':
                         case 'set':
                             $before .= PMA_showMySQLDocu('data-types', 'string-types', false, '', true);
                             $after = '</a>' . $after;
                             break;
                     }
                 }
                 if ($typearr[3] == 'alpha_columnAttrib') {
                     $after .= ' ';
                 }
                 if ($typearr[1] == 'alpha_columnType') {
                     $before .= ' ';
                 }
                 break;
             case 'alpha_columnAttrib':
                 // ALTER TABLE tbl_name AUTO_INCREMENT = 1
                 // COLLATE LATIN1_GENERAL_CI DEFAULT
                 if ($typearr[1] == 'alpha_identifier' || $typearr[1] == 'alpha_charset') {
                     $before .= ' ';
                 }
                 if ($typearr[3] == 'alpha_columnAttrib' || $typearr[3] == 'quote_single' || $typearr[3] == 'digit_integer') {
                     $after .= ' ';
                 }
                 // workaround for
                 // AUTO_INCREMENT = 31DEFAULT_CHARSET = utf-8
                 if ($typearr[2] == 'alpha_columnAttrib' && $typearr[3] == 'alpha_reservedWord') {
                     $before .= ' ';
                 }
                 // workaround for
                 // select * from mysql.user where binary user="******"
                 // binary is marked as alpha_columnAttrib
                 // but should be marked as a reserved word
                 if (strtoupper($arr[$i]['data']) == 'BINARY' && $typearr[3] == 'alpha_identifier') {
                     $after .= ' ';
                 }
                 break;
             case 'alpha_reservedWord':
                 // do not uppercase the reserved word if we are calling
                 // this function in query_only mode, because we need
                 // the original query (otherwise we get problems with
                 // semi-reserved words like "storage" which is legal
                 // as an identifier name)
                 if ($mode != 'query_only') {
                     $arr[$i]['data'] = strtoupper($arr[$i]['data']);
                 }
                 if (($typearr[1] != 'alpha_reservedWord' || $typearr[1] == 'alpha_reservedWord' && PMA_STR_binarySearchInArr(strtoupper($arr[$i - 1]['data']), $keywords_no_newline, $keywords_no_newline_cnt)) && $typearr[1] != 'punct_level_plus' && !PMA_STR_binarySearchInArr($arr[$i]['data'], $keywords_no_newline, $keywords_no_newline_cnt)) {
                     // do not put a space before the first token, because
                     // we use a lot of pattern matching checking for the
                     // first reserved word at beginning of query
                     // so do not put a newline before
                     //
                     // also we must not be inside a privilege list
                     if ($i > 0) {
                         // the alpha_identifier exception is there to
                         // catch cases like
                         // GRANT SELECT ON mydb.mytable TO myuser@localhost
                         // (else, we get mydb.mytableTO)
                         //
                         // the quote_single exception is there to
                         // catch cases like
                         // GRANT ... TO 'marc'@'domain.com' IDENTIFIED...
                         /**
                          * @todo fix all cases and find why this happens
                          */
                         if (!$in_priv_list || $typearr[1] == 'alpha_identifier' || $typearr[1] == 'quote_single' || $typearr[1] == 'white_newline') {
                             $before .= $space_alpha_reserved_word;
                         }
                     } else {
                         // on first keyword, check if it introduces a
                         // privilege list
                         if (PMA_STR_binarySearchInArr($arr[$i]['data'], $keywords_priv_list, $keywords_priv_list_cnt)) {
                             $in_priv_list = TRUE;
                         }
                     }
                 } else {
                     $before .= ' ';
                 }
                 switch ($arr[$i]['data']) {
                     case 'CREATE':
                     case 'ALTER':
                     case 'DROP':
                     case 'RENAME':
                     case 'TRUNCATE':
                     case 'ANALYZE':
                     case 'ANALYSE':
                     case 'OPTIMIZE':
                         if ($docu) {
                             switch ($arr[$i + 1]['data']) {
                                 case 'EVENT':
                                 case 'TABLE':
                                 case 'TABLESPACE':
                                 case 'FUNCTION':
                                 case 'INDEX':
                                 case 'PROCEDURE':
                                 case 'TRIGGER':
                                 case 'SERVER':
                                 case 'DATABASE':
                                 case 'VIEW':
                                     $before .= PMA_showMySQLDocu('SQL-Syntax', $arr[$i]['data'] . '_' . $arr[$i + 1]['data'], false, '', true);
                                     $close_docu_link = true;
                                     break;
                             }
                             if ($arr[$i + 1]['data'] == 'LOGFILE' && $arr[$i + 2]['data'] == 'GROUP') {
                                 $before .= PMA_showMySQLDocu('SQL-Syntax', $arr[$i]['data'] . '_LOGFILE_GROUP', false, '', true);
                                 $close_docu_link = true;
                             }
                         }
                         if (!$in_priv_list) {
                             $space_punct_listsep = $html_line_break;
                             $space_alpha_reserved_word = ' ';
                         }
                         break;
                     case 'EVENT':
                     case 'TABLESPACE':
                     case 'TABLE':
                     case 'FUNCTION':
                     case 'INDEX':
                     case 'PROCEDURE':
                     case 'SERVER':
                     case 'TRIGGER':
                     case 'DATABASE':
                     case 'VIEW':
                     case 'GROUP':
                         if ($close_docu_link) {
                             $after = '</a>' . $after;
                             $close_docu_link = false;
                         }
                         break;
                     case 'SET':
                         if ($docu && ($i == 0 || $arr[$i - 1]['data'] != 'CHARACTER')) {
                             $before .= PMA_showMySQLDocu('SQL-Syntax', $arr[$i]['data'], false, '', true);
                             $after = '</a>' . $after;
                         }
                         if (!$in_priv_list) {
                             $space_punct_listsep = $html_line_break;
                             $space_alpha_reserved_word = ' ';
                         }
                         break;
                     case 'EXPLAIN':
                     case 'DESCRIBE':
                     case 'DELETE':
                     case 'SHOW':
                     case 'UPDATE':
                         if ($docu) {
                             $before .= PMA_showMySQLDocu('SQL-Syntax', $arr[$i]['data'], false, '', true);
                             $after = '</a>' . $after;
                         }
                         if (!$in_priv_list) {
                             $space_punct_listsep = $html_line_break;
                             $space_alpha_reserved_word = ' ';
                         }
                         break;
                     case 'INSERT':
                     case 'REPLACE':
                         if ($docu) {
                             $before .= PMA_showMySQLDocu('SQL-Syntax', $arr[$i]['data'], false, '', true);
                             $after = '</a>' . $after;
                         }
                         if (!$in_priv_list) {
                             $space_punct_listsep = $html_line_break;
                             $space_alpha_reserved_word = $html_line_break;
                         }
                         break;
                     case 'VALUES':
                         $space_punct_listsep = ' ';
                         $space_alpha_reserved_word = $html_line_break;
                         break;
                     case 'SELECT':
                         if ($docu) {
                             $before .= PMA_showMySQLDocu('SQL-Syntax', 'SELECT', false, '', true);
                             $after = '</a>' . $after;
                         }
                         $space_punct_listsep = ' ';
                         $space_alpha_reserved_word = $html_line_break;
                         break;
                     case 'CALL':
                     case 'DO':
                     case 'HANDLER':
                         if ($docu) {
                             $before .= PMA_showMySQLDocu('SQL-Syntax', $arr[$i]['data'], false, '', true);
                             $after = '</a>' . $after;
                         }
                         break;
                     default:
                         break;
                 }
                 // end switch ($arr[$i]['data'])
                 $after .= ' ';
                 break;
             case 'digit_integer':
             case 'digit_float':
             case 'digit_hex':
                 /**
                  * @todo could there be other types preceding a digit?
                  */
                 if ($typearr[1] == 'alpha_reservedWord') {
                     $after .= ' ';
                 }
                 if ($infunction && $typearr[3] == 'punct_bracket_close_round') {
                     $after .= ' ';
                 }
                 if ($typearr[1] == 'alpha_columnAttrib') {
                     $before .= ' ';
                 }
                 break;
             case 'alpha_variable':
                 $after = ' ';
                 break;
             case 'quote_double':
             case 'quote_single':
                 // workaround: for the query
                 // REVOKE SELECT ON `base2\_db`.* FROM 'user'@'%'
                 // the @ is incorrectly marked as alpha_variable
                 // in the parser, and here, the '%' gets a blank before,
                 // which is a syntax error
                 if ($typearr[1] != 'punct_user' && $typearr[1] != 'alpha_bitfield_constant_introducer') {
                     $before .= ' ';
                 }
                 if ($infunction && $typearr[3] == 'punct_bracket_close_round') {
                     $after .= ' ';
                 }
                 break;
             case 'quote_backtick':
                 // here we check for punct_user to handle correctly
                 // DEFINER = `username`@`%`
                 // where @ is the punct_user and `%` is the quote_backtick
                 if ($typearr[3] != 'punct_qualifier' && $typearr[3] != 'alpha_variable' && $typearr[3] != 'punct_user') {
                     $after .= ' ';
                 }
                 if ($typearr[1] != 'punct_qualifier' && $typearr[1] != 'alpha_variable' && $typearr[1] != 'punct_user') {
                     $before .= ' ';
                 }
                 break;
             default:
                 break;
         }
         // end switch ($typearr[2])
         /*
                     if ($typearr[3] != 'punct_qualifier') {
                         $after             .= ' ';
                     }
                     $after                 .= "\n";
         */
         $str .= $before;
         if ($mode == 'color') {
             $str .= PMA_SQP_formatHTML_colorize($arr[$i]);
         } elseif ($mode == 'text') {
             $str .= htmlspecialchars($arr[$i]['data']);
         } else {
             $str .= $arr[$i]['data'];
         }
         $str .= $after;
     }
     // end for
     // close unclosed indent levels
     while ($indent > 0) {
         $indent--;
         $str .= $mode != 'query_only' ? '</div>' : ' ';
     }
     /* End possibly unclosed documentation link */
     if ($close_docu_link) {
         $str .= '</a>';
         $close_docu_link = false;
     }
     if ($mode != 'query_only') {
         // close inner_sql span
         $str .= '</span>';
     }
     if ($mode == 'color') {
         // close syntax span
         $str .= '</span>';
     }
     return $str;
 }