Merge branch 'MAINT_4_5_5' into STABLE

This commit is contained in:
Isaac Bennetch 2016-02-29 08:50:23 -05:00
commit 84a3d88fb2
37 changed files with 247 additions and 106 deletions

View File

@ -1,6 +1,18 @@
phpMyAdmin - ChangeLog phpMyAdmin - ChangeLog
====================== ======================
4.5.5.1 (2016-02-29)
- issue #11971 CREATE UNIQUE INDEX index type is not recognized by parser.
- issue #11982 Row count wrong when grouping joined tables.
- issue #12012 Column definition with default value and comment in CREATE TABLE expoerted faulty.
- issue #12020 New statement but no delimiter and unexpected token with REPLACE.
- issue #12029 Fixed incorrect usage of SQL parser context in SQL export
- issue [security] XSS vulnerability in SQL parser, see PMASA-2016-10.
- issue [security] Multiple XSS vulnerabilities, see PMASA-2016-11.
- issue [security] Multiple XSS vulnerabilities, see PMASA-2016-12.
- issue [security] Vulnerability allowing man-in-the-middle attack on API call to GitHub, see PMASA-2016-13.
- issue #12048 Fixed inclusion of gettext library from SQL parser
4.5.5.0 (2016-02-22) 4.5.5.0 (2016-02-22)
- issue Undefined index: is_ajax_request - issue Undefined index: is_ajax_request
- issue #11855 Fix password change on MariaDB 10.1 and newer - issue #11855 Fix password change on MariaDB 10.1 and newer
@ -70,15 +82,15 @@ phpMyAdmin - ChangeLog
- issue #11854 Undefined property: stdClass::$releases at version check when disabled in config - issue #11854 Undefined property: stdClass::$releases at version check when disabled in config
- issue #11814 SQL comment and variable stripped from bookmark on save - issue #11814 SQL comment and variable stripped from bookmark on save
- issue Gracefully handle errors in regex based javascript search - issue Gracefully handle errors in regex based javascript search
- issue [Security] Multiple full path disclosure vulnerabilities, see PMASA-2016-1 - issue [security] Multiple full path disclosure vulnerabilities, see PMASA-2016-1
- issue [Security] Unsafe generation of CSRF token, see PMASA-2016-2 - issue [security] Unsafe generation of CSRF token, see PMASA-2016-2
- issue [Security] Multiple XSS vulnerabilities, see PMASA-2016-3 - issue [security] Multiple XSS vulnerabilities, see PMASA-2016-3
- issue [Security] Insecure password generation in JavaScript, see PMASA-2016-4 - issue [security] Insecure password generation in JavaScript, see PMASA-2016-4
- issue [Security] Unsafe comparison of CSRF token, see PMASA-2016-5 - issue [security] Unsafe comparison of CSRF token, see PMASA-2016-5
- issue [Security] Multiple full path disclosure vulnerabilities, see PMASA-2016-6 - issue [security] Multiple full path disclosure vulnerabilities, see PMASA-2016-6
- issue [Security] XSS vulnerability in normalization page, see PMASA-2016-7 - issue [security] XSS vulnerability in normalization page, see PMASA-2016-7
- issue [Security] Full path disclosure vulnerability in SQL parser, see PMASA-2016-8 - issue [security] Full path disclosure vulnerability in SQL parser, see PMASA-2016-8
- issue [Security] XSS vulnerability in SQL editor, see PMASA-2016-9 - issue [security] XSS vulnerability in SQL editor, see PMASA-2016-9
--- Older ChangeLogs can be found on our project website --- --- Older ChangeLogs can be found on our project website ---
http://www.phpmyadmin.net/old-stuff/ChangeLogs/ http://www.phpmyadmin.net/old-stuff/ChangeLogs/

2
README
View File

@ -1,7 +1,7 @@
phpMyAdmin - Readme phpMyAdmin - Readme
=================== ===================
Version 4.5.5 Version 4.5.5.1
A set of PHP-scripts to manage MySQL over the web. A set of PHP-scripts to manage MySQL over the web.

View File

@ -92,7 +92,7 @@ if (isset($_REQUEST['total_rows']) && $_REQUEST['total_rows']) {
} else { } else {
$total_rows = PMA_getCentralColumnsCount($db); $total_rows = PMA_getCentralColumnsCount($db);
} }
if (isset($_REQUEST['pos'])) { if (PMA_isValid($_REQUEST['pos'], 'integer')) {
$pos = $_REQUEST['pos']; $pos = $_REQUEST['pos'];
} else { } else {
$pos = 0; $pos = 0;

View File

@ -51,7 +51,7 @@ copyright = u'2012 - 2014, The phpMyAdmin devel team'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '4.5.5' version = '4.5.5.1'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = version release = version

View File

@ -67,12 +67,16 @@ if (isset($_REQUEST['filename']) && isset($_REQUEST['image'])) {
} else if (isset($_REQUEST['monitorconfig'])) { } else if (isset($_REQUEST['monitorconfig'])) {
/* For monitor chart config export */ /* For monitor chart config export */
PMA_downloadHeader('monitor.cfg', 'application/force-download'); PMA_downloadHeader('monitor.cfg', 'application/json; charset=UTF-8');
header('X-Content-Type-Options: nosniff');
echo urldecode($_REQUEST['monitorconfig']); echo urldecode($_REQUEST['monitorconfig']);
} else if (isset($_REQUEST['import'])) { } else if (isset($_REQUEST['import'])) {
/* For monitor chart config import */ /* For monitor chart config import */
header('Content-type: text/plain'); header('Content-Type: application/json; charset=UTF-8');
header('X-Content-Type-Options: nosniff');
if (!file_exists($_FILES['file']['tmp_name'])) { if (!file_exists($_FILES['file']['tmp_name'])) {
exit(); exit();
} }

View File

@ -243,6 +243,24 @@ function escapeHtml(unsafe) {
} }
} }
function escapeJsString(unsafe) {
if (typeof(unsafe) != 'undefined') {
return unsafe
.toString()
.replace("\000", '')
.replace('\\', '\\\\')
.replace('\'', '\\\'')
.replace("'", "\\\'")
.replace('"', '\"')
.replace(""", "\"")
.replace("\n", '\n')
.replace("\r", '\r')
.replace(/<\/script/gi, '</\' + \'script')
} else {
return false;
}
}
function PMA_sprintf() { function PMA_sprintf() {
return sprintf.apply(this, arguments); return sprintf.apply(this, arguments);
} }
@ -1840,7 +1858,7 @@ AJAX.registerOnload('functions.js', function () {
var $inner_sql = $(this).parent().prev().find('code.sql'); var $inner_sql = $(this).parent().prev().find('code.sql');
var old_text = $inner_sql.html(); var old_text = $inner_sql.html();
var new_content = "<textarea name=\"sql_query_edit\" id=\"sql_query_edit\">" + sql_query + "</textarea>\n"; var new_content = "<textarea name=\"sql_query_edit\" id=\"sql_query_edit\">" + escapeHtml(sql_query) + "</textarea>\n";
new_content += getForeignKeyCheckboxLoader(); new_content += getForeignKeyCheckboxLoader();
new_content += "<input type=\"submit\" id=\"sql_query_edit_save\" class=\"button btnSave\" value=\"" + PMA_messages.strGo + "\"/>\n"; new_content += "<input type=\"submit\" id=\"sql_query_edit_save\" class=\"button btnSave\" value=\"" + PMA_messages.strGo + "\"/>\n";
new_content += "<input type=\"button\" id=\"sql_query_edit_discard\" class=\"button btnDiscard\" value=\"" + PMA_messages.strCancel + "\"/>\n"; new_content += "<input type=\"button\" id=\"sql_query_edit_discard\" class=\"button btnDiscard\" value=\"" + PMA_messages.strCancel + "\"/>\n";

View File

@ -82,7 +82,7 @@ function goTo2NFStep1() {
$("#mainContent #extra").html(data.extra); $("#mainContent #extra").html(data.extra);
$("#mainContent #newCols").html(''); $("#mainContent #newCols").html('');
if (data.subText !== '') { if (data.subText !== '') {
$('.tblFooters').html('<input type="submit" value="' + PMA_messages.strDone + '" onclick="processDependencies(\'' + data.primary_key + '\');">'); $('.tblFooters').html('<input type="submit" value="' + PMA_messages.strDone + '" onclick="processDependencies(\'' + escapeJsString(escapeHtml(data.primary_key)) + '\');">');
} else { } else {
if (normalizeto === '3nf') { if (normalizeto === '3nf') {
$("#mainContent #newCols").html(PMA_messages.strToNextStep); $("#mainContent #newCols").html(PMA_messages.strToNextStep);
@ -128,7 +128,7 @@ function goToStep4()
$("#mainContent #newCols").html(''); $("#mainContent #newCols").html('');
$('.tblFooters').html(''); $('.tblFooters').html('');
for(var pk in primary_key) { for(var pk in primary_key) {
$("#extra input[value='" + primary_key[pk] + "']").attr("disabled","disabled"); $("#extra input[value='" + escapeJsString(primary_key[pk]) + "']").attr("disabled","disabled");
} }
} }
); );
@ -153,7 +153,7 @@ function goToStep3()
$('.tblFooters').html(''); $('.tblFooters').html('');
primary_key = $.parseJSON(data.primary_key); primary_key = $.parseJSON(data.primary_key);
for(var pk in primary_key) { for(var pk in primary_key) {
$("#extra input[value='" + primary_key[pk] + "']").attr("disabled","disabled"); $("#extra input[value='" + escapeJsString(primary_key[pk]) + "']").attr("disabled","disabled");
} }
} }
); );
@ -638,7 +638,7 @@ AJAX.registerOnload('normalization.js', function() {
'</ol>'; '</ol>';
$("#newCols").html(confirmStr); $("#newCols").html(confirmStr);
$('.tblFooters').html('<input type="submit" value="' + PMA_messages.strCancel + '" onclick="$(\'#newCols\').html(\'\');$(\'#extra input[type=checkbox]\').removeAttr(\'checked\')"/>' + $('.tblFooters').html('<input type="submit" value="' + PMA_messages.strCancel + '" onclick="$(\'#newCols\').html(\'\');$(\'#extra input[type=checkbox]\').removeAttr(\'checked\')"/>' +
'<input type="submit" value="' + PMA_messages.strGo + '" onclick="moveRepeatingGroup(\'' + repeatingCols + '\')"/>'); '<input type="submit" value="' + PMA_messages.strGo + '" onclick="moveRepeatingGroup(\'' + escapeJsString(escapeHtml(repeatingCols)) + '\')"/>');
} }
}); });
$("#mainContent p").on("click", "#createPrimaryKey", function(event) { $("#mainContent p").on("click", "#createPrimaryKey", function(event) {

View File

@ -114,7 +114,7 @@ class PMA_Config
*/ */
public function checkSystem() public function checkSystem()
{ {
$this->set('PMA_VERSION', '4.5.5'); $this->set('PMA_VERSION', '4.5.5.1');
/** /**
* @deprecated * @deprecated
*/ */
@ -774,8 +774,8 @@ class PMA_Config
PMA_Util::configureCurl($handle); PMA_Util::configureCurl($handle);
curl_setopt($handle, CURLOPT_FOLLOWLOCATION, 0); curl_setopt($handle, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1); curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, '2');
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, '1');
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($handle, CURLOPT_TIMEOUT, 5); curl_setopt($handle, CURLOPT_TIMEOUT, 5);
curl_setopt($handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_setopt($handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
@ -1370,7 +1370,7 @@ class PMA_Config
$pma_absolute_uri .= '@'; $pma_absolute_uri .= '@';
} }
// Add hostname // Add hostname
$pma_absolute_uri .= $url['host']; $pma_absolute_uri .= urlencode($url['host']);
// Add port, if it not the default one // Add port, if it not the default one
// (or 80 for https which is most likely a bug) // (or 80 for https which is most likely a bug)
if (! empty($url['port']) if (! empty($url['port'])

View File

@ -471,7 +471,11 @@ class TableSearchController extends TableController
return; return;
} }
$key = array_search($field, $this->_columnNames); $key = array_search($field, $this->_columnNames);
$properties = $this->getColumnProperties($_REQUEST['it'], $key); $search_index = 0;
if (PMA_isValid($_REQUEST['it'], 'integer')) {
$search_index = $_REQUEST['it'];
}
$properties = $this->getColumnProperties($search_index, $key);
$this->response->addJSON( $this->response->addJSON(
'field_type', htmlspecialchars($properties['type']) 'field_type', htmlspecialchars($properties['type'])
); );

View File

@ -1554,7 +1554,7 @@ class ExportSql extends ExportPlugin
if (empty($sql_backquotes)) { if (empty($sql_backquotes)) {
// Option "Enclose table and column names with backquotes" // Option "Enclose table and column names with backquotes"
// was checked. // was checked.
Context::$MODE |= Context::NO_ENCLOSING_QUOTES; SqlParser\Context::$MODE |= SqlParser\Context::NO_ENCLOSING_QUOTES;
} }
// Using appropriate quotes. // Using appropriate quotes.

View File

@ -3499,7 +3499,7 @@ function PMA_getUsersOverview($result, $db_rights, $pmaThemeImage, $text_dir)
__('Export'), 'b_tblexport.png', 'export' __('Export'), 'b_tblexport.png', 'export'
); );
$html_output .= '<input type="hidden" name="initial" ' $html_output .= '<input type="hidden" name="initial" '
. 'value="' . (isset($_GET['initial']) ? $_GET['initial'] : '') . '" />'; . 'value="' . (isset($_GET['initial']) ? htmlspecialchars($_GET['initial']) : '') . '" />';
$html_output .= '</div>' $html_output .= '</div>'
. '<div class="clear_both" style="clear:both"></div>'; . '<div class="clear_both" style="clear:both"></div>';

View File

@ -67,7 +67,8 @@ class AutoloaderInit
// This must be included before any class of the parser is loaded because // This must be included before any class of the parser is loaded because
// if there is no `__` function defined, the library defines a dummy one // if there is no `__` function defined, the library defines a dummy one
// in `common.php`. // in `common.php`.
require_once './libraries/php-gettext/gettext.inc'; require_once './libraries/vendor_config.php';
require_once GETTEXT_INC;
// Initializing the autoloader. // Initializing the autoloader.
return AutoloaderInit::getLoader( return AutoloaderInit::getLoader(

View File

@ -26,19 +26,31 @@ class AlterOperation extends Component
{ {
/** /**
* All alter operations. * All database options
* *
* @var array * @var array
*/ */
public static $OPTIONS = array( public static $DB_OPTIONS = array(
'CHARACTER SET' => array(1, 'var'),
'CHARSET' => array(1, 'var'),
'DEFAULT CHARACTER SET' => array(1, 'var'),
'DEFAULT CHARSET' => array(1, 'var'),
'UPGRADE' => array(1, 'var'),
'COLLATE' => array(2, 'var'),
'DEFAULT COLLATE' => array(2, 'var'),
);
// table_options /**
* All table options
*
* @var array
*/
public static $TABLE_OPTIONS = array(
'ENGINE' => array(1, 'var='), 'ENGINE' => array(1, 'var='),
'AUTO_INCREMENT' => array(1, 'var='), 'AUTO_INCREMENT' => array(1, 'var='),
'AVG_ROW_LENGTH' => array(1, 'var'), 'AVG_ROW_LENGTH' => array(1, 'var'),
'MAX_ROWS' => array(1, 'var'), 'MAX_ROWS' => array(1, 'var'),
'ROW_FORMAT' => array(1, 'var'), 'ROW_FORMAT' => array(1, 'var'),
'ADD' => 1, 'ADD' => 1,
'ALTER' => 1, 'ALTER' => 1,
'ANALYZE' => 1, 'ANALYZE' => 1,
@ -60,6 +72,7 @@ class AlterOperation extends Component
'RENAME' => 1, 'RENAME' => 1,
'REORGANIZE' => 1, 'REORGANIZE' => 1,
'REPAIR' => 1, 'REPAIR' => 1,
'UPGRADE' => 1,
'COLUMN' => 2, 'COLUMN' => 2,
'CONSTRAINT' => 2, 'CONSTRAINT' => 2,
@ -75,11 +88,15 @@ class AlterOperation extends Component
'SPATIAL' => 2, 'SPATIAL' => 2,
'TABLESPACE' => 2, 'TABLESPACE' => 2,
'INDEX' => 2, 'INDEX' => 2,
);
'DEFAULT CHARACTER SET' => array(3, 'var'), /**
'DEFAULT CHARSET' => array(3, 'var'), * All view options
*
'COLLATE' => array(4, 'var'), * @var array
*/
public static $VIEW_OPTIONS = array(
'AS' => 1,
); );
/** /**
@ -165,7 +182,18 @@ class AlterOperation extends Component
} }
if ($state === 0) { if ($state === 0) {
$ret->options = OptionsArray::parse($parser, $list, static::$OPTIONS); $ret->options = OptionsArray::parse($parser, $list, $options);
if ($ret->options->has('AS')) {
for (; $list->idx < $list->count; ++$list->idx) {
if ($list->tokens[$list->idx]->type === Token::TYPE_DELIMITER) {
break;
}
$ret->unknown[] = $list->tokens[$list->idx];
}
break;
}
$state = 1; $state = 1;
} elseif ($state === 1) { } elseif ($state === 1) {
$ret->field = Expression::parse( $ret->field = Expression::parse(

View File

@ -108,7 +108,7 @@ class ArrayObj extends Component
|| ($token->type === Token::TYPE_COMMENT) || ($token->type === Token::TYPE_COMMENT)
) { ) {
$lastRaw .= $token->token; $lastRaw .= $token->token;
$lastValue = trim($lastValue) .' '; $lastValue = trim($lastValue) . ' ';
continue; continue;
} }

View File

@ -166,7 +166,10 @@ class Condition extends Component
} }
} }
if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED)) { if (($token->type === Token::TYPE_KEYWORD)
&& ($token->flags & Token::FLAG_KEYWORD_RESERVED)
&& !($token->flags & Token::FLAG_KEYWORD_FUNCTION)
) {
if ($token->value === 'BETWEEN') { if ($token->value === 'BETWEEN') {
$betweenBefore = true; $betweenBefore = true;
} }

View File

@ -43,7 +43,7 @@ class CreateDefinition extends Component
'NOT NULL' => 1, 'NOT NULL' => 1,
'NULL' => 1, 'NULL' => 1,
'DEFAULT' => array(2, 'expr'), 'DEFAULT' => array(2, 'expr', array('breakOnAlias' => true)),
'AUTO_INCREMENT' => 3, 'AUTO_INCREMENT' => 3,
'PRIMARY' => 4, 'PRIMARY' => 4,
'PRIMARY KEY' => 4, 'PRIMARY KEY' => 4,

View File

@ -243,9 +243,9 @@ class Expression extends Component
if (!empty($options['breakOnAlias'])) { if (!empty($options['breakOnAlias'])) {
break; break;
} }
if (!empty($ret->alias)) { if ($alias) {
$parser->error( $parser->error(
__('An alias was previously found.'), __('An alias was expected.'),
$token $token
); );
break; break;

View File

@ -63,6 +63,13 @@ class JoinKeyword extends Component
*/ */
public $on; public $on;
/**
* Columns in Using clause
*
* @var ArrayObj
*/
public $using;
/** /**
* @param Parser $parser The parser that serves as context. * @param Parser $parser The parser that serves as context.
* @param TokensList $list The list of tokens that are being parsed. * @param TokensList $list The list of tokens that are being parsed.
@ -86,9 +93,12 @@ class JoinKeyword extends Component
* 1 -----------------------[ expr ]----------------------> 2 * 1 -----------------------[ expr ]----------------------> 2
* *
* 2 ------------------------[ ON ]-----------------------> 3 * 2 ------------------------[ ON ]-----------------------> 3
* 2 -----------------------[ USING ]---------------------> 4
* *
* 3 --------------------[ conditions ]-------------------> 0 * 3 --------------------[ conditions ]-------------------> 0
* *
* 4 ----------------------[ columns ]--------------------> 0
*
* @var int $state * @var int $state
*/ */
$state = 0; $state = 0;
@ -131,14 +141,23 @@ class JoinKeyword extends Component
$expr->expr = Expression::parse($parser, $list, array('field' => 'table')); $expr->expr = Expression::parse($parser, $list, array('field' => 'table'));
$state = 2; $state = 2;
} elseif ($state === 2) { } elseif ($state === 2) {
if (($token->type === Token::TYPE_KEYWORD) && ($token->value === 'ON')) { if ($token->type === Token::TYPE_KEYWORD) {
$state = 3; if ($token->value === 'ON') {
$state = 3;
} elseif ($token->value === 'USING') {
$state = 4;
}
} }
} elseif ($state === 3) { } elseif ($state === 3) {
$expr->on = Condition::parse($parser, $list); $expr->on = Condition::parse($parser, $list);
$ret[] = $expr; $ret[] = $expr;
$expr = new JoinKeyword(); $expr = new JoinKeyword();
$state = 0; $state = 0;
} elseif ($state === 4) {
$expr->using = ArrayObj::parse($parser, $list);
$ret[] = $expr;
$expr = new JoinKeyword();
$state = 0;
} }
} }
@ -161,8 +180,10 @@ class JoinKeyword extends Component
{ {
$ret = array(); $ret = array();
foreach ($component as $c) { foreach ($component as $c) {
$ret[] = array_search($c->type, static::$JOINS) . ' ' $ret[] = array_search($c->type, static::$JOINS) . ' ' . $c->expr
. $c->expr . ' ON ' . Condition::build($c->on); . (!empty($c->on)
? ' ON ' . Condition::build($c->on)
: ' USING ' . ArrayObj::build($c->using));
} }
return implode(' ', $ret); return implode(' ', $ret);
} }

View File

@ -93,7 +93,7 @@ class Key extends Component
* @param TokensList $list The list of tokens that are being parsed. * @param TokensList $list The list of tokens that are being parsed.
* @param array $options Parameters for parsing. * @param array $options Parameters for parsing.
* *
* @return Key[] * @return Key
*/ */
public static function parse(Parser $parser, TokensList $list, array $options = array()) public static function parse(Parser $parser, TokensList $list, array $options = array())
{ {

View File

@ -128,7 +128,7 @@ class Limit extends Component
public static function build($component, array $options = array()) public static function build($component, array $options = array())
{ {
if (empty($component->offset)) { if (empty($component->offset)) {
return $component->rowCount; return (string) $component->rowCount;
} else { } else {
return $component->offset . ', ' . $component->rowCount; return $component->offset . ', ' . $component->rowCount;
} }

View File

@ -287,10 +287,12 @@ class OptionsArray extends Component
public function has($key, $getExpr = false) public function has($key, $getExpr = false)
{ {
foreach ($this->options as $option) { foreach ($this->options as $option) {
if ($key === $option) { if (is_array($option)) {
if (!strcasecmp($key, $option['name'])) {
return $getExpr ? $option['expr'] : $option['value'];
}
} elseif (!strcasecmp($key, $option)) {
return true; return true;
} elseif ((is_array($option)) && ($key === $option['name'])) {
return $getExpr ? $option['expr'] : $option['value'];
} }
} }
return false; return false;
@ -306,9 +308,12 @@ class OptionsArray extends Component
public function remove($key) public function remove($key)
{ {
foreach ($this->options as $idx => $option) { foreach ($this->options as $idx => $option) {
if (($key === $option) if (is_array($option)) {
|| ((is_array($option)) && ($key === $option['name'])) if (!strcasecmp($key, $option['name'])) {
) { unset($this->options[$idx]);
return true;
}
} elseif (!strcasecmp($key, $option)) {
unset($this->options[$idx]); unset($this->options[$idx]);
return true; return true;
} }

View File

@ -100,9 +100,13 @@ class OrderKeyword extends Component
$expr->expr = Expression::parse($parser, $list); $expr->expr = Expression::parse($parser, $list);
$state = 1; $state = 1;
} elseif ($state === 1) { } elseif ($state === 1) {
if (($token->type === Token::TYPE_KEYWORD) && (($token->value === 'ASC') || ($token->value === 'DESC'))) { if (($token->type === Token::TYPE_KEYWORD)
&& (($token->value === 'ASC') || ($token->value === 'DESC'))
) {
$expr->type = $token->value; $expr->type = $token->value;
} elseif (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) { } elseif (($token->type === Token::TYPE_OPERATOR)
&& ($token->value === ',')
) {
if (!empty($expr->expr)) { if (!empty($expr->expr)) {
$ret[] = $expr; $ret[] = $expr;
} }

View File

@ -85,7 +85,10 @@ class SetOperation extends Component
} }
// No keyword is expected. // No keyword is expected.
if (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_RESERVED) && ($state == 0)) { if (($token->type === Token::TYPE_KEYWORD)
&& ($token->flags & Token::FLAG_KEYWORD_RESERVED)
&& ($state == 0)
) {
break; break;
} }
@ -104,7 +107,6 @@ class SetOperation extends Component
) )
); );
if ($tmp == null) { if ($tmp == null) {
$expr = null;
break; break;
} }
$expr->column = trim($expr->column); $expr->column = trim($expr->column);

View File

@ -185,6 +185,11 @@ class Parser
'class' => 'SqlParser\\Components\\JoinKeyword', 'class' => 'SqlParser\\Components\\JoinKeyword',
'field' => 'join', 'field' => 'join',
), ),
'ON' => array(
'class' => 'SqlParser\\Components\\Expression',
'field' => 'table',
'options' => array('parseField' => 'table'),
),
'RIGHT JOIN' => array( 'RIGHT JOIN' => array(
'class' => 'SqlParser\\Components\\JoinKeyword', 'class' => 'SqlParser\\Components\\JoinKeyword',
'field' => 'join', 'field' => 'join',

View File

@ -51,6 +51,15 @@ class AlterStatement extends Statement
'ONLINE' => 1, 'ONLINE' => 1,
'OFFLINE' => 1, 'OFFLINE' => 1,
'IGNORE' => 2, 'IGNORE' => 2,
'DATABASE' => 3,
'EVENT' => 3,
'FUNCTION' => 3,
'PROCEDURE' => 3,
'SERVER' => 3,
'TABLE' => 3,
'TABLESPACE' => 3,
'VIEW' => 3,
); );
/** /**
@ -67,16 +76,14 @@ class AlterStatement extends Statement
$list, $list,
static::$OPTIONS static::$OPTIONS
); );
++$list->idx;
// Skipping `TABLE`.
$list->getNextOfTypeAndValue(Token::TYPE_KEYWORD, 'TABLE');
// Parsing affected table. // Parsing affected table.
$this->table = Expression::parse( $this->table = Expression::parse(
$parser, $parser,
$list, $list,
array( array(
'parseField' => 'column', 'parseField' => 'table',
'breakOnAlias' => true, 'breakOnAlias' => true,
) )
); );
@ -114,7 +121,16 @@ class AlterStatement extends Statement
} }
if ($state === 0) { if ($state === 0) {
$this->altered[] = AlterOperation::parse($parser, $list); $options = array();
if ($this->options->has('DATABASE')) {
$options = AlterOperation::$DB_OPTIONS;
} elseif ($this->options->has('TABLE')) {
$options = AlterOperation::$TABLE_OPTIONS;
} elseif ($this->options->has('VIEW')) {
$options = AlterOperation::$VIEW_OPTIONS;
}
$this->altered[] = AlterOperation::parse($parser, $list, $options);
$state = 1; $state = 1;
} elseif ($state === 1) { } elseif ($state === 1) {
if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) { if (($token->type === Token::TYPE_OPERATOR) && ($token->value === ',')) {
@ -135,7 +151,7 @@ class AlterStatement extends Statement
} }
return 'ALTER ' . OptionsArray::build($this->options) return 'ALTER ' . OptionsArray::build($this->options)
. ' TABLE ' . Expression::build($this->table) . ' ' . Expression::build($this->table)
. ' ' . implode(', ', $tmp); . ' ' . implode(', ', $tmp);
} }
} }

View File

@ -53,6 +53,9 @@ class CreateStatement extends Statement
'EVENT' => 6, 'EVENT' => 6,
'FUNCTION' => 6, 'FUNCTION' => 6,
'INDEX' => 6, 'INDEX' => 6,
'UNIQUE INDEX' => 6,
'FULLTEXT INDEX' => 6,
'SPATIAL INDEX' => 6,
'PROCEDURE' => 6, 'PROCEDURE' => 6,
'SERVER' => 6, 'SERVER' => 6,
'TABLE' => 6, 'TABLE' => 6,
@ -314,13 +317,11 @@ class CreateStatement extends Statement
. Expression::build($this->name) . ' ' . Expression::build($this->name) . ' '
. ParameterDefinition::build($this->parameters) . ' ' . ParameterDefinition::build($this->parameters) . ' '
. $tmp . ' ' . TokensList::build($this->body); . $tmp . ' ' . TokensList::build($this->body);
} else {
return 'CREATE '
. OptionsArray::build($this->options) . ' '
. Expression::build($this->name) . ' '
. TokensList::build($this->body);
} }
return ''; return 'CREATE '
. OptionsArray::build($this->options) . ' '
. Expression::build($this->name) . ' '
. TokensList::build($this->body);
} }
/** /**

View File

@ -59,6 +59,7 @@ class DropStatement extends Statement
'_OPTIONS' => array('_OPTIONS', 1), '_OPTIONS' => array('_OPTIONS', 1),
// Used for select expressions. // Used for select expressions.
'DROP_' => array('DROP', 1), 'DROP_' => array('DROP', 1),
'ON' => array('ON', 3),
); );
/** /**
@ -67,4 +68,11 @@ class DropStatement extends Statement
* @var Expression[] * @var Expression[]
*/ */
public $fields; public $fields;
/**
* Table of the dropped index.
*
* @var Expression
*/
public $table;
} }

View File

@ -235,17 +235,17 @@ class Token
if ($this->flags & Token::FLAG_NUMBER_HEX) { if ($this->flags & Token::FLAG_NUMBER_HEX) {
if ($this->flags & Token::FLAG_NUMBER_NEGATIVE) { if ($this->flags & Token::FLAG_NUMBER_NEGATIVE) {
$ret = str_replace('-', '', $this->token); $ret = str_replace('-', '', $this->token);
sscanf($ret, "%x", $ret); sscanf($ret, '%x', $ret);
$ret = -$ret; $ret = -$ret;
} else { } else {
sscanf($ret, "%x", $ret); sscanf($ret, '%x', $ret);
} }
} elseif (($this->flags & Token::FLAG_NUMBER_APPROXIMATE) } elseif (($this->flags & Token::FLAG_NUMBER_APPROXIMATE)
|| ($this->flags & Token::FLAG_NUMBER_FLOAT) || ($this->flags & Token::FLAG_NUMBER_FLOAT)
) { ) {
sscanf($ret, "%f", $ret); sscanf($ret, '%f', $ret);
} else { } else {
sscanf($ret, "%d", $ret); sscanf($ret, '%d', $ret);
} }
return $ret; return $ret;
case Token::TYPE_STRING: case Token::TYPE_STRING:

View File

@ -90,7 +90,7 @@ class Error
++$i, ++$i,
$err[0], $err[0],
$err[1], $err[1],
$err[2], htmlspecialchars($err[2]),
$err[3] $err[3]
); );
} }

View File

@ -80,7 +80,7 @@ class Formatter
* *
* @var string * @var string
*/ */
'indentation' => " ", 'indentation' => ' ',
/** /**
* Whether comments should be removed or not. * Whether comments should be removed or not.
@ -122,49 +122,49 @@ class Formatter
'type' => Token::TYPE_KEYWORD, 'type' => Token::TYPE_KEYWORD,
'flags' => Token::FLAG_KEYWORD_RESERVED, 'flags' => Token::FLAG_KEYWORD_RESERVED,
'html' => 'class="sql-reserved"', 'html' => 'class="sql-reserved"',
'cli' => "\e[35m", 'cli' => "\e[35m",
'function' => 'strtoupper', 'function' => 'strtoupper',
), ),
array( array(
'type' => Token::TYPE_KEYWORD, 'type' => Token::TYPE_KEYWORD,
'flags' => 0, 'flags' => 0,
'html' => 'class="sql-keyword"', 'html' => 'class="sql-keyword"',
'cli' => "\e[95m", 'cli' => "\e[95m",
'function' => 'strtoupper', 'function' => 'strtoupper',
), ),
array( array(
'type' => Token::TYPE_COMMENT, 'type' => Token::TYPE_COMMENT,
'flags' => 0, 'flags' => 0,
'html' => 'class="sql-comment"', 'html' => 'class="sql-comment"',
'cli' => "\e[37m", 'cli' => "\e[37m",
'function' => '', 'function' => '',
), ),
array( array(
'type' => Token::TYPE_BOOL, 'type' => Token::TYPE_BOOL,
'flags' => 0, 'flags' => 0,
'html' => 'class="sql-atom"', 'html' => 'class="sql-atom"',
'cli' => "\e[36m", 'cli' => "\e[36m",
'function' => 'strtoupper', 'function' => 'strtoupper',
), ),
array( array(
'type' => Token::TYPE_NUMBER, 'type' => Token::TYPE_NUMBER,
'flags' => 0, 'flags' => 0,
'html' => 'class="sql-number"', 'html' => 'class="sql-number"',
'cli' => "\e[92m", 'cli' => "\e[92m",
'function' => 'strtolower', 'function' => 'strtolower',
), ),
array( array(
'type' => Token::TYPE_STRING, 'type' => Token::TYPE_STRING,
'flags' => 0, 'flags' => 0,
'html' => 'class="sql-string"', 'html' => 'class="sql-string"',
'cli' => "\e[91m", 'cli' => "\e[91m",
'function' => '', 'function' => '',
), ),
array( array(
'type' => Token::TYPE_SYMBOL, 'type' => Token::TYPE_SYMBOL,
'flags' => 0, 'flags' => 0,
'html' => 'class="sql-variable"', 'html' => 'class="sql-variable"',
'cli' => "\e[36m", 'cli' => "\e[36m",
'function' => '', 'function' => '',
), ),
) )
@ -387,7 +387,8 @@ class Formatter
// Also, some tokens do not have spaces before or after them. // Also, some tokens do not have spaces before or after them.
if (!((($prev->type === Token::TYPE_OPERATOR) && (($prev->value === '.') || ($prev->value === '('))) if (!((($prev->type === Token::TYPE_OPERATOR) && (($prev->value === '.') || ($prev->value === '(')))
// No space after . ( // No space after . (
|| (($curr->type === Token::TYPE_OPERATOR) && (($curr->value === '.') || ($curr->value === ',') || ($curr->value === '(') || ($curr->value === ')'))) || (($curr->type === Token::TYPE_OPERATOR) && (($curr->value === '.') || ($curr->value === ',')
|| ($curr->value === '(') || ($curr->value === ')')))
// No space before . , ( ) // No space before . , ( )
|| (($curr->type === Token::TYPE_DELIMITER)) && (mb_strlen($curr->value, 'UTF-8') < 2)) || (($curr->type === Token::TYPE_DELIMITER)) && (mb_strlen($curr->value, 'UTF-8') < 2))
// A space after delimiters that are longer than 2 characters. // A space after delimiters that are longer than 2 characters.

View File

@ -57,8 +57,8 @@ class Query
/** /**
* Gets an array with flags this statement has. * Gets an array with flags this statement has.
* *
* @param Statement $statement The statement to be processed. * @param Statement|null $statement The statement to be processed.
* @param bool $all If `false`, false values will not be included. * @param bool $all If `false`, false values will not be included.
* *
* @return array * @return array
*/ */
@ -380,7 +380,7 @@ class Query
$parser = new Parser($query); $parser = new Parser($query);
if (empty($parser->statements[0])) { if (empty($parser->statements[0])) {
return array(); return static::getFlags(null, true);
} }
$statement = $parser->statements[0]; $statement = $parser->statements[0];

View File

@ -2508,8 +2508,6 @@ class TCPDF_STATIC {
} }
curl_setopt($cs, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($cs, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($cs, CURLOPT_TIMEOUT, 30); curl_setopt($cs, CURLOPT_TIMEOUT, 30);
curl_setopt($cs, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($cs, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($cs, CURLOPT_USERAGENT, 'TCPDF'); curl_setopt($cs, CURLOPT_USERAGENT, 'TCPDF');
$ret = curl_exec($cs); $ret = curl_exec($cs);
curl_close($cs); curl_close($cs);

View File

@ -72,7 +72,7 @@ $scripts = $header->getScripts();
$scripts->addFile('normalization.js'); $scripts->addFile('normalization.js');
$scripts->addFile('jquery/jquery.uitablefilter.js'); $scripts->addFile('jquery/jquery.uitablefilter.js');
$normalForm = '1nf'; $normalForm = '1nf';
if (isset($_REQUEST['normalizeTo'])) { if (PMA_isValid($_REQUEST['normalizeTo'], array('1nf', '2nf', '3nf'))) {
$normalForm = $_REQUEST['normalizeTo']; $normalForm = $_REQUEST['normalizeTo'];
} }
if (isset($_REQUEST['createNewTables2NF'])) { if (isset($_REQUEST['createNewTables2NF'])) {

View File

@ -51,16 +51,20 @@ if ($requested_sort == $sort) {
} }
$_url_params = array( $_url_params = array(
'db' => $_REQUEST['db'], 'db' => $_REQUEST['db'],
'pos' => 0, // We set the position back to 0 every time they sort.
'sort' => $sort,
'sort_order' => $future_sort_order,
); );
$url = 'db_structure.php' . PMA_URL_getCommon($_url_params);
// We set the position back to 0 every time they sort. if (PMA_isValid($_REQUEST['tbl_type'], array('view', 'table'))) {
$url .= "&amp;pos=0&amp;sort=$sort&amp;sort_order=$future_sort_order"; $_url_params['tbl_type'] = $_REQUEST['tbl_type'];
if (! empty($_REQUEST['tbl_type'])) {
$url .= "&amp;tbl_type=" . $_REQUEST['tbl_type'];
} }
if (! empty($_REQUEST['tbl_group'])) { if (! empty($_REQUEST['tbl_group'])) {
$url .= "&amp;tbl_group=" . $_REQUEST['tbl_group']; $_url_params['tbl_group'] = $_REQUEST['tbl_group'];
} }
$url = 'db_structure.php' . PMA_URL_getCommon($_url_params);
echo PMA_Util::linkOrButton( echo PMA_Util::linkOrButton(
$url, $title . $order_img, $order_link_params $url, $title . $order_img, $order_link_params
); );

View File

@ -20,7 +20,7 @@ if ($_foreigners
<?php if (isset($criteriaValues[$column_index]) <?php if (isset($criteriaValues[$column_index])
&& is_string($criteriaValues[$column_index]) && is_string($criteriaValues[$column_index])
): ?> ): ?>
value="<?php echo $criteriaValues[$column_index]; ?>" value="<?php echo htmlspecialchars($criteriaValues[$column_index]); ?>"
<?php endif; ?> /> <?php endif; ?> />
<a class="ajax browse_foreign" <a class="ajax browse_foreign"
href="browse_foreigners.php<?php href="browse_foreigners.php<?php
@ -93,13 +93,13 @@ if ($_foreigners
&& is_array($criteriaValues[$column_index]) && is_array($criteriaValues[$column_index])
&& in_array($value[$j], $criteriaValues[$column_index]) && in_array($value[$j], $criteriaValues[$column_index])
): ?> ): ?>
<option value="<?php echo $value[$j]; ?>" <option value="<?php echo htmlspecialchars($value[$j]); ?>"
selected> selected>
<?php echo $value[$j]; ?> <?php echo htmlspecialchars($value[$j]); ?>
</option> </option>
<?php else: ?> <?php else: ?>
<option value="<?php echo $value[$j]; ?>"> <option value="<?php echo htmlspecialchars($value[$j]); ?>">
<?php echo $value[$j]; ?> <?php echo htmlspecialchars($value[$j]); ?>
</option> </option>
<?php endif; ?> <?php endif; ?>
<?php endfor; ?> <?php endfor; ?>
@ -129,7 +129,7 @@ if ($_foreigners
<?php if (isset($criteriaValues[$column_index]) <?php if (isset($criteriaValues[$column_index])
&& is_string($criteriaValues[$column_index]) && is_string($criteriaValues[$column_index])
): ?> ): ?>
value="<?php echo $criteriaValues[$column_index]; ?>" value="<?php echo htmlspecialchars($criteriaValues[$column_index]); ?>"
<?php endif; ?>/> <?php endif; ?>/>
<?php endif; ?> <?php endif; ?>

View File

@ -68,7 +68,7 @@ for ($i = 0; $i < 4; $i++): ?>
</td> </td>
<!-- Inputbox for search criteria value --> <!-- Inputbox for search criteria value -->
<td> <td>
<?php echo (isset($value[$i]) ? htmlspecialchars($value[$i]) : ''); ?> <?php echo (isset($value[$i]) ? $value[$i] : ''); ?>
</td> </td>
</tr> </tr>
<!-- Displays hidden fields --> <!-- Displays hidden fields -->

View File

@ -53,6 +53,7 @@ class PMA_ConfigTest extends PHPUnit_Framework_TestCase
$GLOBALS['server'] = 0; $GLOBALS['server'] = 0;
$_SESSION['is_git_revision'] = true; $_SESSION['is_git_revision'] = true;
$GLOBALS['PMA_Config'] = new PMA_Config(CONFIG_FILE); $GLOBALS['PMA_Config'] = new PMA_Config(CONFIG_FILE);
$GLOBALS['cfg']['ProxyUrl'] = '';
//for testing file permissions //for testing file permissions
$this->permTestObj = new PMA_Config("./config.sample.inc.php"); $this->permTestObj = new PMA_Config("./config.sample.inc.php");
@ -1038,14 +1039,19 @@ class PMA_ConfigTest extends PHPUnit_Framework_TestCase
$this->markTestSkipped('Missing curl extension!'); $this->markTestSkipped('Missing curl extension!');
} }
$this->assertTrue( $this->assertTrue(
$this->object->checkHTTP("http://www.phpmyadmin.net/test/data") $this->object->checkHTTP("https://www.phpmyadmin.net/test/data")
); );
$this->assertContains( $this->assertContains(
"TEST DATA", "TEST DATA",
$this->object->checkHTTP("http://www.phpmyadmin.net/test/data", true) $this->object->checkHTTP("https://www.phpmyadmin.net/test/data", true)
); );
$this->assertFalse( $this->assertFalse(
$this->object->checkHTTP("http://www.phpmyadmin.net/test/nothing") $this->object->checkHTTP("https://www.phpmyadmin.net/test/nothing")
);
// Use rate limit API as it's not subject to rate limiting
$this->assertContains(
'"resources"',
$this->object->checkHTTP("https://api.github.com/rate_limit", true)
); );
} }