/** * Checks if a given character position in the string is escaped or not * * @uses PMA_strlen() * @uses PMA_substr() * @uses max() * @uses intval() * @param string string to check for * @param integer the character to check for * @param integer starting position in the string * @return boolean whether the character is escaped or not */ function PMA_STR_charIsEscaped($string, $pos, $start = 0) { $pos = max(intval($pos), 0); $start = max(intval($start), 0); $len = PMA_strlen($string); // Base case: // Check for string length or invalid input or special case of input // (pos == $start) if ($pos <= $start || $len <= max($pos, $start)) { return false; } $pos--; $escaped = false; while ($pos >= $start && PMA_substr($string, $pos, 1) == '\\') { $escaped = !$escaped; $pos--; } // end while return $escaped; }
/** * Displays the body of the results table * * @uses $_SESSION['tmp_user_values']['disp_direction'] * @uses $_SESSION['tmp_user_values']['repeat_cells'] * @uses $_SESSION['tmp_user_values']['max_rows'] * @uses $_SESSION['tmp_user_values']['display_text'] * @uses $_SESSION['tmp_user_values']['display_binary'] * @uses $_SESSION['tmp_user_values']['display_binary_as_hex'] * @uses $_SESSION['tmp_user_values']['display_blob'] * @param integer the link id associated to the query which results have * to be displayed * @param array which elements to display * @param array the list of relations * @param array the analyzed query * * @return boolean always true * * @global string $db the database name * @global string $table the table name * @global string $goto the URL to go back in case of errors * @global string $sql_query the SQL query * @global array $fields_meta the list of fields properties * @global integer $fields_cnt the total number of fields returned by * the SQL query * @global array $vertical_display informations used with vertical display * mode * @global array $highlight_columns column names to highlight * @global array $row current row data * * @access private * * @see PMA_displayTable() */ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { global $db, $table, $goto; global $sql_query, $fields_meta, $fields_cnt; global $vertical_display, $highlight_columns; global $row; // mostly because of browser transformations, to make the row-data accessible in a plugin $url_sql_query = $sql_query; // query without conditions to shorten URLs when needed, 200 is just // guess, it should depend on remaining URL length if (isset($analyzed_sql) && isset($analyzed_sql[0]) && isset($analyzed_sql[0]['querytype']) && $analyzed_sql[0]['querytype'] == 'SELECT' && strlen($sql_query) > 200) { $url_sql_query = 'SELECT '; if (isset($analyzed_sql[0]['queryflags']['distinct'])) { $url_sql_query .= ' DISTINCT '; } $url_sql_query .= $analyzed_sql[0]['select_expr_clause']; if (!empty($analyzed_sql[0]['from_clause'])) { $url_sql_query .= ' FROM ' . $analyzed_sql[0]['from_clause']; } } if (!is_array($map)) { $map = array(); } $row_no = 0; $vertical_display['edit'] = array(); $vertical_display['delete'] = array(); $vertical_display['data'] = array(); $vertical_display['row_delete'] = array(); // Correction University of Virginia 19991216 in the while below // Previous code assumed that all tables have keys, specifically that // the phpMyAdmin GUI should support row delete/edit only for such // tables. // Although always using keys is arguably the prescribed way of // defining a relational table, it is not required. This will in // particular be violated by the novice. // We want to encourage phpMyAdmin usage by such novices. So the code // below has been changed to conditionally work as before when the // table being displayed has one or more keys; but to display // delete/edit options correctly for tables without keys. $odd_row = true; while ($row = PMA_DBI_fetch_row($dt_result)) { // lem9: "vertical display" mode stuff if ($row_no != 0 && $_SESSION['tmp_user_values']['repeat_cells'] != 0 && !($row_no % $_SESSION['tmp_user_values']['repeat_cells']) && ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped')) { echo '<tr>' . "\n"; if ($vertical_display['emptypre'] > 0) { echo ' <th colspan="' . $vertical_display['emptypre'] . '">' . "\n" . ' </th>' . "\n"; } foreach ($vertical_display['desc'] as $val) { echo $val; } if ($vertical_display['emptyafter'] > 0) { echo ' <th colspan="' . $vertical_display['emptyafter'] . '">' . "\n" . ' </th>' . "\n"; } echo '</tr>' . "\n"; } // end if $class = $odd_row ? 'odd' : 'even'; $odd_row = !$odd_row; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { // loic1: pointer code part echo ' <tr class="' . $class . '">' . "\n"; $class = ''; } // 1. Prepares the row // 1.1 Results from a "SELECT" statement -> builds the // WHERE clause to use in links (a unique key if possible) /** * @todo $where_clause could be empty, for example a table * with only one field and it's a BLOB; in this case, * avoid to display the delete and edit links */ list($where_clause, $clause_is_unique) = PMA_getUniqueCondition($dt_result, $fields_cnt, $fields_meta, $row); $where_clause_html = urlencode($where_clause); // 1.2 Defines the URLs for the modify/delete link(s) if ($is_display['edit_lnk'] != 'nn' || $is_display['del_lnk'] != 'nn') { // We need to copy the value or else the == 'both' check will always return true if ($GLOBALS['cfg']['PropertiesIconic'] === 'both') { $iconic_spacer = '<div class="nowrap">'; } else { $iconic_spacer = ''; } // 1.2.1 Modify link(s) if ($is_display['edit_lnk'] == 'ur') { // update row case $_url_params = array('db' => $db, 'table' => $table, 'where_clause' => $where_clause, 'clause_is_unique' => $clause_is_unique, 'sql_query' => $url_sql_query, 'goto' => 'sql.php'); $edit_url = 'tbl_change.php' . PMA_generate_common_url($_url_params); $edit_str = PMA_getIcon('b_edit.png', $GLOBALS['strEdit'], true); } // end if (1.2.1) if (isset($GLOBALS['cfg']['Bookmark']['table']) && isset($GLOBALS['cfg']['Bookmark']['db']) && $table == $GLOBALS['cfg']['Bookmark']['table'] && $db == $GLOBALS['cfg']['Bookmark']['db'] && isset($row[1]) && isset($row[0])) { $_url_params = array('db' => $row[1], 'id_bookmark' => $row[0], 'action_bookmark' => '0', 'action_bookmark_all' => '1', 'SQL' => $GLOBALS['strExecuteBookmarked']); $bookmark_go = '<a href="import.php' . PMA_generate_common_url($_url_params) . ' " title="' . $GLOBALS['strExecuteBookmarked'] . '">'; $bookmark_go .= PMA_getIcon('b_bookmark.png', $GLOBALS['strExecuteBookmarked'], true); $bookmark_go .= '</a>'; } else { $bookmark_go = ''; } // 1.2.2 Delete/Kill link(s) if ($is_display['del_lnk'] == 'dr') { // delete row case $_url_params = array('db' => $db, 'table' => $table, 'sql_query' => $url_sql_query, 'zero_rows' => $GLOBALS['strDeleted'], 'goto' => empty($goto) ? 'tbl_sql.php' : $goto); $lnk_goto = 'sql.php' . PMA_generate_common_url($_url_params, 'text'); $del_query = 'DELETE FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table) . ' WHERE ' . $where_clause . ($clause_is_unique ? '' : ' LIMIT 1'); $_url_params = array('db' => $db, 'table' => $table, 'sql_query' => $del_query, 'zero_rows' => $GLOBALS['strDeleted'], 'goto' => $lnk_goto); $del_url = 'sql.php' . PMA_generate_common_url($_url_params); $js_conf = 'DELETE FROM ' . PMA_jsFormat($db) . '.' . PMA_jsFormat($table) . ' WHERE ' . PMA_jsFormat($where_clause, false) . ($clause_is_unique ? '' : ' LIMIT 1'); $del_str = PMA_getIcon('b_drop.png', $GLOBALS['strDelete'], true); } elseif ($is_display['del_lnk'] == 'kp') { // kill process case $_url_params = array('db' => $db, 'table' => $table, 'sql_query' => $url_sql_query, 'goto' => 'main.php'); $lnk_goto = 'sql.php' . PMA_generate_common_url($_url_params, 'text'); $_url_params = array('db' => 'mysql', 'sql_query' => 'KILL ' . $row[0], 'goto' => $lnk_goto); $del_url = 'sql.php' . PMA_generate_common_url($_url_params); $del_query = 'KILL ' . $row[0]; $js_conf = 'KILL ' . $row[0]; $del_str = PMA_getIcon('b_drop.png', $GLOBALS['strKill'], true); } // end if (1.2.2) // 1.3 Displays the links at left if required if ($GLOBALS['cfg']['ModifyDeleteAtLeft'] && ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped')) { $doWriteModifyAt = 'left'; require './libraries/display_tbl_links.lib.php'; } // end if (1.3) } // end if (1) // 2. Displays the rows' values for ($i = 0; $i < $fields_cnt; ++$i) { $meta = $fields_meta[$i]; $pointer = $i; // garvin: See if this column should get highlight because it's used in the // where-query. if (isset($highlight_columns) && (isset($highlight_columns[$meta->name]) || isset($highlight_columns[PMA_backquote($meta->name)]))) { $condition_field = true; } else { $condition_field = false; } $mouse_events = ''; if ($_SESSION['tmp_user_values']['disp_direction'] == 'vertical' && (!isset($GLOBALS['printview']) || $GLOBALS['printview'] != '1')) { if ($GLOBALS['cfg']['BrowsePointerEnable'] == true) { $mouse_events .= ' onmouseover="setVerticalPointer(this, ' . $row_no . ', \'over\', \'odd\', \'even\', \'hover\', \'marked\');"' . ' onmouseout="setVerticalPointer(this, ' . $row_no . ', \'out\', \'odd\', \'even\', \'hover\', \'marked\');" '; } if ($GLOBALS['cfg']['BrowseMarkerEnable'] == true) { $mouse_events .= ' onmousedown="setVerticalPointer(this, ' . $row_no . ', \'click\', \'odd\', \'even\', \'hover\', \'marked\'); setCheckboxColumn(\'id_rows_to_delete' . $row_no . '\');" '; } else { $mouse_events .= ' onmousedown="setCheckboxColumn(\'id_rows_to_delete' . $row_no . '\');" '; } } // end if // garvin: Wrap MIME-transformations. [MIME] $default_function = 'default_function'; // default_function $transform_function = $default_function; $transform_options = array(); if ($GLOBALS['cfgRelation']['mimework'] && $GLOBALS['cfg']['BrowseMIME']) { if (isset($GLOBALS['mime_map'][$meta->name]['mimetype']) && isset($GLOBALS['mime_map'][$meta->name]['transformation']) && !empty($GLOBALS['mime_map'][$meta->name]['transformation'])) { $include_file = $GLOBALS['mime_map'][$meta->name]['transformation']; if (file_exists('./libraries/transformations/' . $include_file)) { $transformfunction_name = str_replace('.inc.php', '', $GLOBALS['mime_map'][$meta->name]['transformation']); require_once './libraries/transformations/' . $include_file; if (function_exists('PMA_transformation_' . $transformfunction_name)) { $transform_function = 'PMA_transformation_' . $transformfunction_name; $transform_options = PMA_transformation_getOptions(isset($GLOBALS['mime_map'][$meta->name]['transformation_options']) ? $GLOBALS['mime_map'][$meta->name]['transformation_options'] : ''); $meta->mimetype = str_replace('_', '/', $GLOBALS['mime_map'][$meta->name]['mimetype']); } } // end if file_exists } // end if transformation is set } // end if mime/transformation works. $_url_params = array('db' => $db, 'table' => $table, 'where_clause' => $where_clause, 'transform_key' => $meta->name); if (!empty($sql_query)) { $_url_params['sql_query'] = $url_sql_query; } $transform_options['wrapper_link'] = PMA_generate_common_url($_url_params); // n u m e r i c if ($meta->numeric == 1) { // lem9: if two fields have the same name (this is possible // with self-join queries, for example), using $meta->name // will show both fields NULL even if only one is NULL, // so use the $pointer if (!isset($row[$i]) || is_null($row[$i])) { $vertical_display['data'][$row_no][$i] = ' <td align="right"' . $mouse_events . ' class="' . $class . ($condition_field ? ' condition' : '') . '"><i>NULL</i></td>' . "\n"; } elseif ($row[$i] != '') { $nowrap = ' nowrap'; $where_comparison = ' = ' . $row[$i]; $vertical_display['data'][$row_no][$i] = '<td align="right"' . PMA_prepare_row_data($mouse_events, $class, $condition_field, $analyzed_sql, $meta, $map, $row[$i], $transform_function, $default_function, $nowrap, $where_comparison, $transform_options); } else { $vertical_display['data'][$row_no][$i] = ' <td align="right"' . $mouse_events . ' class="' . $class . ' nowrap' . ($condition_field ? ' condition' : '') . '"> </td>' . "\n"; } // b l o b } elseif (stristr($meta->type, 'BLOB')) { // loic1 : PMA_mysql_fetch_fields returns BLOB in place of // TEXT fields type so we have to ensure it's really a BLOB $field_flags = PMA_DBI_field_flags($dt_result, $i); if (stristr($field_flags, 'BINARY')) { // rajk - for blobstreaming $bs_reference_exists = $allBSTablesExist = FALSE; // load PMA configuration $PMA_Config = $_SESSION['PMA_Config']; // if PMA configuration exists if ($PMA_Config) { // load BS variables $pluginsExist = $PMA_Config->get('BLOBSTREAMING_PLUGINS_EXIST'); // if BS plugins exist if ($pluginsExist) { // load BS databases $bs_tables = $PMA_Config->get('BLOBSTREAMABLE_DATABASES'); // if BS db array and specified db string not empty and valid if (!empty($bs_tables) && strlen($db) > 0) { $bs_tables = $bs_tables[$db]; if (isset($bs_tables)) { $allBSTablesExist = TRUE; // check if BS tables exist for given database foreach ($bs_tables as $table_key => $bs_tbl) { if (!$bs_tables[$table_key]['Exists']) { $allBSTablesExist = FALSE; break; } } } } } } // if necessary BS tables exist if ($allBSTablesExist) { $bs_reference_exists = PMA_BS_ReferenceExists($row[$i], $db); } // if valid BS reference exists if ($bs_reference_exists) { $blobtext = PMA_BS_CreateReferenceLink($row[$i], $db); } else { $blobtext = PMA_handle_non_printable_contents('BLOB', isset($row[$i]) ? $row[$i] : '', $transform_function, $transform_options, $default_function, $meta); } $vertical_display['data'][$row_no][$i] = ' <td align="left"' . $mouse_events . ' class="' . $class . ($condition_field ? ' condition' : '') . '">' . $blobtext . '</td>'; unset($blobtext); // not binary: } else { if (!isset($row[$i]) || is_null($row[$i])) { $vertical_display['data'][$row_no][$i] = ' <td' . $mouse_events . ' class="' . $class . ($condition_field ? ' condition' : '') . '"><i>NULL</i></td>' . "\n"; } elseif ($row[$i] != '') { // garvin: if a transform function for blob is set, none of these replacements will be made if (PMA_strlen($row[$i]) > $GLOBALS['cfg']['LimitChars'] && $_SESSION['tmp_user_values']['display_text'] == 'P') { $row[$i] = PMA_substr($row[$i], 0, $GLOBALS['cfg']['LimitChars']) . '...'; } // loic1: displays all space characters, 4 space // characters for tabulations and <cr>/<lf> $row[$i] = $default_function != $transform_function ? $transform_function($row[$i], $transform_options, $meta) : $default_function($row[$i], array(), $meta); $vertical_display['data'][$row_no][$i] = ' <td' . $mouse_events . ' class="' . $class . ($condition_field ? ' condition' : '') . '">' . $row[$i] . '</td>' . "\n"; } else { $vertical_display['data'][$row_no][$i] = ' <td' . $mouse_events . ' class="' . $class . ($condition_field ? ' condition' : '') . '"> </td>' . "\n"; } } // n o t n u m e r i c a n d n o t B L O B } else { if (!isset($row[$i]) || is_null($row[$i])) { $vertical_display['data'][$row_no][$i] = ' <td' . $mouse_events . ' class="' . $class . ($condition_field ? ' condition' : '') . '"><i>NULL</i></td>' . "\n"; } elseif ($row[$i] != '') { // loic1: support blanks in the key $relation_id = $row[$i]; // nijel: Cut all fields to $GLOBALS['cfg']['LimitChars'] // lem9: (unless it's a link-type transformation) if (PMA_strlen($row[$i]) > $GLOBALS['cfg']['LimitChars'] && $_SESSION['tmp_user_values']['display_text'] == 'P' && !strpos($transform_function, 'link') === true) { $row[$i] = PMA_substr($row[$i], 0, $GLOBALS['cfg']['LimitChars']) . '...'; } // loic1: displays special characters from binaries $field_flags = PMA_DBI_field_flags($dt_result, $i); if (isset($meta->_type) && $meta->_type === MYSQLI_TYPE_BIT) { $row[$i] = PMA_printable_bit_value($row[$i], $meta->length); } elseif (stristr($field_flags, 'BINARY') && $meta->type == 'string') { if ($_SESSION['tmp_user_values']['display_binary'] || isset($GLOBALS['is_analyse']) && $GLOBALS['is_analyse']) { // user asked to see the real contents of BINARY // fields, or we detected a PROCEDURE ANALYSE in // the query (results are reported as being // binary strings) if ($_SESSION['tmp_user_values']['display_binary_as_hex']) { $row[$i] = bin2hex($row[$i]); } else { $row[$i] = htmlspecialchars(PMA_replace_binary_contents($row[$i])); } } else { // we show the BINARY message and field's size // (or maybe use a transformation) $row[$i] = PMA_handle_non_printable_contents('BINARY', $row[$i], $transform_function, $transform_options, $default_function, $meta); } } // garvin: transform functions may enable no-wrapping: $function_nowrap = $transform_function . '_nowrap'; $bool_nowrap = $default_function != $transform_function && function_exists($function_nowrap) ? $function_nowrap($transform_options) : false; // loic1: do not wrap if date field type $nowrap = preg_match('@DATE|TIME@i', $meta->type) || $bool_nowrap ? ' nowrap' : ''; $where_comparison = ' = \'' . PMA_sqlAddslashes($row[$i]) . '\''; $vertical_display['data'][$row_no][$i] = '<td ' . PMA_prepare_row_data($mouse_events, $class, $condition_field, $analyzed_sql, $meta, $map, $row[$i], $transform_function, $default_function, $nowrap, $where_comparison, $transform_options); } else { $vertical_display['data'][$row_no][$i] = ' <td' . $mouse_events . ' class="' . $class . ($condition_field ? ' condition' : '') . '"> </td>' . "\n"; } } // lem9: output stored cell if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo $vertical_display['data'][$row_no][$i]; } if (isset($vertical_display['rowdata'][$i][$row_no])) { $vertical_display['rowdata'][$i][$row_no] .= $vertical_display['data'][$row_no][$i]; } else { $vertical_display['rowdata'][$i][$row_no] = $vertical_display['data'][$row_no][$i]; } } // end for (2) // 3. Displays the modify/delete links on the right if required if ($GLOBALS['cfg']['ModifyDeleteAtRight'] && ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped')) { $doWriteModifyAt = 'right'; require './libraries/display_tbl_links.lib.php'; } // end if (3) if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { ?> </tr> <?php } // end if // 4. Gather links of del_urls and edit_urls in an array for later // output if (!isset($vertical_display['edit'][$row_no])) { $vertical_display['edit'][$row_no] = ''; $vertical_display['delete'][$row_no] = ''; $vertical_display['row_delete'][$row_no] = ''; } $column_style_vertical = ''; if ($GLOBALS['cfg']['BrowsePointerEnable'] == true) { $column_style_vertical .= ' onmouseover="setVerticalPointer(this, ' . $row_no . ', \'over\', \'odd\', \'even\', \'hover\', \'marked\');"' . ' onmouseout="setVerticalPointer(this, ' . $row_no . ', \'out\', \'odd\', \'even\', \'hover\', \'marked\');"'; } $column_marker_vertical = ''; if ($GLOBALS['cfg']['BrowseMarkerEnable'] == true) { $column_marker_vertical .= 'setVerticalPointer(this, ' . $row_no . ', \'click\', \'odd\', \'even\', \'hover\', \'marked\');'; } if (!empty($del_url) && $is_display['del_lnk'] != 'kp') { $vertical_display['row_delete'][$row_no] .= ' <td align="center" class="' . $class . '" ' . $column_style_vertical . '>' . "\n" . ' <input type="checkbox" id="id_rows_to_delete' . $row_no . '[%_PMA_CHECKBOX_DIR_%]" name="rows_to_delete[' . $where_clause_html . ']"' . ' onclick="' . $column_marker_vertical . 'copyCheckboxesRange(\'rowsDeleteForm\', \'id_rows_to_delete' . $row_no . '\',\'[%_PMA_CHECKBOX_DIR_%]\');"' . ' value="' . htmlspecialchars($del_query) . '" ' . (isset($GLOBALS['checkall']) ? 'checked="checked"' : '') . ' />' . "\n" . ' </td>' . "\n"; } else { unset($vertical_display['row_delete'][$row_no]); } if (isset($edit_url)) { $vertical_display['edit'][$row_no] .= ' <td align="center" class="' . $class . '" ' . $column_style_vertical . '>' . "\n" . PMA_linkOrButton($edit_url, $edit_str, array(), false) . $bookmark_go . ' </td>' . "\n"; } else { unset($vertical_display['edit'][$row_no]); } if (isset($del_url)) { $vertical_display['delete'][$row_no] .= ' <td align="center" class="' . $class . '" ' . $column_style_vertical . '>' . "\n" . PMA_linkOrButton($del_url, $del_str, isset($js_conf) ? $js_conf : '', false) . ' </td>' . "\n"; } else { unset($vertical_display['delete'][$row_no]); } echo $_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped' ? "\n" : ''; $row_no++; } // end while // this is needed by PMA_displayTable() to generate the proper param // in the multi-edit and multi-delete form return $clause_is_unique; }
/** * Displays the body of the results table * * @param integer the link id associated to the query which results have * to be displayed * @param array which elements to display * @param array the list of relations * @param array the analyzed query * * @return boolean always true * * @global string $db the database name * @global string $table the table name * @global string $goto the url to go back in case of errors * @global boolean $dontlimitchars whether to limit the number of displayed * characters of text type fields or not * @global string $sql_query the sql query * @global integer $pos the current position in results * @global integer $session_max_rows the maximum number of rows per page * @global array $fields_meta the list of fields properties * @global integer $fields_cnt the total number of fields returned by * the sql query * @global array $vertical_display informations used with vertical display * mode * @global string $disp_direction the display mode * (horizontal/vertical/horizontalflipped) * @global integer $repeat_cells the number of row to display between two * table headers * @global array $highlight_columns collumn names to highlight * @gloabl array $row current row data * * @access private * * @see PMA_displayTable() */ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { global $db, $table, $goto, $dontlimitchars; global $sql_query, $pos, $session_max_rows, $fields_meta, $fields_cnt; global $vertical_display, $disp_direction, $repeat_cells, $highlight_columns; global $row; // mostly because of browser transformations, to make the row-data accessible in a plugin $url_sql_query = $sql_query; // query without conditions to shorten urls when needed, 200 is just // guess, it should depend on remaining url length if (isset($analyzed_sql) && isset($analyzed_sql[0]) && isset($analyzed_sql[0]['querytype']) && $analyzed_sql[0]['querytype'] == 'SELECT' && strlen($sql_query) > 200) { $url_sql_query = 'SELECT '; if (isset($analyzed_sql[0]['queryflags']['distinct'])) { $url_sql_query .= ' DISTINCT '; } $url_sql_query .= $analyzed_sql[0]['select_expr_clause']; if (!empty($analyzed_sql[0]['from_clause'])) { $url_sql_query .= ' FROM ' . $analyzed_sql[0]['from_clause']; } } if (!is_array($map)) { $map = array(); } $row_no = 0; $vertical_display['edit'] = array(); $vertical_display['delete'] = array(); $vertical_display['data'] = array(); $vertical_display['row_delete'] = array(); // Correction uva 19991216 in the while below // Previous code assumed that all tables have keys, specifically that // the phpMyAdmin GUI should support row delete/edit only for such // tables. // Although always using keys is arguably the prescribed way of // defining a relational table, it is not required. This will in // particular be violated by the novice. // We want to encourage phpMyAdmin usage by such novices. So the code // below has been changed to conditionally work as before when the // table being displayed has one or more keys; but to display // delete/edit options correctly for tables without keys. // loic1: use 'PMA_mysql_fetch_array' rather than 'PMA_mysql_fetch_row' // to get the NULL values // rabus: This function needs a little rework. // Using MYSQL_BOTH just pollutes the memory! // ne0x: Use function PMA_DBI_fetch_array() due to mysqli // compatibility. Now this function is wrapped. $odd_row = true; while ($row = PMA_DBI_fetch_row($dt_result)) { // lem9: "vertical display" mode stuff if ($row_no != 0 && $repeat_cells != 0 && !($row_no % $repeat_cells) && ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped')) { echo '<tr>' . "\n"; if ($vertical_display['emptypre'] > 0) { echo ' <th colspan="' . $vertical_display['emptypre'] . '">' . "\n" . ' </th>' . "\n"; } foreach ($vertical_display['desc'] as $val) { echo $val; } if ($vertical_display['emptyafter'] > 0) { echo ' <th colspan="' . $vertical_display['emptyafter'] . '">' . "\n" . ' </th>' . "\n"; } echo '</tr>' . "\n"; } // end if $class = $odd_row ? 'odd' : 'even'; $odd_row = !$odd_row; if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { // loic1: pointer code part echo ' <tr class="' . $class . '">' . "\n"; $class = ''; } // 1. Prepares the row (gets primary keys to use) // 1.1 Results from a "SELECT" statement -> builds the // "primary" key to use in links $uva_condition = urlencode(PMA_getUvaCondition($dt_result, $fields_cnt, $fields_meta, $row)); // 1.2 Defines the urls for the modify/delete link(s) $url_query = PMA_generate_common_url($db, $table) . '&pos=' . $pos . '&session_max_rows=' . $session_max_rows . '&disp_direction=' . $disp_direction . '&repeat_cells=' . $repeat_cells . '&dontlimitchars=' . $dontlimitchars; if ($is_display['edit_lnk'] != 'nn' || $is_display['del_lnk'] != 'nn') { // We need to copy the value or else the == 'both' check will always return true if ($GLOBALS['cfg']['PropertiesIconic'] === 'both') { $iconic_spacer = '<div class="nowrap">'; } else { $iconic_spacer = ''; } // 1.2.1 Modify link(s) if ($is_display['edit_lnk'] == 'ur') { // update row case $lnk_goto = 'sql.php'; $edit_url = 'tbl_change.php' . '?' . $url_query . '&primary_key=' . $uva_condition . '&sql_query=' . urlencode($url_sql_query) . '&goto=' . urlencode($lnk_goto); if ($GLOBALS['cfg']['PropertiesIconic'] === false) { $edit_str = $GLOBALS['strEdit']; } else { $edit_str = $iconic_spacer . '<img class="icon" width="16" height="16" src="' . $GLOBALS['pmaThemeImage'] . 'b_edit.png" alt="' . $GLOBALS['strEdit'] . '" title="' . $GLOBALS['strEdit'] . '" />'; if ($GLOBALS['cfg']['PropertiesIconic'] === 'both') { $edit_str .= ' ' . $GLOBALS['strEdit'] . '</div>'; } } } // end if (1.2.1) if ($table == $GLOBALS['cfg']['Bookmark']['table'] && $db == $GLOBALS['cfg']['Bookmark']['db'] && isset($row[1]) && isset($row[0])) { $bookmark_go = '<a href="import.php?' . PMA_generate_common_url($row[1], '') . '&id_bookmark=' . $row[0] . '&action_bookmark=0' . '&action_bookmark_all=1' . '&SQL=' . $GLOBALS['strExecuteBookmarked'] . ' " title="' . $GLOBALS['strExecuteBookmarked'] . '">'; if ($GLOBALS['cfg']['PropertiesIconic'] === false) { $bookmark_go .= $GLOBALS['strExecuteBookmarked']; } else { $bookmark_go .= $iconic_spacer . '<img class="icon" width="16" height="16" src="' . $GLOBALS['pmaThemeImage'] . 'b_bookmark.png" alt="' . $GLOBALS['strExecuteBookmarked'] . '" title="' . $GLOBALS['strExecuteBookmarked'] . '" />'; if ($GLOBALS['cfg']['PropertiesIconic'] === 'both') { $bookmark_go .= ' ' . $GLOBALS['strExecuteBookmarked'] . '</div>'; } } $bookmark_go .= '</a>'; } else { $bookmark_go = ''; } // 1.2.2 Delete/Kill link(s) if ($is_display['del_lnk'] == 'dr') { // delete row case $lnk_goto = 'sql.php' . '?' . str_replace('&', '&', $url_query) . '&sql_query=' . urlencode($url_sql_query) . '&zero_rows=' . urlencode(htmlspecialchars($GLOBALS['strDeleted'])) . '&goto=' . (empty($goto) ? 'tbl_properties.php' : $goto); $del_query = urlencode('DELETE FROM ' . PMA_backquote($table) . ' WHERE') . $uva_condition . '+LIMIT+1'; $del_url = 'sql.php' . '?' . $url_query . '&sql_query=' . $del_query . '&zero_rows=' . urlencode(htmlspecialchars($GLOBALS['strDeleted'])) . '&goto=' . urlencode($lnk_goto); $js_conf = 'DELETE FROM ' . PMA_jsFormat($table) . ' WHERE ' . trim(PMA_jsFormat(urldecode($uva_condition), false)) . ' LIMIT 1'; if ($GLOBALS['cfg']['PropertiesIconic'] === false) { $del_str = $GLOBALS['strDelete']; } else { $del_str = $iconic_spacer . '<img class="icon" width="16" height="16" src="' . $GLOBALS['pmaThemeImage'] . 'b_drop.png" alt="' . $GLOBALS['strDelete'] . '" title="' . $GLOBALS['strDelete'] . '" />'; if ($GLOBALS['cfg']['PropertiesIconic'] === 'both') { $del_str .= ' ' . $GLOBALS['strDelete'] . '</div>'; } } } elseif ($is_display['del_lnk'] == 'kp') { // kill process case $lnk_goto = 'sql.php' . '?' . str_replace('&', '&', $url_query) . '&sql_query=' . urlencode($url_sql_query) . '&goto=main.php'; $del_url = 'sql.php?' . PMA_generate_common_url('mysql') . '&sql_query=' . urlencode('KILL ' . $row[0]) . '&goto=' . urlencode($lnk_goto); $del_query = urlencode('KILL ' . $row[0]); $js_conf = 'KILL ' . $row[0]; if ($GLOBALS['cfg']['PropertiesIconic'] === false) { $del_str = $GLOBALS['strKill']; } else { $del_str = $iconic_spacer . '<img class="icon" width="16" height="16" src="' . $GLOBALS['pmaThemeImage'] . 'b_drop.png" alt="' . $GLOBALS['strKill'] . '" title="' . $GLOBALS['strKill'] . '" />'; if ($GLOBALS['cfg']['PropertiesIconic'] === 'both') { $del_str .= ' ' . $GLOBALS['strKill'] . '</div>'; } } } // end if (1.2.2) // 1.3 Displays the links at left if required if ($GLOBALS['cfg']['ModifyDeleteAtLeft'] && ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped')) { $doWriteModifyAt = 'left'; require './libraries/display_tbl_links.lib.php'; } // end if (1.3) } // end if (1) // 2. Displays the rows' values for ($i = 0; $i < $fields_cnt; ++$i) { $meta = $fields_meta[$i]; // loic1: To fix bug #474943 under php4, the row pointer will // depend on whether the "is_null" php4 function is // available or not $pointer = function_exists('is_null') ? $i : $meta->name; // garvin: See if this column should get highlight because it's used in the // where-query. if (isset($highlight_columns) && (isset($highlight_columns[$meta->name]) || isset($highlight_columns[PMA_backquote($meta->name)]))) { $condition_field = true; } else { $condition_field = false; } $mouse_events = ''; if ($disp_direction == 'vertical' && (!isset($GLOBALS['printview']) || $GLOBALS['printview'] != '1')) { if ($GLOBALS['cfg']['BrowsePointerEnable'] == true) { $mouse_events .= ' onmouseover="setVerticalPointer(this, ' . $row_no . ', \'over\', \'odd\', \'even\', \'hover\', \'marked\');"' . ' onmouseout="setVerticalPointer(this, ' . $row_no . ', \'out\', \'odd\', \'even\', \'hover\', \'marked\');" '; } if ($GLOBALS['cfg']['BrowseMarkerEnable'] == true) { $mouse_events .= ' onmousedown="setVerticalPointer(this, ' . $row_no . ', \'click\', \'odd\', \'even\', \'hover\', \'marked\'); setCheckboxColumn(\'id_rows_to_delete' . $row_no . '\');" '; } else { $mouse_events .= ' onmousedown="setCheckboxColumn(\'id_rows_to_delete' . $row_no . '\');" '; } } // end if // garvin: Wrap MIME-transformations. [MIME] $default_function = 'default_function'; // default_function $transform_function = $default_function; $transform_options = array(); if ($GLOBALS['cfgRelation']['mimework'] && $GLOBALS['cfg']['BrowseMIME']) { if (isset($GLOBALS['mime_map'][$meta->name]['mimetype']) && isset($GLOBALS['mime_map'][$meta->name]['transformation']) && !empty($GLOBALS['mime_map'][$meta->name]['transformation'])) { $include_file = PMA_sanitizeTransformationFile($GLOBALS['mime_map'][$meta->name]['transformation']); if (file_exists('./libraries/transformations/' . $include_file)) { $transformfunction_name = preg_replace('@(\\.inc\\.php3?)$@i', '', $GLOBALS['mime_map'][$meta->name]['transformation']); require_once './libraries/transformations/' . $include_file; if (function_exists('PMA_transformation_' . $transformfunction_name)) { $transform_function = 'PMA_transformation_' . $transformfunction_name; $transform_options = PMA_transformation_getOptions(isset($GLOBALS['mime_map'][$meta->name]['transformation_options']) ? $GLOBALS['mime_map'][$meta->name]['transformation_options'] : ''); $meta->mimetype = str_replace('_', '/', $GLOBALS['mime_map'][$meta->name]['mimetype']); } } // end if file_exists } // end if transformation is set } // end if mime/transformation works. $transform_options['wrapper_link'] = '?' . (isset($url_query) ? $url_query : '') . '&primary_key=' . (isset($uva_condition) ? $uva_condition : '') . '&sql_query=' . (isset($sql_query) ? urlencode($url_sql_query) : '') . '&goto=' . (isset($sql_goto) ? urlencode($lnk_goto) : '') . '&transform_key=' . urlencode($meta->name); // n u m e r i c if ($meta->numeric == 1) { // lem9: if two fields have the same name (this is possible // with self-join queries, for example), using $meta->name // will show both fields NULL even if only one is NULL, // so use the $pointer // (works only if function_exists('is_null') // PS: why not always work with the number ($i), since // the default second parameter of // mysql_fetch_array() is MYSQL_BOTH, so we always get // associative and numeric indices? //if (!isset($row[$meta->name]) if (!isset($row[$i]) || is_null($row[$i])) { $vertical_display['data'][$row_no][$i] = ' <td align="right"' . $mouse_events . ' class="' . $class . ($condition_field ? ' condition' : '') . '"><i>NULL</i></td>' . "\n"; } elseif ($row[$i] != '') { $vertical_display['data'][$row_no][$i] = ' <td align="right"' . $mouse_events . ' class="' . $class . ($condition_field ? ' condition' : '') . ' nowrap">'; if (isset($analyzed_sql[0]['select_expr']) && is_array($analyzed_sql[0]['select_expr'])) { foreach ($analyzed_sql[0]['select_expr'] as $select_expr_position => $select_expr) { $alias = $analyzed_sql[0]['select_expr'][$select_expr_position]['alias']; if (isset($alias) && strlen($alias)) { $true_column = $analyzed_sql[0]['select_expr'][$select_expr_position]['column']; if ($alias == $meta->name) { $meta->name = $true_column; } // end if } // end if } // end while } if (isset($map[$meta->name])) { // Field to display from the foreign table? if (isset($map[$meta->name][2]) && strlen($map[$meta->name][2])) { $dispsql = 'SELECT ' . PMA_backquote($map[$meta->name][2]) . ' FROM ' . PMA_backquote($map[$meta->name][3]) . '.' . PMA_backquote($map[$meta->name][0]) . ' WHERE ' . PMA_backquote($map[$meta->name][1]) . ' = ' . $row[$i]; $dispresult = PMA_DBI_try_query($dispsql, null, PMA_DBI_QUERY_STORE); if ($dispresult && PMA_DBI_num_rows($dispresult) > 0) { list($dispval) = PMA_DBI_fetch_row($dispresult, 0); } else { $dispval = $GLOBALS['strLinkNotFound']; } @PMA_DBI_free_result($dispresult); } else { $dispval = ''; } // end if... else... if (isset($GLOBALS['printview']) && $GLOBALS['printview'] == '1') { $vertical_display['data'][$row_no][$i] .= ($transform_function != $default_function ? $transform_function($row[$i], $transform_options, $meta) : $transform_function($row[$i], array(), $meta)) . ' <code>[->' . $dispval . ']</code>'; } else { $title = !empty($dispval) ? ' title="' . htmlspecialchars($dispval) . '"' : ''; $vertical_display['data'][$row_no][$i] .= '<a href="sql.php?' . PMA_generate_common_url($map[$meta->name][3], $map[$meta->name][0]) . '&pos=0&session_max_rows=' . $session_max_rows . '&dontlimitchars=' . $dontlimitchars . '&sql_query=' . urlencode('SELECT * FROM ' . PMA_backquote($map[$meta->name][0]) . ' WHERE ' . PMA_backquote($map[$meta->name][1]) . ' = ' . $row[$i]) . '"' . $title . '>' . ($transform_function != $default_function ? $transform_function($row[$i], $transform_options, $meta) : $transform_function($row[$i], array(), $meta)) . '</a>'; } } else { $vertical_display['data'][$row_no][$i] .= $transform_function != $default_function ? $transform_function($row[$i], $transform_options, $meta) : $transform_function($row[$i], array(), $meta); } $vertical_display['data'][$row_no][$i] .= '</td>' . "\n"; } else { $vertical_display['data'][$row_no][$i] = ' <td align="right"' . $mouse_events . ' class="' . $class . ' nowrap' . ($condition_field ? ' condition' : '') . '"> </td>' . "\n"; } // b l o b } elseif ($GLOBALS['cfg']['ShowBlob'] == false && stristr($meta->type, 'BLOB')) { // loic1 : PMA_mysql_fetch_fields returns BLOB in place of // TEXT fields type, however TEXT fields must be displayed // even if $GLOBALS['cfg']['ShowBlob'] is false -> get the true type // of the fields. $field_flags = PMA_DBI_field_flags($dt_result, $i); if (stristr($field_flags, 'BINARY')) { $blobtext = '[BLOB'; if (!isset($row[$i]) || is_null($row[$i])) { $blobtext .= ' - NULL'; $blob_size = 0; } elseif (isset($row[$i])) { $blob_size = strlen($row[$i]); $display_blob_size = PMA_formatByteDown($blob_size, 3, 1); $blobtext .= ' - ' . $display_blob_size[0] . ' ' . $display_blob_size[1]; unset($display_blob_size); } $blobtext .= ']'; if (strpos($transform_function, 'octetstream')) { $blobtext = $row[$i]; } if ($blob_size > 0) { $blobtext = $default_function != $transform_function ? $transform_function($blobtext, $transform_options, $meta) : $default_function($blobtext, array(), $meta); } unset($blob_size); $vertical_display['data'][$row_no][$i] = ' <td align="left"' . $mouse_events . ' class="' . $class . ($condition_field ? ' condition' : '') . '">' . $blobtext . '</td>'; } else { if (!isset($row[$i]) || is_null($row[$i])) { $vertical_display['data'][$row_no][$i] = ' <td' . $mouse_events . ' class="' . $class . ($condition_field ? ' condition' : '') . '"><i>NULL</i></td>' . "\n"; } elseif ($row[$i] != '') { // garvin: if a transform function for blob is set, none of these replacements will be made if (PMA_strlen($row[$i]) > $GLOBALS['cfg']['LimitChars'] && $dontlimitchars != 1) { $row[$i] = PMA_substr($row[$i], 0, $GLOBALS['cfg']['LimitChars']) . '...'; } // loic1: displays all space characters, 4 space // characters for tabulations and <cr>/<lf> $row[$i] = $default_function != $transform_function ? $transform_function($row[$i], $transform_options, $meta) : $default_function($row[$i], array(), $meta); $vertical_display['data'][$row_no][$i] = ' <td' . $mouse_events . ' class="' . $class . ($condition_field ? ' condition' : '') . '">' . $row[$i] . '</td>' . "\n"; } else { $vertical_display['data'][$row_no][$i] = ' <td' . $mouse_events . ' class="' . $class . ($condition_field ? ' condition' : '') . '"> </td>' . "\n"; } } } else { if (!isset($row[$i]) || is_null($row[$i])) { $vertical_display['data'][$row_no][$i] = ' <td' . $mouse_events . ' class="' . $class . ($condition_field ? ' condition' : '') . '"><i>NULL</i></td>' . "\n"; } elseif ($row[$i] != '') { // loic1: support blanks in the key $relation_id = $row[$i]; // nijel: Cut all fields to $GLOBALS['cfg']['LimitChars'] // lem9: (unless it's a link-type transformation) if (PMA_strlen($row[$i]) > $GLOBALS['cfg']['LimitChars'] && $dontlimitchars != 1 && !strpos($transform_function, 'link') === true) { $row[$i] = PMA_substr($row[$i], 0, $GLOBALS['cfg']['LimitChars']) . '...'; } // loic1: displays special characters from binaries $field_flags = PMA_DBI_field_flags($dt_result, $i); if (stristr($field_flags, 'BINARY')) { $row[$i] = str_replace("", '\\0', $row[$i]); $row[$i] = str_replace("", '\\b', $row[$i]); $row[$i] = str_replace("\n", '\\n', $row[$i]); $row[$i] = str_replace("\r", '\\r', $row[$i]); $row[$i] = str_replace("", '\\Z', $row[$i]); $row[$i] = $default_function != $transform_function ? $transform_function($row[$i], $transform_options, $meta) : $default_function($row[$i], array(), $meta); } else { $row[$i] = $default_function != $transform_function ? $transform_function($row[$i], $transform_options, $meta) : $default_function($row[$i], array(), $meta); } // garvin: transform functions may enable nowrapping: $function_nowrap = $transform_function . '_nowrap'; $bool_nowrap = $default_function != $transform_function && function_exists($function_nowrap) ? $function_nowrap($transform_options) : false; // loic1: do not wrap if date field type $nowrap = preg_match('@DATE|TIME@i', $meta->type) || $bool_nowrap ? ' nowrap' : ''; $vertical_display['data'][$row_no][$i] = ' <td' . $mouse_events . ' class="' . $class . $nowrap . ($condition_field ? ' condition' : '') . '">'; if (isset($analyzed_sql[0]['select_expr']) && is_array($analyzed_sql[0]['select_expr'])) { foreach ($analyzed_sql[0]['select_expr'] as $select_expr_position => $select_expr) { $alias = $analyzed_sql[0]['select_expr'][$select_expr_position]['alias']; if (isset($alias) && strlen($alias)) { $true_column = $analyzed_sql[0]['select_expr'][$select_expr_position]['column']; if ($alias == $meta->name) { $meta->name = $true_column; } // end if } // end if } // end while } if (isset($map[$meta->name])) { // Field to display from the foreign table? if (isset($map[$meta->name][2]) && strlen($map[$meta->name][2])) { $dispsql = 'SELECT ' . PMA_backquote($map[$meta->name][2]) . ' FROM ' . PMA_backquote($map[$meta->name][3]) . '.' . PMA_backquote($map[$meta->name][0]) . ' WHERE ' . PMA_backquote($map[$meta->name][1]) . ' = \'' . PMA_sqlAddslashes($row[$i]) . '\''; $dispresult = PMA_DBI_try_query($dispsql, null, PMA_DBI_QUERY_STORE); if ($dispresult && PMA_DBI_num_rows($dispresult) > 0) { list($dispval) = PMA_DBI_fetch_row($dispresult); @PMA_DBI_free_result($dispresult); } else { $dispval = $GLOBALS['strLinkNotFound']; } } else { $dispval = ''; } $title = !empty($dispval) ? ' title="' . htmlspecialchars($dispval) . '"' : ''; $vertical_display['data'][$row_no][$i] .= '<a href="sql.php?' . PMA_generate_common_url($map[$meta->name][3], $map[$meta->name][0]) . '&pos=0&session_max_rows=' . $session_max_rows . '&dontlimitchars=' . $dontlimitchars . '&sql_query=' . urlencode('SELECT * FROM ' . PMA_backquote($map[$meta->name][0]) . ' WHERE ' . PMA_backquote($map[$meta->name][1]) . ' = \'' . PMA_sqlAddslashes($relation_id) . '\'') . '"' . $title . '>' . $row[$i] . '</a>'; } else { $vertical_display['data'][$row_no][$i] .= $row[$i]; } $vertical_display['data'][$row_no][$i] .= '</td>' . "\n"; } else { $vertical_display['data'][$row_no][$i] = ' <td' . $mouse_events . ' class="' . $class . ($condition_field ? ' condition' : '') . '"> </td>' . "\n"; } } // lem9: output stored cell if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { echo $vertical_display['data'][$row_no][$i]; } if (isset($vertical_display['rowdata'][$i][$row_no])) { $vertical_display['rowdata'][$i][$row_no] .= $vertical_display['data'][$row_no][$i]; } else { $vertical_display['rowdata'][$i][$row_no] = $vertical_display['data'][$row_no][$i]; } } // end for (2) // 3. Displays the modify/delete links on the right if required if ($GLOBALS['cfg']['ModifyDeleteAtRight'] && ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped')) { $doWriteModifyAt = 'right'; require './libraries/display_tbl_links.lib.php'; } // end if (3) if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { ?> </tr> <?php } // end if // 4. Gather links of del_urls and edit_urls in an array for later // output if (!isset($vertical_display['edit'][$row_no])) { $vertical_display['edit'][$row_no] = ''; $vertical_display['delete'][$row_no] = ''; $vertical_display['row_delete'][$row_no] = ''; } $column_style_vertical = ''; if ($GLOBALS['cfg']['BrowsePointerEnable'] == true) { $column_style_vertical .= ' onmouseover="setVerticalPointer(this, ' . $row_no . ', \'over\', \'odd\', \'even\', \'hover\', \'marked\');"' . ' onmouseout="setVerticalPointer(this, ' . $row_no . ', \'out\', \'odd\', \'even\', \'hover\', \'marked\');"'; } $column_marker_vertical = ''; if ($GLOBALS['cfg']['BrowseMarkerEnable'] == true) { $column_marker_vertical .= 'setVerticalPointer(this, ' . $row_no . ', \'click\', \'odd\', \'even\', \'hover\', \'marked\');'; } if (!empty($del_url) && $is_display['del_lnk'] != 'kp') { $vertical_display['row_delete'][$row_no] .= ' <td align="center" class="' . $class . '" ' . $column_style_vertical . '>' . "\n" . ' <input type="checkbox" id="id_rows_to_delete' . $row_no . '[%_PMA_CHECKBOX_DIR_%]" name="rows_to_delete[' . $uva_condition . ']"' . ' onclick="' . $column_marker_vertical . 'copyCheckboxesRange(\'rowsDeleteForm\', \'id_rows_to_delete' . $row_no . '\',\'[%_PMA_CHECKBOX_DIR_%]\');"' . ' value="' . $del_query . '" ' . (isset($GLOBALS['checkall']) ? 'checked="checked"' : '') . ' />' . "\n" . ' </td>' . "\n"; } else { unset($vertical_display['row_delete'][$row_no]); } if (isset($edit_url)) { $vertical_display['edit'][$row_no] .= ' <td align="center" class="' . $class . '" ' . $column_style_vertical . '>' . "\n" . PMA_linkOrButton($edit_url, $edit_str, array(), false) . $bookmark_go . ' </td>' . "\n"; } else { unset($vertical_display['edit'][$row_no]); } if (isset($del_url)) { $vertical_display['delete'][$row_no] .= ' <td align="center" class="' . $class . '" ' . $column_style_vertical . '>' . "\n" . PMA_linkOrButton($del_url, $del_str, isset($js_conf) ? $js_conf : '', false) . ' </td>' . "\n"; } else { unset($vertical_display['delete'][$row_no]); } echo $disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped' ? "\n" : ''; $row_no++; } // end while if (isset($url_query)) { $GLOBALS['url_query'] = $url_query; } return true; }
$hcount = 0; $odd_row = true; } $key_ordered_current_key = $keys[$key_ordered_current_row]; $key_ordered_current_val = $values[$key_ordered_current_row]; $val_ordered_current_key = $keys[$val_ordered_current_row]; $val_ordered_current_val = $values[$val_ordered_current_row]; $val_ordered_current_row++; if (PMA_strlen($val_ordered_current_val) <= $cfg['LimitChars']) { $val_ordered_current_val = htmlspecialchars($val_ordered_current_val); $val_ordered_current_val_title = ''; } else { $val_ordered_current_val_title = htmlspecialchars($val_ordered_current_val); $val_ordered_current_val = htmlspecialchars(PMA_substr($val_ordered_current_val, 0, $cfg['LimitChars']) . '...'); } if (PMA_strlen($key_ordered_current_val) <= $cfg['LimitChars']) { $key_ordered_current_val = htmlspecialchars($key_ordered_current_val); $key_ordered_current_val_title = ''; } else { $key_ordered_current_val_title = htmlspecialchars($key_ordered_current_val); $key_ordered_current_val = htmlspecialchars(PMA_substr($key_ordered_current_val, 0, $cfg['LimitChars']) . '...'); } if (!empty($data)) { $val_ordered_current_equals_data = $val_ordered_current_key == $data; $key_ordered_current_equals_data = $key_ordered_current_key == $data; } ?> <tr class="noclick <?php echo $odd_row ? 'odd' : 'even'; $odd_row = !$odd_row; ?>
/** * Parses the SQL queries * * @param string The SQL query list * * @return mixed Most of times, nothing... * * @global array The current PMA configuration * @global array MySQL column attributes * @global array MySQL reserved words * @global array MySQL column types * @global array MySQL function names * @global integer MySQL column attributes count * @global integer MySQL reserved words count * @global integer MySQL column types count * @global integer MySQL function names count * @global array List of available character sets * @global array List of available collations * @global integer Character sets count * @global integer Collations count * * @access public */ function PMA_SQP_parse($sql) { global $cfg; global $PMA_SQPdata_column_attrib, $PMA_SQPdata_reserved_word, $PMA_SQPdata_column_type, $PMA_SQPdata_function_name, $PMA_SQPdata_column_attrib_cnt, $PMA_SQPdata_reserved_word_cnt, $PMA_SQPdata_column_type_cnt, $PMA_SQPdata_function_name_cnt; global $mysql_charsets, $mysql_collations_flat, $mysql_charsets_count, $mysql_collations_count; global $PMA_SQPdata_forbidden_word, $PMA_SQPdata_forbidden_word_cnt; // rabus: Convert all line feeds to Unix style $sql = str_replace("\r\n", "\n", $sql); $sql = str_replace("\r", "\n", $sql); $len = PMA_strlen($sql); if ($len == 0) { return array(); } $sql_array = array(); $sql_array['raw'] = $sql; $count1 = 0; $count2 = 0; $punct_queryend = ';'; $punct_qualifier = '.'; $punct_listsep = ','; $punct_level_plus = '('; $punct_level_minus = ')'; $digit_floatdecimal = '.'; $digit_hexset = 'x'; $bracket_list = '()[]{}'; $allpunct_list = '-,;:!?/.^~\\*&%+<=>|'; $allpunct_list_pair = array(0 => '!=', 1 => '&&', 2 => ':=', 3 => '<<', 4 => '<=', 5 => '<=>', 6 => '<>', 7 => '>=', 8 => '>>', 9 => '||'); $allpunct_list_pair_size = 10; //count($allpunct_list_pair); $quote_list = '\'"`'; $arraysize = 0; while ($count2 < $len) { $c = PMA_substr($sql, $count2, 1); $count1 = $count2; if ($c == "\n") { $count2++; PMA_SQP_arrayAdd($sql_array, 'white_newline', '', $arraysize); continue; } // Checks for white space if (PMA_STR_isSpace($c)) { $count2++; continue; } // Checks for comment lines. // MySQL style # // C style /* */ // ANSI style -- if ($c == '#' || $count2 + 1 < $len && $c == '/' && PMA_substr($sql, $count2 + 1, 1) == '*' || $count2 + 2 == $len && $c == '-' && PMA_substr($sql, $count2 + 1, 1) == '-' || $count2 + 2 < $len && $c == '-' && PMA_substr($sql, $count2 + 1, 1) == '-' && PMA_substr($sql, $count2 + 2, 1) <= ' ') { $count2++; $pos = 0; $type = 'bad'; switch ($c) { case '#': $type = 'mysql'; case '-': $type = 'ansi'; $pos = $GLOBALS['PMA_strpos']($sql, "\n", $count2); break; case '/': $type = 'c'; $pos = $GLOBALS['PMA_strpos']($sql, '*/', $count2); $pos += 2; break; default: break; } // end switch $count2 = $pos < $count2 ? $len : $pos; $str = PMA_substr($sql, $count1, $count2 - $count1); PMA_SQP_arrayAdd($sql_array, 'comment_' . $type, $str, $arraysize); continue; } // end if // Checks for something inside quotation marks if (PMA_STR_strInStr($c, $quote_list)) { $startquotepos = $count2; $quotetype = $c; $count2++; $escaped = FALSE; $escaped_escaped = FALSE; $pos = $count2; $oldpos = 0; do { $oldpos = $pos; $pos = $GLOBALS['PMA_strpos'](' ' . $sql, $quotetype, $oldpos + 1) - 1; // ($pos === FALSE) if ($pos < 0) { $debugstr = $GLOBALS['strSQPBugUnclosedQuote'] . ' @ ' . $startquotepos . "\n" . 'STR: ' . htmlspecialchars($quotetype); PMA_SQP_throwError($debugstr, $sql); return $sql; } // If the quote is the first character, it can't be // escaped, so don't do the rest of the code if ($pos == 0) { break; } // Checks for MySQL escaping using a \ // And checks for ANSI escaping using the $quotetype character if ($pos < $len && PMA_STR_charIsEscaped($sql, $pos)) { $pos++; continue; } else { if ($pos + 1 < $len && PMA_substr($sql, $pos, 1) == $quotetype && PMA_substr($sql, $pos + 1, 1) == $quotetype) { $pos = $pos + 2; continue; } else { break; } } } while ($len > $pos); // end do $count2 = $pos; $count2++; $type = 'quote_'; switch ($quotetype) { case '\'': $type .= 'single'; break; case '"': $type .= 'double'; break; case '`': $type .= 'backtick'; break; default: break; } // end switch $data = PMA_substr($sql, $count1, $count2 - $count1); PMA_SQP_arrayAdd($sql_array, $type, $data, $arraysize); continue; } // Checks for brackets if (PMA_STR_strInStr($c, $bracket_list)) { // All bracket tokens are only one item long $count2++; $type_type = ''; if (PMA_STR_strInStr($c, '([{')) { $type_type = 'open'; } else { $type_type = 'close'; } $type_style = ''; if (PMA_STR_strInStr($c, '()')) { $type_style = 'round'; } elseif (PMA_STR_strInStr($c, '[]')) { $type_style = 'square'; } else { $type_style = 'curly'; } $type = 'punct_bracket_' . $type_type . '_' . $type_style; PMA_SQP_arrayAdd($sql_array, $type, $c, $arraysize); continue; } // Checks for identifier (alpha or numeric) if (PMA_STR_isSqlIdentifier($c, FALSE) || $c == '@' || $c == '.' && PMA_STR_isDigit(PMA_substr($sql, $count2 + 1, 1))) { $count2++; //TODO: a @ can also be present in expressions like // FROM 'user'@'%' // or TO 'user'@'%' // in this case, the @ is wrongly marked as alpha_variable $is_sql_variable = $c == '@'; $is_digit = !$is_sql_variable && PMA_STR_isDigit($c); $is_hex_digit = $is_digit && $c == '.' && $c == '0' && $count2 < $len && PMA_substr($sql, $count2, 1) == 'x'; $is_float_digit = $c == '.'; $is_float_digit_exponent = FALSE; // Nijel: Fast skip is especially needed for huge BLOB data, requires PHP at least 4.3.0: if (PMA_PHP_INT_VERSION >= 40300) { if ($is_hex_digit) { $count2++; $pos = strspn($sql, '0123456789abcdefABCDEF', $count2); if ($pos > $count2) { $count2 = $pos; } unset($pos); } elseif ($is_digit) { $pos = strspn($sql, '0123456789', $count2); if ($pos > $count2) { $count2 = $pos; } unset($pos); } } while ($count2 < $len && PMA_STR_isSqlIdentifier(PMA_substr($sql, $count2, 1), $is_sql_variable || $is_digit)) { $c2 = PMA_substr($sql, $count2, 1); if ($is_sql_variable && $c2 == '.') { $count2++; continue; } if ($is_digit && !$is_hex_digit && $c2 == '.') { $count2++; if (!$is_float_digit) { $is_float_digit = TRUE; continue; } else { $debugstr = $GLOBALS['strSQPBugInvalidIdentifer'] . ' @ ' . ($count1 + 1) . "\n" . 'STR: ' . htmlspecialchars(PMA_substr($sql, $count1, $count2 - $count1)); PMA_SQP_throwError($debugstr, $sql); return $sql; } } if ($is_digit && !$is_hex_digit && ($c2 == 'e' || $c2 == 'E')) { if (!$is_float_digit_exponent) { $is_float_digit_exponent = TRUE; $is_float_digit = TRUE; $count2++; continue; } else { $is_digit = FALSE; $is_float_digit = FALSE; } } if ($is_hex_digit && PMA_STR_isHexDigit($c2) || $is_digit && PMA_STR_isDigit($c2)) { $count2++; continue; } else { $is_digit = FALSE; $is_hex_digit = FALSE; } $count2++; } // end while $l = $count2 - $count1; $str = PMA_substr($sql, $count1, $l); $type = ''; if ($is_digit) { $type = 'digit'; if ($is_float_digit) { $type .= '_float'; } else { if ($is_hex_digit) { $type .= '_hex'; } else { $type .= '_integer'; } } } else { if ($is_sql_variable != FALSE) { $type = 'alpha_variable'; } else { $type = 'alpha'; } } // end if... else.... PMA_SQP_arrayAdd($sql_array, $type, $str, $arraysize); continue; } // Checks for punct if (PMA_STR_strInStr($c, $allpunct_list)) { while ($count2 < $len && PMA_STR_strInStr(PMA_substr($sql, $count2, 1), $allpunct_list)) { $count2++; } $l = $count2 - $count1; if ($l == 1) { $punct_data = $c; } else { $punct_data = PMA_substr($sql, $count1, $l); } // Special case, sometimes, althought two characters are // adjectent directly, they ACTUALLY need to be seperate if ($l == 1) { $t_suffix = ''; switch ($punct_data) { case $punct_queryend: $t_suffix = '_queryend'; break; case $punct_qualifier: $t_suffix = '_qualifier'; break; case $punct_listsep: $t_suffix = '_listsep'; break; default: break; } PMA_SQP_arrayAdd($sql_array, 'punct' . $t_suffix, $punct_data, $arraysize); } else { if (PMA_STR_binarySearchInArr($punct_data, $allpunct_list_pair, $allpunct_list_pair_size)) { // Ok, we have one of the valid combined punct expressions PMA_SQP_arrayAdd($sql_array, 'punct', $punct_data, $arraysize); } else { // Bad luck, lets split it up more $first = $punct_data[0]; $first2 = $punct_data[0] . $punct_data[1]; $last2 = $punct_data[$l - 2] . $punct_data[$l - 1]; $last = $punct_data[$l - 1]; if ($first == ',' || $first == ';' || $first == '.' || $first == '*') { $count2 = $count1 + 1; $punct_data = $first; } else { if ($last2 == '/*' || $last2 == '--' && ($count2 == $len || PMA_substr($sql, $count2, 1) <= ' ')) { $count2 -= 2; $punct_data = PMA_substr($sql, $count1, $count2 - $count1); } else { if ($last == '-' || $last == '+' || $last == '!') { $count2--; $punct_data = PMA_substr($sql, $count1, $count2 - $count1); // TODO: for negation operator, split in 2 tokens ? // "select x&~1 from t" // becomes "select x & ~ 1 from t" ? } else { if ($last != '~') { $debugstr = $GLOBALS['strSQPBugUnknownPunctuation'] . ' @ ' . ($count1 + 1) . "\n" . 'STR: ' . htmlspecialchars($punct_data); PMA_SQP_throwError($debugstr, $sql); return $sql; } } } } PMA_SQP_arrayAdd($sql_array, 'punct', $punct_data, $arraysize); continue; } } // end if... else if... else continue; } // DEBUG $count2++; $debugstr = 'C1 C2 LEN: ' . $count1 . ' ' . $count2 . ' ' . $len . "\n" . 'STR: ' . PMA_substr($sql, $count1, $count2 - $count1) . "\n"; PMA_SQP_bug($debugstr, $sql); return $sql; } // end while ($count2 < $len) if ($arraysize > 0) { $t_next = $sql_array[0]['type']; $t_prev = ''; $t_bef_prev = ''; $t_cur = ''; $d_next = $sql_array[0]['data']; $d_prev = ''; $d_bef_prev = ''; $d_cur = ''; $d_next_upper = $t_next == 'alpha' ? strtoupper($d_next) : $d_next; $d_prev_upper = ''; $d_bef_prev_upper = ''; $d_cur_upper = ''; } for ($i = 0; $i < $arraysize; $i++) { $t_bef_prev = $t_prev; $t_prev = $t_cur; $t_cur = $t_next; $d_bef_prev = $d_prev; $d_prev = $d_cur; $d_cur = $d_next; $d_bef_prev_upper = $d_prev_upper; $d_prev_upper = $d_cur_upper; $d_cur_upper = $d_next_upper; if ($i + 1 < $arraysize) { $t_next = $sql_array[$i + 1]['type']; $d_next = $sql_array[$i + 1]['data']; $d_next_upper = $t_next == 'alpha' ? strtoupper($d_next) : $d_next; } else { $t_next = ''; $d_next = ''; $d_next_upper = ''; } //DEBUG echo "[prev: <b>".$d_prev."</b> ".$t_prev."][cur: <b>".$d_cur."</b> ".$t_cur."][next: <b>".$d_next."</b> ".$t_next."]<br />"; if ($t_cur == 'alpha') { $t_suffix = '_identifier'; if ($t_next == 'punct_qualifier' || $t_prev == 'punct_qualifier') { $t_suffix = '_identifier'; } else { if ($t_next == 'punct_bracket_open_round' && PMA_STR_binarySearchInArr($d_cur_upper, $PMA_SQPdata_function_name, $PMA_SQPdata_function_name_cnt)) { // FIXME-2005-10-16: in the case of a CREATE TABLE containing a TIMESTAMP, // since TIMESTAMP() is also a function, it's found here and // the token is wrongly marked as alpha_functionName. But we // compensate for this when analysing for timestamp_not_null // later in this script. $t_suffix = '_functionName'; } else { if (PMA_STR_binarySearchInArr($d_cur_upper, $PMA_SQPdata_column_type, $PMA_SQPdata_column_type_cnt)) { $t_suffix = '_columnType'; // Temporary fix for BUG #621357 //TODO FIX PROPERLY NEEDS OVERHAUL OF SQL TOKENIZER if ($d_cur_upper == 'SET' && $t_next != 'punct_bracket_open_round') { $t_suffix = '_reservedWord'; } //END OF TEMPORARY FIX // CHARACTER is a synonym for CHAR, but can also be meant as // CHARACTER SET. In this case, we have a reserved word. if ($d_cur_upper == 'CHARACTER' && $d_next_upper == 'SET') { $t_suffix = '_reservedWord'; } // experimental // current is a column type, so previous must not be // a reserved word but an identifier // CREATE TABLE SG_Persons (first varchar(64)) //if ($sql_array[$i-1]['type'] =='alpha_reservedWord') { // $sql_array[$i-1]['type'] = 'alpha_identifier'; //} } else { if (PMA_STR_binarySearchInArr($d_cur_upper, $PMA_SQPdata_reserved_word, $PMA_SQPdata_reserved_word_cnt)) { $t_suffix = '_reservedWord'; } else { if (PMA_STR_binarySearchInArr($d_cur_upper, $PMA_SQPdata_column_attrib, $PMA_SQPdata_column_attrib_cnt)) { $t_suffix = '_columnAttrib'; // INNODB is a MySQL table type, but in "SHOW INNODB STATUS", // it should be regarded as a reserved word. if ($d_cur_upper == 'INNODB' && $d_prev_upper == 'SHOW' && $d_next_upper == 'STATUS') { $t_suffix = '_reservedWord'; } if ($d_cur_upper == 'DEFAULT' && $d_next_upper == 'CHARACTER') { $t_suffix = '_reservedWord'; } // Binary as character set if ($d_cur_upper == 'BINARY' && ($d_bef_prev_upper == 'CHARACTER' && $d_prev_upper == 'SET' || $d_bef_prev_upper == 'SET' && $d_prev_upper == '=' || $d_bef_prev_upper == 'CHARSET' && $d_prev_upper == '=' || $d_prev_upper == 'CHARSET') && PMA_STR_binarySearchInArr($d_cur, $mysql_charsets, count($mysql_charsets))) { $t_suffix = '_charset'; } } elseif (PMA_STR_binarySearchInArr($d_cur, $mysql_charsets, $mysql_charsets_count) || PMA_STR_binarySearchInArr($d_cur, $mysql_collations_flat, $mysql_collations_count) || $d_cur[0] == '_' && PMA_STR_binarySearchInArr(substr($d_cur, 1), $mysql_charsets, $mysql_charsets_count)) { $t_suffix = '_charset'; } else { // Do nothing } } } } } // check if present in the list of forbidden words if ($t_suffix == '_reservedWord' && PMA_STR_binarySearchInArr($d_cur_upper, $PMA_SQPdata_forbidden_word, $PMA_SQPdata_forbidden_word_cnt)) { $sql_array[$i]['forbidden'] = TRUE; } else { $sql_array[$i]['forbidden'] = FALSE; } $sql_array[$i]['type'] .= $t_suffix; } } // end for // Stores the size of the array inside the array, as count() is a slow // operation. $sql_array['len'] = $arraysize; // Sends the data back return $sql_array; }
echo $strBinLogServerId; ?> </th> <th> <?php echo $strBinLogOriginalPosition; ?> </th> <th> <?php echo $strBinLogInfo; ?> </th> </tr> <?php $useBgcolorOne = TRUE; foreach ($serverProcesses as $value) { if (empty($full) && PMA_strlen($value['Info']) > $GLOBALS['cfg']['LimitChars']) { $value['Info'] = PMA_substr($value['Info'], 0, $GLOBALS['cfg']['LimitChars']) . '...'; } ?> <tr> <td bgcolor="<?php echo $useBgcolorOne ? $cfg['BgcolorOne'] : $cfg['BgcolorTwo']; ?> "> <?php echo $value['Log_name']; ?> </td> <td bgcolor="<?php echo $useBgcolorOne ? $cfg['BgcolorOne'] : $cfg['BgcolorTwo']; ?> " align="right"> <?php
</th> <th><?php echo __('Original position'); ?> </th> <th><?php echo __('Information'); ?> </th> </tr> </thead> <tbody> <?php $odd_row = true; while ($value = PMA_DBI_fetch_assoc($result)) { if (!$dontlimitchars && PMA_strlen($value['Info']) > $GLOBALS['cfg']['LimitChars']) { $value['Info'] = PMA_substr($value['Info'], 0, $GLOBALS['cfg']['LimitChars']) . '...'; } ?> <tr class="noclick <?php echo $odd_row ? 'odd' : 'even'; ?> "> <td> <?php echo $value['Log_name']; ?> </td> <td align="right"> <?php echo $value['Pos']; ?> </td>
/** * Checks if a given character position in the string is escaped or not * * @param string string to check for * @param integer the character to check for * @param integer starting position in the string * * @return boolean whether the character is escaped or not */ function PMA_STR_charIsEscaped($string, $pos, $start = 0) { $len = PMA_strlen($string); // Base case: // Check for string length or invalid input or special case of input // (pos == $start) if ($pos == $start || $len <= $pos) { return FALSE; } $p = $pos - 1; $escaped = FALSE; while ($p >= $start && $string[$p] == '\\') { $escaped = !$escaped; $p--; } // end while if ($pos < $start) { // throw error about strings } return $escaped; }
/** * Prepares the dropdown for one mode * * @param array $foreign the keys and values for foreigns * @param string $data the current data of the dropdown * @param string $mode the needed mode * * @return array the <option value=""><option>s * * @access protected */ function PMA__foreignDropdownBuild($foreign, $data, $mode) { $reloptions = array(); // id-only is a special mode used when no foreign display column // is available if ($mode == 'id-content' || $mode == 'id-only') { // sort for id-content if ($GLOBALS['cfg']['NaturalOrder']) { uksort($foreign, 'strnatcasecmp'); } else { ksort($foreign); } } elseif ($mode == 'content-id') { // sort for content-id if ($GLOBALS['cfg']['NaturalOrder']) { natcasesort($foreign); } else { asort($foreign); } } foreach ($foreign as $key => $value) { if (PMA_strlen($value) <= $GLOBALS['cfg']['LimitChars']) { $vtitle = ''; $value = htmlspecialchars($value); } else { $vtitle = htmlspecialchars($value); $value = htmlspecialchars(substr($value, 0, $GLOBALS['cfg']['LimitChars']) . '...'); } $reloption = '<option value="' . htmlspecialchars($key) . '"'; if ($vtitle != '') { $reloption .= ' title="' . $vtitle . '"'; } if ((string) $key == (string) $data) { $reloption .= ' selected="selected"'; } if ($mode == 'content-id') { $reloptions[] = $reloption . '>' . $value . ' - ' . htmlspecialchars($key) . '</option>'; } elseif ($mode == 'id-content') { $reloptions[] = $reloption . '>' . htmlspecialchars($key) . ' - ' . $value . '</option>'; } elseif ($mode == 'id-only') { $reloptions[] = $reloption . '>' . htmlspecialchars($key) . '</option>'; } } // end foreach return $reloptions; }
/** * Prepares the dropdown for one mode * * @param array the keys and values for foreigns * @param string the current data of the dropdown * @param string the needed mode * * @global array global phpMyAdmin configuration * * @return array the <option value=""><option>s * * @access private */ function PMA_foreignDropdownBuild($foreign, $data, $mode) { global $cfg; $reloptions = array(); foreach ($foreign as $key => $value) { if (PMA_strlen($value) <= $cfg['LimitChars']) { $vtitle = ''; $value = htmlspecialchars($value); } else { $vtitle = htmlspecialchars($value); $value = htmlspecialchars(substr($value, 0, $cfg['LimitChars']) . '...'); } $reloption = ' <option value="' . htmlspecialchars($key) . '"'; if ($vtitle != '') { $reloption .= ' title="' . $vtitle . '"'; } if ((string) $key == (string) $data) { $reloption .= ' selected="selected"'; } if ($mode == 'content-id') { $reloptions[] = $reloption . '>' . $value . ' - ' . htmlspecialchars($key) . '</option>' . "\n"; } else { $reloptions[] = $reloption . '>' . htmlspecialchars($key) . ' - ' . $value . '</option>' . "\n"; } } // end foreach return $reloptions; }
/** * Displays the body of the results table * * @uses $_SESSION['tmp_user_values']['disp_direction'] * @uses $_SESSION['tmp_user_values']['repeat_cells'] * @uses $_SESSION['tmp_user_values']['max_rows'] * @uses $_SESSION['tmp_user_values']['display_text'] * @uses $_SESSION['tmp_user_values']['display_binary'] * @uses $_SESSION['tmp_user_values']['display_binary_as_hex'] * @uses $_SESSION['tmp_user_values']['display_blob'] * @param integer the link id associated to the query which results have * to be displayed * @param array which elements to display * @param array the list of relations * @param array the analyzed query * * @return boolean always true * * @global string $db the database name * @global string $table the table name * @global string $goto the URL to go back in case of errors * @global string $sql_query the SQL query * @global array $fields_meta the list of fields properties * @global integer $fields_cnt the total number of fields returned by * the SQL query * @global array $vertical_display informations used with vertical display * mode * @global array $highlight_columns column names to highlight * @global array $row current row data * * @access private * * @see PMA_displayTable() */ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { global $db, $table, $goto; global $sql_query, $fields_meta, $fields_cnt; global $vertical_display, $highlight_columns; global $row; // mostly because of browser transformations, to make the row-data accessible in a plugin $url_sql_query = $sql_query; // query without conditions to shorten URLs when needed, 200 is just // guess, it should depend on remaining URL length if (isset($analyzed_sql) && isset($analyzed_sql[0]) && isset($analyzed_sql[0]['querytype']) && $analyzed_sql[0]['querytype'] == 'SELECT' && strlen($sql_query) > 200) { $url_sql_query = 'SELECT '; if (isset($analyzed_sql[0]['queryflags']['distinct'])) { $url_sql_query .= ' DISTINCT '; } $url_sql_query .= $analyzed_sql[0]['select_expr_clause']; if (!empty($analyzed_sql[0]['from_clause'])) { $url_sql_query .= ' FROM ' . $analyzed_sql[0]['from_clause']; } } if (!is_array($map)) { $map = array(); } $row_no = 0; $vertical_display['edit'] = array(); $vertical_display['copy'] = array(); $vertical_display['delete'] = array(); $vertical_display['data'] = array(); $vertical_display['row_delete'] = array(); // name of the class added to all inline editable elements $inline_edit_class = 'inline_edit'; // Correction University of Virginia 19991216 in the while below // Previous code assumed that all tables have keys, specifically that // the phpMyAdmin GUI should support row delete/edit only for such // tables. // Although always using keys is arguably the prescribed way of // defining a relational table, it is not required. This will in // particular be violated by the novice. // We want to encourage phpMyAdmin usage by such novices. So the code // below has been changed to conditionally work as before when the // table being displayed has one or more keys; but to display // delete/edit options correctly for tables without keys. $odd_row = true; while ($row = PMA_DBI_fetch_row($dt_result)) { // "vertical display" mode stuff if ($row_no != 0 && $_SESSION['tmp_user_values']['repeat_cells'] != 0 && !($row_no % $_SESSION['tmp_user_values']['repeat_cells']) && ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped')) { echo '<tr>' . "\n"; if ($vertical_display['emptypre'] > 0) { echo ' <th colspan="' . $vertical_display['emptypre'] . '">' . "\n" . ' </th>' . "\n"; } foreach ($vertical_display['desc'] as $val) { echo $val; } if ($vertical_display['emptyafter'] > 0) { echo ' <th colspan="' . $vertical_display['emptyafter'] . '">' . "\n" . ' </th>' . "\n"; } echo '</tr>' . "\n"; } // end if $alternating_color_class = $odd_row ? 'odd' : 'even'; $odd_row = !$odd_row; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { // pointer code part echo '<tr class="' . $alternating_color_class . '">'; } // 1. Prepares the row // 1.1 Results from a "SELECT" statement -> builds the // WHERE clause to use in links (a unique key if possible) /** * @todo $where_clause could be empty, for example a table * with only one field and it's a BLOB; in this case, * avoid to display the delete and edit links */ list($where_clause, $clause_is_unique) = PMA_getUniqueCondition($dt_result, $fields_cnt, $fields_meta, $row); $where_clause_html = urlencode($where_clause); // 1.2 Defines the URLs for the modify/delete link(s) if ($is_display['edit_lnk'] != 'nn' || $is_display['del_lnk'] != 'nn') { // We need to copy the value or else the == 'both' check will always return true if ($GLOBALS['cfg']['PropertiesIconic'] === 'both') { $iconic_spacer = '<div class="nowrap">'; } else { $iconic_spacer = ''; } // 1.2.1 Modify link(s) if ($is_display['edit_lnk'] == 'ur') { // update row case $_url_params = array('db' => $db, 'table' => $table, 'where_clause' => $where_clause, 'clause_is_unique' => $clause_is_unique, 'sql_query' => $url_sql_query, 'goto' => 'sql.php'); $edit_url = 'tbl_change.php' . PMA_generate_common_url($_url_params + array('default_action' => 'update')); $copy_url = 'tbl_change.php' . PMA_generate_common_url($_url_params + array('default_action' => 'insert')); $edit_str = PMA_getIcon('b_edit.png', __('Edit'), true); $copy_str = PMA_getIcon('b_insrow.png', __('Copy'), true); // Class definitions required for inline editing jQuery scripts $edit_anchor_class = "edit_row_anchor"; if ($clause_is_unique == 0) { $edit_anchor_class .= ' nonunique'; } } // end if (1.2.1) // 1.2.2 Delete/Kill link(s) if ($is_display['del_lnk'] == 'dr') { // delete row case $_url_params = array('db' => $db, 'table' => $table, 'sql_query' => $url_sql_query, 'message_to_show' => __('The row has been deleted'), 'goto' => empty($goto) ? 'tbl_sql.php' : $goto); $lnk_goto = 'sql.php' . PMA_generate_common_url($_url_params, 'text'); $del_query = 'DELETE FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table) . ' WHERE ' . $where_clause . ($clause_is_unique ? '' : ' LIMIT 1'); $_url_params = array('db' => $db, 'table' => $table, 'sql_query' => $del_query, 'message_to_show' => __('The row has been deleted'), 'goto' => $lnk_goto); $del_url = 'sql.php' . PMA_generate_common_url($_url_params); $js_conf = 'DELETE FROM ' . PMA_jsFormat($db) . '.' . PMA_jsFormat($table) . ' WHERE ' . PMA_jsFormat($where_clause, false) . ($clause_is_unique ? '' : ' LIMIT 1'); $del_str = PMA_getIcon('b_drop.png', __('Delete'), true); } elseif ($is_display['del_lnk'] == 'kp') { // kill process case $_url_params = array('db' => $db, 'table' => $table, 'sql_query' => $url_sql_query, 'goto' => 'main.php'); $lnk_goto = 'sql.php' . PMA_generate_common_url($_url_params, 'text'); $_url_params = array('db' => 'mysql', 'sql_query' => 'KILL ' . $row[0], 'goto' => $lnk_goto); $del_url = 'sql.php' . PMA_generate_common_url($_url_params); $del_query = 'KILL ' . $row[0]; $js_conf = 'KILL ' . $row[0]; $del_str = PMA_getIcon('b_drop.png', __('Kill'), true); } // end if (1.2.2) // 1.3 Displays the links at left if required if ($GLOBALS['cfg']['ModifyDeleteAtLeft'] && ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped')) { if (!isset($js_conf)) { $js_conf = ''; } echo PMA_generateCheckboxAndLinks('left', $del_url, $is_display, $row_no, $where_clause, $where_clause_html, $del_query, 'l', $edit_url, $copy_url, $edit_anchor_class, $edit_str, $copy_str, $del_str, $js_conf); } // end if (1.3) } // end if (1) // 2. Displays the rows' values for ($i = 0; $i < $fields_cnt; ++$i) { $meta = $fields_meta[$i]; $not_null_class = $meta->not_null ? 'not_null' : ''; $relation_class = isset($map[$meta->name]) ? 'relation' : ''; $pointer = $i; $is_field_truncated = false; //If the previous column had blob data, we need to reset the class // to $inline_edit_class $class = 'data ' . $inline_edit_class . ' ' . $not_null_class . ' ' . $alternating_color_class . ' ' . $relation_class; // See if this column should get highlight because it's used in the // where-query. if (isset($highlight_columns) && (isset($highlight_columns[$meta->name]) || isset($highlight_columns[PMA_backquote($meta->name)]))) { $condition_field = true; } else { $condition_field = false; } if ($_SESSION['tmp_user_values']['disp_direction'] == 'vertical' && (!isset($GLOBALS['printview']) || $GLOBALS['printview'] != '1')) { // the row number corresponds to a data row, not HTML table row $class .= ' row_' . $row_no; if ($GLOBALS['cfg']['BrowsePointerEnable'] == true) { $class .= ' vpointer'; } if ($GLOBALS['cfg']['BrowseMarkerEnable'] == true) { $class .= ' vmarker'; } } // end if // Wrap MIME-transformations. [MIME] $default_function = 'default_function'; // default_function $transform_function = $default_function; $transform_options = array(); if ($GLOBALS['cfgRelation']['mimework'] && $GLOBALS['cfg']['BrowseMIME']) { if (isset($GLOBALS['mime_map'][$meta->name]['mimetype']) && isset($GLOBALS['mime_map'][$meta->name]['transformation']) && !empty($GLOBALS['mime_map'][$meta->name]['transformation'])) { $include_file = PMA_securePath($GLOBALS['mime_map'][$meta->name]['transformation']); if (file_exists('./libraries/transformations/' . $include_file)) { $transformfunction_name = str_replace('.inc.php', '', $GLOBALS['mime_map'][$meta->name]['transformation']); require_once './libraries/transformations/' . $include_file; if (function_exists('PMA_transformation_' . $transformfunction_name)) { $transform_function = 'PMA_transformation_' . $transformfunction_name; $transform_options = PMA_transformation_getOptions(isset($GLOBALS['mime_map'][$meta->name]['transformation_options']) ? $GLOBALS['mime_map'][$meta->name]['transformation_options'] : ''); $meta->mimetype = str_replace('_', '/', $GLOBALS['mime_map'][$meta->name]['mimetype']); } } // end if file_exists } // end if transformation is set } // end if mime/transformation works. $_url_params = array('db' => $db, 'table' => $table, 'where_clause' => $where_clause, 'transform_key' => $meta->name); if (!empty($sql_query)) { $_url_params['sql_query'] = $url_sql_query; } $transform_options['wrapper_link'] = PMA_generate_common_url($_url_params); // n u m e r i c if ($meta->numeric == 1) { // if two fields have the same name (this is possible // with self-join queries, for example), using $meta->name // will show both fields NULL even if only one is NULL, // so use the $pointer if (!isset($row[$i]) || is_null($row[$i])) { $vertical_display['data'][$row_no][$i] = PMA_buildNullDisplay($class, $condition_field, $meta, 'align="right"'); } elseif ($row[$i] != '') { $nowrap = ' nowrap'; $where_comparison = ' = ' . $row[$i]; $vertical_display['data'][$row_no][$i] = '<td align="right"' . PMA_prepare_row_data($class, $condition_field, $analyzed_sql, $meta, $map, $row[$i], $transform_function, $default_function, $nowrap, $where_comparison, $transform_options, $is_field_truncated); } else { $vertical_display['data'][$row_no][$i] = PMA_buildEmptyDisplay($class, $condition_field, $meta, 'align="right"'); } // b l o b } elseif (stristr($meta->type, 'BLOB')) { // PMA_mysql_fetch_fields returns BLOB in place of // TEXT fields type so we have to ensure it's really a BLOB $field_flags = PMA_DBI_field_flags($dt_result, $i); // remove 'inline_edit' from $class as we can't edit binary data. $class = str_replace('inline_edit', '', $class); if (stristr($field_flags, 'BINARY')) { if (!isset($row[$i]) || is_null($row[$i])) { $vertical_display['data'][$row_no][$i] = PMA_buildNullDisplay($class, $condition_field, $meta); } else { // for blobstreaming // if valid BS reference exists if (PMA_BS_IsPBMSReference($row[$i], $db)) { $blobtext = PMA_BS_CreateReferenceLink($row[$i], $db); } else { $blobtext = PMA_handle_non_printable_contents('BLOB', isset($row[$i]) ? $row[$i] : '', $transform_function, $transform_options, $default_function, $meta, $_url_params); } $vertical_display['data'][$row_no][$i] = PMA_buildValueDisplay($class, $condition_field, $blobtext); unset($blobtext); } // not binary: } else { if (!isset($row[$i]) || is_null($row[$i])) { $vertical_display['data'][$row_no][$i] = PMA_buildNullDisplay($class, $condition_field, $meta); } elseif ($row[$i] != '') { // if a transform function for blob is set, none of these replacements will be made if (PMA_strlen($row[$i]) > $GLOBALS['cfg']['LimitChars'] && $_SESSION['tmp_user_values']['display_text'] == 'P') { $row[$i] = PMA_substr($row[$i], 0, $GLOBALS['cfg']['LimitChars']) . '...'; $is_field_truncated = true; } // displays all space characters, 4 space // characters for tabulations and <cr>/<lf> $row[$i] = $default_function != $transform_function ? $transform_function($row[$i], $transform_options, $meta) : $default_function($row[$i], array(), $meta); $vertical_display['data'][$row_no][$i] = PMA_buildValueDisplay($class, $condition_field, $row[$i]); } else { $vertical_display['data'][$row_no][$i] = PMA_buildEmptyDisplay($class, $condition_field, $meta); } } // g e o m e t r y } elseif ($meta->type == 'geometry') { $geometry_text = PMA_handle_non_printable_contents('GEOMETRY', isset($row[$i]) ? $row[$i] : '', $transform_function, $transform_options, $default_function, $meta); // remove 'inline_edit' from $class as we can't edit geometry data. $class = str_replace('inline_edit', '', $class); $vertical_display['data'][$row_no][$i] = PMA_buildValueDisplay($class, $condition_field, $geometry_text); unset($geometry_text); // n o t n u m e r i c a n d n o t B L O B } else { if (!isset($row[$i]) || is_null($row[$i])) { $vertical_display['data'][$row_no][$i] = PMA_buildNullDisplay($class, $condition_field, $meta); } elseif ($row[$i] != '') { // support blanks in the key $relation_id = $row[$i]; // Cut all fields to $GLOBALS['cfg']['LimitChars'] // (unless it's a link-type transformation) if (PMA_strlen($row[$i]) > $GLOBALS['cfg']['LimitChars'] && $_SESSION['tmp_user_values']['display_text'] == 'P' && !strpos($transform_function, 'link') === true) { $row[$i] = PMA_substr($row[$i], 0, $GLOBALS['cfg']['LimitChars']) . '...'; $is_field_truncated = true; } // displays special characters from binaries $field_flags = PMA_DBI_field_flags($dt_result, $i); $is_html = false; if (isset($meta->_type) && $meta->_type === MYSQLI_TYPE_BIT) { $row[$i] = PMA_printable_bit_value($row[$i], $meta->length); // some results of PROCEDURE ANALYSE() are reported as // being BINARY but they are quite readable, // so don't treat them as BINARY } elseif (stristr($field_flags, 'BINARY') && $meta->type == 'string' && !(isset($GLOBALS['is_analyse']) && $GLOBALS['is_analyse'])) { if ($_SESSION['tmp_user_values']['display_binary']) { // user asked to see the real contents of BINARY // fields if ($_SESSION['tmp_user_values']['display_binary_as_hex'] && PMA_contains_nonprintable_ascii($row[$i])) { $row[$i] = bin2hex($row[$i]); } else { $row[$i] = htmlspecialchars(PMA_replace_binary_contents($row[$i])); } } else { // we show the BINARY message and field's size // (or maybe use a transformation) $row[$i] = PMA_handle_non_printable_contents('BINARY', $row[$i], $transform_function, $transform_options, $default_function, $meta, $_url_params); $is_html = true; } } if ($is_html) { $vertical_display['data'][$row_no][$i] = PMA_buildValueDisplay($class, $condition_field, $row[$i]); } else { // transform functions may enable no-wrapping: $function_nowrap = $transform_function . '_nowrap'; $bool_nowrap = $default_function != $transform_function && function_exists($function_nowrap) ? $function_nowrap($transform_options) : false; // do not wrap if date field type $nowrap = preg_match('@DATE|TIME@i', $meta->type) || $bool_nowrap ? ' nowrap' : ''; $where_comparison = ' = \'' . PMA_sqlAddslashes($row[$i]) . '\''; $vertical_display['data'][$row_no][$i] = '<td ' . PMA_prepare_row_data($class, $condition_field, $analyzed_sql, $meta, $map, $row[$i], $transform_function, $default_function, $nowrap, $where_comparison, $transform_options, $is_field_truncated); } } else { $vertical_display['data'][$row_no][$i] = PMA_buildEmptyDisplay($class, $condition_field, $meta); } } // output stored cell if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo $vertical_display['data'][$row_no][$i]; } if (isset($vertical_display['rowdata'][$i][$row_no])) { $vertical_display['rowdata'][$i][$row_no] .= $vertical_display['data'][$row_no][$i]; } else { $vertical_display['rowdata'][$i][$row_no] = $vertical_display['data'][$row_no][$i]; } } // end for (2) // 3. Displays the modify/delete links on the right if required if ($GLOBALS['cfg']['ModifyDeleteAtRight'] && ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped')) { if (!isset($js_conf)) { $js_conf = ''; } echo PMA_generateCheckboxAndLinks('right', $del_url, $is_display, $row_no, $where_clause, $where_clause_html, $del_query, 'r', $edit_url, $copy_url, $edit_anchor_class, $edit_str, $copy_str, $del_str, $js_conf); } // end if (3) if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { ?> </tr> <?php } // end if // 4. Gather links of del_urls and edit_urls in an array for later // output if (!isset($vertical_display['edit'][$row_no])) { $vertical_display['edit'][$row_no] = ''; $vertical_display['copy'][$row_no] = ''; $vertical_display['delete'][$row_no] = ''; $vertical_display['row_delete'][$row_no] = ''; } $vertical_class = ' row_' . $row_no; if ($GLOBALS['cfg']['BrowsePointerEnable'] == true) { $vertical_class .= ' vpointer'; } if ($GLOBALS['cfg']['BrowseMarkerEnable'] == true) { $vertical_class .= ' vmarker'; } if (!empty($del_url) && $is_display['del_lnk'] != 'kp') { $vertical_display['row_delete'][$row_no] .= PMA_generateCheckboxForMulti($del_url, $is_display, $row_no, $where_clause_html, $del_query, '[%_PMA_CHECKBOX_DIR_%]', $alternating_color_class . $vertical_class); } else { unset($vertical_display['row_delete'][$row_no]); } if (isset($edit_url)) { $vertical_display['edit'][$row_no] .= PMA_generateEditLink($edit_url, $alternating_color_class . ' ' . $edit_anchor_class . $vertical_class, $edit_str, $where_clause, $where_clause_html); } else { unset($vertical_display['edit'][$row_no]); } if (isset($copy_url)) { $vertical_display['copy'][$row_no] .= PMA_generateCopyLink($copy_url, $copy_str, $where_clause, $where_clause_html, $alternating_color_class . $vertical_class); } else { unset($vertical_display['copy'][$row_no]); } if (isset($del_url)) { if (!isset($js_conf)) { $js_conf = ''; } $vertical_display['delete'][$row_no] .= PMA_generateDeleteLink($del_url, $del_str, $js_conf, $alternating_color_class . $vertical_class); } else { unset($vertical_display['delete'][$row_no]); } echo $_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped' ? "\n" : ''; $row_no++; } // end while // this is needed by PMA_displayTable() to generate the proper param // in the multi-edit and multi-delete form return $clause_is_unique; }
/** * Parses the SQL queries * * @param string $sql The SQL query list * * @return mixed Most of times, nothing... * * @global array The current PMA configuration * @global array MySQL column attributes * @global array MySQL reserved words * @global array MySQL column types * @global array MySQL function names * @global array List of available character sets * @global array List of available collations * * @access public */ function PMA_SQP_parse($sql) { static $PMA_SQPdata_column_attrib, $PMA_SQPdata_reserved_word; static $PMA_SQPdata_column_type; static $PMA_SQPdata_function_name, $PMA_SQPdata_forbidden_word; global $mysql_charsets, $mysql_collations_flat; // Convert all line feeds to Unix style $sql = str_replace("\r\n", "\n", $sql); $sql = str_replace("\r", "\n", $sql); $len = PMA_strlen($sql); if ($len == 0) { return array(); } // Create local hashtables if (!isset($PMA_SQPdata_column_attrib)) { $PMA_SQPdata_column_attrib = array_flip($GLOBALS['PMA_SQPdata_column_attrib']); $PMA_SQPdata_function_name = array_flip($GLOBALS['PMA_SQPdata_function_name']); $PMA_SQPdata_reserved_word = array_flip($GLOBALS['PMA_SQPdata_reserved_word']); $PMA_SQPdata_forbidden_word = array_flip($GLOBALS['PMA_SQPdata_forbidden_word']); $PMA_SQPdata_column_type = array_flip($GLOBALS['PMA_SQPdata_column_type']); } $sql_array = array(); $sql_array['raw'] = $sql; $count1 = 0; $count2 = 0; $punct_queryend = ';'; $punct_qualifier = '.'; $punct_listsep = ','; $punct_level_plus = '('; $punct_level_minus = ')'; $punct_user = '******'; $digit_floatdecimal = '.'; $digit_hexset = 'x'; $bracket_list = '()[]{}'; $allpunct_list = '-,;:!?/.^~\\*&%+<=>|'; $allpunct_list_pair = array('!=' => 1, '&&' => 1, ':=' => 1, '<<' => 1, '<=' => 1, '<=>' => 1, '<>' => 1, '>=' => 1, '>>' => 1, '||' => 1, '==' => 1); $quote_list = '\'"`'; $arraysize = 0; $previous_was_space = false; $this_was_space = false; $previous_was_bracket = false; $this_was_bracket = false; $previous_was_punct = false; $this_was_punct = false; $previous_was_listsep = false; $this_was_listsep = false; $previous_was_quote = false; $this_was_quote = false; while ($count2 < $len) { $c = PMA_substr($sql, $count2, 1); $count1 = $count2; $previous_was_space = $this_was_space; $this_was_space = false; $previous_was_bracket = $this_was_bracket; $this_was_bracket = false; $previous_was_punct = $this_was_punct; $this_was_punct = false; $previous_was_listsep = $this_was_listsep; $this_was_listsep = false; $previous_was_quote = $this_was_quote; $this_was_quote = false; if ($c == "\n") { $this_was_space = true; $count2++; PMA_SQP_arrayAdd($sql_array, 'white_newline', '', $arraysize); continue; } // Checks for white space if (PMA_STR_isSpace($c)) { $this_was_space = true; $count2++; continue; } // Checks for comment lines. // MySQL style # // C style /* */ // ANSI style -- $next_c = PMA_substr($sql, $count2 + 1, 1); if ($c == '#' || $count2 + 1 < $len && $c == '/' && $next_c == '*' || $count2 + 2 == $len && $c == '-' && $next_c == '-' || $count2 + 2 < $len && $c == '-' && $next_c == '-' && PMA_substr($sql, $count2 + 2, 1) <= ' ') { $count2++; $pos = 0; $type = 'bad'; switch ($c) { case '#': $type = 'mysql'; case '-': $type = 'ansi'; $pos = PMA_strpos($sql, "\n", $count2); break; case '/': $type = 'c'; $pos = PMA_strpos($sql, '*/', $count2); $pos += 2; break; default: break; } // end switch $count2 = $pos < $count2 ? $len : $pos; $str = PMA_substr($sql, $count1, $count2 - $count1); PMA_SQP_arrayAdd($sql_array, 'comment_' . $type, $str, $arraysize); continue; } // end if // Checks for something inside quotation marks if (PMA_strpos($quote_list, $c) !== false) { $startquotepos = $count2; $quotetype = $c; $count2++; $escaped = false; $pos = $count2; $oldpos = 0; do { $oldpos = $pos; $pos = PMA_strpos(' ' . $sql, $quotetype, $oldpos + 1) - 1; // ($pos === false) if ($pos < 0) { if ($c == '`') { /* * Behave same as MySQL and accept end of query as end of backtick. * I know this is sick, but MySQL behaves like this: * * SELECT * FROM `table * * is treated like * * SELECT * FROM `table` */ $pos_quote_separator = PMA_strpos(' ' . $sql, $GLOBALS['sql_delimiter'], $oldpos + 1) - 1; if ($pos_quote_separator < 0) { $len += 1; $sql .= '`'; $sql_array['raw'] .= '`'; $pos = $len; } else { $len += 1; $sql = PMA_substr($sql, 0, $pos_quote_separator) . '`' . PMA_substr($sql, $pos_quote_separator); $sql_array['raw'] = $sql; $pos = $pos_quote_separator; } if (class_exists('PMA_Message') && $GLOBALS['is_ajax_request'] != true) { PMA_Message::notice(__('Automatically appended backtick to the end of query!'))->display(); } } else { $debugstr = __('Unclosed quote') . ' @ ' . $startquotepos . "\n" . 'STR: ' . htmlspecialchars($quotetype); PMA_SQP_throwError($debugstr, $sql); return $sql_array; } } // If the quote is the first character, it can't be // escaped, so don't do the rest of the code if ($pos == 0) { break; } // Checks for MySQL escaping using a \ // And checks for ANSI escaping using the $quotetype character if ($pos < $len && PMA_STR_charIsEscaped($sql, $pos) && $c != '`') { $pos++; continue; } elseif ($pos + 1 < $len && PMA_substr($sql, $pos, 1) == $quotetype && PMA_substr($sql, $pos + 1, 1) == $quotetype) { $pos = $pos + 2; continue; } else { break; } } while ($len > $pos); // end do $count2 = $pos; $count2++; $type = 'quote_'; switch ($quotetype) { case '\'': $type .= 'single'; $this_was_quote = true; break; case '"': $type .= 'double'; $this_was_quote = true; break; case '`': $type .= 'backtick'; $this_was_quote = true; break; default: break; } // end switch $data = PMA_substr($sql, $count1, $count2 - $count1); PMA_SQP_arrayAdd($sql_array, $type, $data, $arraysize); continue; } // Checks for brackets if (PMA_strpos($bracket_list, $c) !== false) { // All bracket tokens are only one item long $this_was_bracket = true; $count2++; $type_type = ''; if (PMA_strpos('([{', $c) !== false) { $type_type = 'open'; } else { $type_type = 'close'; } $type_style = ''; if (PMA_strpos('()', $c) !== false) { $type_style = 'round'; } elseif (PMA_strpos('[]', $c) !== false) { $type_style = 'square'; } else { $type_style = 'curly'; } $type = 'punct_bracket_' . $type_type . '_' . $type_style; PMA_SQP_arrayAdd($sql_array, $type, $c, $arraysize); continue; } /* DEBUG echo '<pre>1'; var_dump(PMA_STR_isSqlIdentifier($c, false)); var_dump($c == '@'); var_dump($c == '.'); var_dump(PMA_STR_isDigit(PMA_substr($sql, $count2 + 1, 1))); var_dump($previous_was_space); var_dump($previous_was_bracket); var_dump($previous_was_listsep); echo '</pre>'; */ // Checks for identifier (alpha or numeric) if (PMA_STR_isSqlIdentifier($c, false) || $c == '@' || $c == '.' && PMA_STR_isDigit(PMA_substr($sql, $count2 + 1, 1)) && ($previous_was_space || $previous_was_bracket || $previous_was_listsep)) { /* DEBUG echo PMA_substr($sql, $count2); echo '<hr />'; */ $count2++; /** * @todo a @ can also be present in expressions like * FROM 'user'@'%' or TO 'user'@'%' * in this case, the @ is wrongly marked as alpha_variable */ $is_identifier = $previous_was_punct; $is_sql_variable = $c == '@' && !$previous_was_quote; $is_user = $c == '@' && $previous_was_quote; $is_digit = !$is_identifier && !$is_sql_variable && PMA_STR_isDigit($c); $is_hex_digit = $is_digit && $c == '0' && $count2 < $len && PMA_substr($sql, $count2, 1) == 'x'; $is_float_digit = $c == '.'; $is_float_digit_exponent = false; /* DEBUG echo '<pre>2'; var_dump($is_identifier); var_dump($is_sql_variable); var_dump($is_digit); var_dump($is_float_digit); echo '</pre>'; */ // Fast skip is especially needed for huge BLOB data if ($is_hex_digit) { $count2++; $pos = strspn($sql, '0123456789abcdefABCDEF', $count2); if ($pos > $count2) { $count2 = $pos; } unset($pos); } elseif ($is_digit) { $pos = strspn($sql, '0123456789', $count2); if ($pos > $count2) { $count2 = $pos; } unset($pos); } while ($count2 < $len && PMA_STR_isSqlIdentifier(PMA_substr($sql, $count2, 1), $is_sql_variable || $is_digit)) { $c2 = PMA_substr($sql, $count2, 1); if ($is_sql_variable && $c2 == '.') { $count2++; continue; } if ($is_digit && !$is_hex_digit && $c2 == '.') { $count2++; if (!$is_float_digit) { $is_float_digit = true; continue; } else { $debugstr = __('Invalid Identifer') . ' @ ' . ($count1 + 1) . "\n" . 'STR: ' . htmlspecialchars(PMA_substr($sql, $count1, $count2 - $count1)); PMA_SQP_throwError($debugstr, $sql); return $sql_array; } } if ($is_digit && !$is_hex_digit && ($c2 == 'e' || $c2 == 'E')) { if (!$is_float_digit_exponent) { $is_float_digit_exponent = true; $is_float_digit = true; $count2++; continue; } else { $is_digit = false; $is_float_digit = false; } } if ($is_hex_digit && PMA_STR_isHexDigit($c2) || $is_digit && PMA_STR_isDigit($c2)) { $count2++; continue; } else { $is_digit = false; $is_hex_digit = false; } $count2++; } // end while $l = $count2 - $count1; $str = PMA_substr($sql, $count1, $l); $type = ''; if ($is_digit || $is_float_digit || $is_hex_digit) { $type = 'digit'; if ($is_float_digit) { $type .= '_float'; } elseif ($is_hex_digit) { $type .= '_hex'; } else { $type .= '_integer'; } } elseif ($is_user) { $type = 'punct_user'; } elseif ($is_sql_variable != false) { $type = 'alpha_variable'; } else { $type = 'alpha'; } // end if... else.... PMA_SQP_arrayAdd($sql_array, $type, $str, $arraysize, $count2); continue; } // Checks for punct if (PMA_strpos($allpunct_list, $c) !== false) { while ($count2 < $len && PMA_strpos($allpunct_list, PMA_substr($sql, $count2, 1)) !== false) { $count2++; } $l = $count2 - $count1; if ($l == 1) { $punct_data = $c; } else { $punct_data = PMA_substr($sql, $count1, $l); } // Special case, sometimes, althought two characters are // adjectent directly, they ACTUALLY need to be seperate /* DEBUG echo '<pre>'; var_dump($l); var_dump($punct_data); echo '</pre>'; */ if ($l == 1) { $t_suffix = ''; switch ($punct_data) { case $punct_queryend: $t_suffix = '_queryend'; break; case $punct_qualifier: $t_suffix = '_qualifier'; $this_was_punct = true; break; case $punct_listsep: $this_was_listsep = true; $t_suffix = '_listsep'; break; default: break; } PMA_SQP_arrayAdd($sql_array, 'punct' . $t_suffix, $punct_data, $arraysize); } elseif ($punct_data == $GLOBALS['sql_delimiter'] || isset($allpunct_list_pair[$punct_data])) { // Ok, we have one of the valid combined punct expressions PMA_SQP_arrayAdd($sql_array, 'punct', $punct_data, $arraysize); } else { // Bad luck, lets split it up more $first = $punct_data[0]; $first2 = $punct_data[0] . $punct_data[1]; $last2 = $punct_data[$l - 2] . $punct_data[$l - 1]; $last = $punct_data[$l - 1]; if ($first == ',' || $first == ';' || $first == '.' || $first == '*') { $count2 = $count1 + 1; $punct_data = $first; } elseif ($last2 == '/*' || $last2 == '--' && ($count2 == $len || PMA_substr($sql, $count2, 1) <= ' ')) { $count2 -= 2; $punct_data = PMA_substr($sql, $count1, $count2 - $count1); } elseif ($last == '-' || $last == '+' || $last == '!') { $count2--; $punct_data = PMA_substr($sql, $count1, $count2 - $count1); } elseif ($last != '~') { /** * @todo for negation operator, split in 2 tokens ? * "select x&~1 from t" * becomes "select x & ~ 1 from t" ? */ $debugstr = __('Unknown Punctuation String') . ' @ ' . ($count1 + 1) . "\n" . 'STR: ' . htmlspecialchars($punct_data); PMA_SQP_throwError($debugstr, $sql); return $sql_array; } PMA_SQP_arrayAdd($sql_array, 'punct', $punct_data, $arraysize); continue; } // end if... elseif... else continue; } // DEBUG $count2++; $debugstr = 'C1 C2 LEN: ' . $count1 . ' ' . $count2 . ' ' . $len . "\n" . 'STR: ' . PMA_substr($sql, $count1, $count2 - $count1) . "\n"; PMA_SQP_bug($debugstr, $sql); return $sql_array; } // end while ($count2 < $len) /* echo '<pre>'; print_r($sql_array); echo '</pre>'; */ if ($arraysize > 0) { $t_next = $sql_array[0]['type']; $t_prev = ''; $t_bef_prev = ''; $t_cur = ''; $d_next = $sql_array[0]['data']; $d_prev = ''; $d_bef_prev = ''; $d_cur = ''; $d_next_upper = $t_next == 'alpha' ? strtoupper($d_next) : $d_next; $d_prev_upper = ''; $d_bef_prev_upper = ''; $d_cur_upper = ''; } for ($i = 0; $i < $arraysize; $i++) { $t_bef_prev = $t_prev; $t_prev = $t_cur; $t_cur = $t_next; $d_bef_prev = $d_prev; $d_prev = $d_cur; $d_cur = $d_next; $d_bef_prev_upper = $d_prev_upper; $d_prev_upper = $d_cur_upper; $d_cur_upper = $d_next_upper; if ($i + 1 < $arraysize) { $t_next = $sql_array[$i + 1]['type']; $d_next = $sql_array[$i + 1]['data']; $d_next_upper = $t_next == 'alpha' ? strtoupper($d_next) : $d_next; } else { $t_next = ''; $d_next = ''; $d_next_upper = ''; } //DEBUG echo "[prev: <strong>".$d_prev."</strong> ".$t_prev."][cur: <strong>".$d_cur."</strong> ".$t_cur."][next: <strong>".$d_next."</strong> ".$t_next."]<br />"; if ($t_cur == 'alpha') { $t_suffix = '_identifier'; // for example: `thebit` bit(8) NOT NULL DEFAULT b'0' if ($t_prev == 'alpha' && $d_prev == 'DEFAULT' && $d_cur == 'b' && $t_next == 'quote_single') { $t_suffix = '_bitfield_constant_introducer'; } elseif ($t_next == 'punct_qualifier' || $t_prev == 'punct_qualifier') { $t_suffix = '_identifier'; } elseif ($t_next == 'punct_bracket_open_round' && isset($PMA_SQPdata_function_name[$d_cur_upper])) { /** * @todo 2005-10-16: in the case of a CREATE TABLE containing * a TIMESTAMP, since TIMESTAMP() is also a function, it's * found here and the token is wrongly marked as alpha_functionName. * But we compensate for this when analysing for timestamp_not_null * later in this script. * * Same applies to CHAR vs. CHAR() function. */ $t_suffix = '_functionName'; /* There are functions which might be as well column types */ } elseif (isset($PMA_SQPdata_column_type[$d_cur_upper])) { $t_suffix = '_columnType'; /** * Temporary fix for bugs #621357 and #2027720 * * @todo FIX PROPERLY NEEDS OVERHAUL OF SQL TOKENIZER */ if (($d_cur_upper == 'SET' || $d_cur_upper == 'BINARY') && $t_next != 'punct_bracket_open_round') { $t_suffix = '_reservedWord'; } //END OF TEMPORARY FIX // CHARACTER is a synonym for CHAR, but can also be meant as // CHARACTER SET. In this case, we have a reserved word. if ($d_cur_upper == 'CHARACTER' && $d_next_upper == 'SET') { $t_suffix = '_reservedWord'; } // experimental // current is a column type, so previous must not be // a reserved word but an identifier // CREATE TABLE SG_Persons (first varchar(64)) //if ($sql_array[$i-1]['type'] =='alpha_reservedWord') { // $sql_array[$i-1]['type'] = 'alpha_identifier'; //} } elseif (isset($PMA_SQPdata_reserved_word[$d_cur_upper])) { $t_suffix = '_reservedWord'; } elseif (isset($PMA_SQPdata_column_attrib[$d_cur_upper])) { $t_suffix = '_columnAttrib'; // INNODB is a MySQL table type, but in "SHOW INNODB STATUS", // it should be regarded as a reserved word. if ($d_cur_upper == 'INNODB' && $d_prev_upper == 'SHOW' && $d_next_upper == 'STATUS') { $t_suffix = '_reservedWord'; } if ($d_cur_upper == 'DEFAULT' && $d_next_upper == 'CHARACTER') { $t_suffix = '_reservedWord'; } // Binary as character set if ($d_cur_upper == 'BINARY' && ($d_bef_prev_upper == 'CHARACTER' && $d_prev_upper == 'SET' || $d_bef_prev_upper == 'SET' && $d_prev_upper == '=' || $d_bef_prev_upper == 'CHARSET' && $d_prev_upper == '=' || $d_prev_upper == 'CHARSET') && in_array($d_cur, $mysql_charsets)) { $t_suffix = '_charset'; } } elseif (in_array($d_cur, $mysql_charsets) || in_array($d_cur, $mysql_collations_flat) || $d_cur[0] == '_' && in_array(substr($d_cur, 1), $mysql_charsets)) { $t_suffix = '_charset'; } else { // Do nothing } // check if present in the list of forbidden words if ($t_suffix == '_reservedWord' && isset($PMA_SQPdata_forbidden_word[$d_cur_upper])) { $sql_array[$i]['forbidden'] = true; } else { $sql_array[$i]['forbidden'] = false; } $sql_array[$i]['type'] .= $t_suffix; } } // end for // Stores the size of the array inside the array, as count() is a slow // operation. $sql_array['len'] = $arraysize; // DEBUG echo 'After parsing<pre>'; print_r($sql_array); echo '</pre>'; // Sends the data back return $sql_array; }
/** * Get data cell for non numeric and non blob type fields * * @param string $column the relavent column in data row * @param string $class the html class for column * @param object $meta the meta-information about the field * @param array $map the list of relations * @param array $_url_params the parameters for generate url * @param boolean $condition_field the column should highlighted * or not * @param string $transformation_plugin the name of transformation function * @param string $default_function the default transformation function * @param string $transform_options the transformation parameters * @param boolean $is_field_truncated the condition for blob data * replacements * @param array $analyzed_sql the analyzed query * @param integer &$dt_result the link id associated to the query * which results have to be displayed * @param integer $col_index the column index * * @return string $cell the prepared data cell, html content * * @access private * * @see _getTableBody() */ private function _getDataCellForNonNumericAndNonBlobColumns($column, $class, $meta, $map, $_url_params, $condition_field, $transformation_plugin, $default_function, $transform_options, $is_field_truncated, $analyzed_sql, &$dt_result, $col_index) { $is_analyse = $this->__get('_is_analyse'); $field_flags = PMA_DBI_field_flags($dt_result, $col_index); if (stristr($field_flags, self::BINARY_FIELD) && ($GLOBALS['cfg']['ProtectBinary'] == 'all' || $GLOBALS['cfg']['ProtectBinary'] == 'noblob')) { $class = str_replace('grid_edit', '', $class); } if (!isset($column) || is_null($column)) { $cell = $this->_buildNullDisplay($class, $condition_field, $meta); } elseif ($column != '') { // Cut all fields to $GLOBALS['cfg']['LimitChars'] // (unless it's a link-type transformation) if (PMA_strlen($column) > $GLOBALS['cfg']['LimitChars'] && $_SESSION['tmp_user_values']['display_text'] == self::DISPLAY_PARTIAL_TEXT && gettype($transformation_plugin) == "object" && !strpos($transformation_plugin::getName(), 'Link') === true) { $column = PMA_substr($column, 0, $GLOBALS['cfg']['LimitChars']) . '...'; $is_field_truncated = true; } $formatted = false; if (isset($meta->_type) && $meta->_type === MYSQLI_TYPE_BIT) { $column = $this->getCommonFunctions()->printableBitValue($column, $meta->length); // some results of PROCEDURE ANALYSE() are reported as // being BINARY but they are quite readable, // so don't treat them as BINARY } elseif (stristr($field_flags, self::BINARY_FIELD) && $meta->type == self::STRING_FIELD && !(isset($is_analyse) && $is_analyse)) { if ($_SESSION['tmp_user_values']['display_binary']) { // user asked to see the real contents of BINARY // fields if ($_SESSION['tmp_user_values']['display_binary_as_hex'] && $this->getCommonFunctions()->containsNonPrintableAscii($column)) { $column = bin2hex($column); } else { $column = htmlspecialchars($this->getCommonFunctions()->replaceBinaryContents($column)); } } else { // we show the BINARY message and field's size // (or maybe use a transformation) $column = $this->_handleNonPrintableContents(self::BINARY_FIELD, $column, $transformation_plugin, $transform_options, $default_function, $meta, $_url_params); $formatted = true; } } if ($formatted) { $cell = $this->_buildValueDisplay($class, $condition_field, $column); } else { // transform functions may enable no-wrapping: $function_nowrap = 'applyTransformationNoWrap'; $bool_nowrap = $default_function != $transformation_plugin && function_exists($transformation_plugin->{$function_nowrap}()) ? $transformation_plugin->{$function_nowrap}($transform_options) : false; // do not wrap if date field type $nowrap = preg_match('@DATE|TIME@i', $meta->type) || $bool_nowrap ? ' nowrap' : ''; $where_comparison = ' = \'' . $this->getCommonFunctions()->sqlAddSlashes($column) . '\''; $cell = $this->_getRowData($class, $condition_field, $analyzed_sql, $meta, $map, $column, $transformation_plugin, $default_function, $nowrap, $where_comparison, $transform_options, $is_field_truncated); } } else { $cell = $this->_buildEmptyDisplay($class, $condition_field, $meta); } return $cell; }
/** * Outputs dropdown with values of foreign fields * * @param string the query of the foreign keys * @param string the foreign field * @param string the foreign field to display * @param string the current data of the dropdown * * @return string the <option value=""><option>s * * @access public */ function PMA_foreignDropdown($disp, $foreign_field, $foreign_display, $data, $max = 100) { global $cfg; $ret = '<option value=""></option>' . "\n"; $reloptions = array('content-id' => array(), 'id-content' => array()); foreach ($disp as $disp_key => $relrow) { $key = $relrow[$foreign_field]; // if the display field has been defined for the foreign table if ($foreign_display) { if (PMA_strlen($relrow[$foreign_display]) <= $cfg['LimitChars']) { $value = htmlspecialchars($relrow[$foreign_display]); $vtitle = ''; } else { $vtitle = htmlspecialchars($relrow[$foreign_display]); $value = htmlspecialchars(substr($vtitle, 0, $cfg['LimitChars']) . '...'); } } else { $vtitle = $value = ''; } // end if ($foreign_display) $reloption = '<option value="' . htmlspecialchars($key) . '"'; if ($vtitle != '') { $reloption .= ' title="' . $vtitle . '"'; } if ($key == $data) { $reloption .= ' selected="selected"'; } // end if $reloptions['id-content'][] = $reloption . '>' . $value . ' - ' . htmlspecialchars($key) . '</option>' . "\n"; $reloptions['content-id'][] = $reloption . '>' . htmlspecialchars($key) . ' - ' . $value . '</option>' . "\n"; } // end while // the list of keys looks better if not sorted by description if ($cfg['NaturalOrder']) { natsort($reloptions['content-id']); } else { asort($reloptions['content-id']); } if ($max == -1 || count($reloptions['content-id']) < $max) { $ret .= implode('', $reloptions['content-id']); if (count($reloptions['content-id']) > 0) { $ret .= '<option value=""></option>' . "\n"; $ret .= '<option value=""></option>' . "\n"; } } $ret .= implode('', $reloptions['id-content']); return $ret; }
</td> <td bgcolor="<?php echo $bgcolor; ?> "><?php echo ($key_equals_data ? '<b>' : '') . '<a href="#" title="' . $strUseThisValue . ($vtitle != '' ? ': ' . $vtitle : '') . '" onclick="formupdate(\'' . md5($field) . '\', \'' . htmlspecialchars($key) . '\'); return false;">' . $value . '</a>' . ($key_equals_data ? '</b>' : ''); ?> </td> <td width="20%"><img src="<?php echo $GLOBALS['pmaThemeImage'] . 'spacer.png'; ?> " alt="" width="1" height="1"></td> <?php $key = key($mysql_key_relrow[$i]); $val = $mysql_key_relrow[$i][$key]; if (PMA_strlen($val) <= $cfg['LimitChars']) { $value = htmlspecialchars($val); $vtitle = ''; } else { $vtitle = htmlspecialchars($val); $value = htmlspecialchars(PMA_substr($val, 0, $cfg['LimitChars']) . '...'); } $key_equals_data = isset($data) && $key == $data; ?> <td bgcolor="<?php echo $bgcolor; ?> "><?php echo ($key_equals_data ? '<b>' : '') . '<a href="#" title="' . $strUseThisValue . ($vtitle != '' ? ': ' . $vtitle : '') . '" onclick="formupdate(\'' . md5($field) . '\', \'' . htmlspecialchars($key) . '\'); return false;">' . $value . '</a>' . ($key_equals_data ? '</b>' : ''); ?> </td>
. '</tr>' . '<tr>' . '<th>' . __('Log name') . '</th>' . '<th>' . __('Position') . '</th>' . '<th>' . __('Event type') . '</th>' . '<th>' . __('Server ID') . '</th>' . '<th>' . __('Original position') . '</th>' . '<th>' . __('Information') . '</th>' . '</tr>' . '</thead>' . '<tbody>'; $odd_row = true; while ($value = PMA_DBI_fetch_assoc($result)) { if (! $dontlimitchars && PMA_strlen($value['Info']) > $GLOBALS['cfg']['LimitChars'] ) { $value['Info'] = PMA_substr( $value['Info'], 0, $GLOBALS['cfg']['LimitChars'] ) . '...'; } echo '<tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">' . '<td> ' . $value['Log_name'] . ' </td>' . '<td class="right"> ' . $value['Pos'] . ' </td>' . '<td> ' . $value['Event_type'] . ' </td>' . '<td class="right"> ' . $value['Server_id'] . ' </td>' . '<td class="right"> ' . (isset($value['Orig_log_pos']) ? $value['Orig_log_pos'] : $value['End_log_pos']) . ' </td>'