Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
b156313c09
41
ChangeLog
41
ChangeLog
@ -24,7 +24,46 @@ phpMyAdmin - ChangeLog
|
||||
- issue #12218 Allow to specify further parameters for control connection
|
||||
- issue #12162 Show charset for each table on Database structure page
|
||||
|
||||
4.6.4 (not yet released)
|
||||
4.6.5 (not yet released)
|
||||
|
||||
4.6.4 (2016-08-16)
|
||||
- issue [security] Weaknesses with cookie encryption, see PMASA-2016-29
|
||||
- issue [security] Improve session cookie code for openid.php and signon.php example files
|
||||
- issue [security] Full path disclosure in openid.php and signon.php example files
|
||||
- issue [security] Multiple XSS vulnerabilities, see PMASA-2016-30
|
||||
- issue [security] Multiple XSS vulnerabilities, see PMASA-2016-31
|
||||
- issue [security] Unsafe generation of BlowfishSecret (when not supplied by the user)
|
||||
- issue [security] Referrer leak when phpinfo is enabled
|
||||
- issue [security] PHP code injection, see PMASA-2016-32
|
||||
- issue [security] Full path disclosure, see PMASA-2016-33
|
||||
- issue [security] SQL injection attack, see PMASA-2016-34
|
||||
- issue [security] Local file exposure through LOAD DATA LOCAL INFILE, see PMASA-2016-35
|
||||
- issue [security] Local file exposure through symlinks with UploadDir, see PMASA-2016-36
|
||||
- issue [security] Path traversal with SaveDir and UploadDir, see PMASA-2016-37
|
||||
- issue [security] Multiple XSS vulnerabilities, see PMASA-2016-38
|
||||
- issue [security] SQL injection vulnerability as control user, see PMASA-2016-39
|
||||
- issue [security] SQL injection vulnerability, see PMASA-2016-40
|
||||
- issue [security] Denial-of-service attack through transformation feature, see PMASA-2016-41
|
||||
- issue [security] SQL injection vulnerability as control user, see PMASA-2016-42
|
||||
- issue [security] Verify data before unserializing, see PMASA-2016-43
|
||||
- issue [security] Use HTTPS for wiki links
|
||||
- issue Remove Swekey support
|
||||
- issue [security] SSRF in setup script, see PMASA-2016-44
|
||||
- issue [security] Denial-of-service attack with $cfg['AllowArbitraryServer'] = true and persistent connections, see PMASA-2016-45
|
||||
- issue [security] Improve SSL certificate handling
|
||||
- issue [security] Fix full path disclosure in debugging code
|
||||
- issue [security] Possible circumvention of IP-based allow/deny rules with IPv6 and proxy server, see PMASA-2016-47
|
||||
- issue [security] Detect if user is logged in, see PMASA-2016-48
|
||||
- issue [security] Bypass URL redirection protection, see PMASA-2016-49
|
||||
- issue [security] Referrer leak, see PMASA-2016-50
|
||||
- issue [security] Reflected File Download, see PMASA-2016-51
|
||||
- issue [security] ArbitraryServerRegexp bypass, see PMASA-2016-52
|
||||
- issue [security] Denial-of-service attack by entering long password, see PMASA-2016-53
|
||||
- issue [security] Remote code execution vulnerability when running as CGI, see PMASA-2016-054
|
||||
- issue [security] Administrators could trigger SQL injection attack against users
|
||||
- issue [security] Denial-of-service attack when PHP uses dbase extension, see PMASA-2016-55
|
||||
- issue [security] Remove tode execution vulnerability when PHP uses dbase extension, see PMASA-2016-56
|
||||
- issue [security] Denial-of-service attack by using for loops, see PMASA-2016-46
|
||||
- issue Include X-Robots-Tag header in responses
|
||||
- issue Enforce numeric field length when creating table
|
||||
- issue Fixed invalid Content-Length in some HTTP responses
|
||||
|
||||
@ -13,6 +13,7 @@ require 'libraries/common.inc.php';
|
||||
|
||||
$response = PMA\libraries\Response::getInstance();
|
||||
$response->disable();
|
||||
$response->getHeader()->sendHttpHeaders();
|
||||
|
||||
$filename = CHANGELOG_FILE;
|
||||
|
||||
@ -155,6 +156,7 @@ echo '</pre>';
|
||||
var links = document.getElementsByTagName("a");
|
||||
for(var i = 0; i < links.length; i++) {
|
||||
links[i].target = "_blank";
|
||||
links[i].rel = "noopener noreferrer";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
/**
|
||||
* This is needed for cookie based authentication to encrypt password in
|
||||
* cookie
|
||||
* cookie. Needs to be 32 chars long.
|
||||
*/
|
||||
$cfg['blowfish_secret'] = ''; /* YOU MUST FILL IN THIS FOR COOKIE AUTH! */
|
||||
|
||||
|
||||
@ -1631,7 +1631,10 @@ Cookie authentication options
|
||||
The "cookie" auth\_type uses AES algorithm to encrypt the password. If you
|
||||
are using the "cookie" auth\_type, enter here a random passphrase of your
|
||||
choice. It will be used internally by the AES algorithm: you won’t be
|
||||
prompted for this passphrase. There is no maximum length for this secret.
|
||||
prompted for this passphrase.
|
||||
|
||||
The secret should be 32 characters long. Using shorter will lead to weaker security
|
||||
of encrypted cookies, using longer will cause no harm.
|
||||
|
||||
.. note::
|
||||
|
||||
@ -1991,11 +1994,6 @@ Main panel
|
||||
You can additionally hide more information by using
|
||||
:config:option:`$cfg['Servers'][$i]['verbose']`.
|
||||
|
||||
.. config:option:: $cfg['ShowPhpInfo']
|
||||
|
||||
:type: boolean
|
||||
:default: false
|
||||
|
||||
.. config:option:: $cfg['ShowChgPassword']
|
||||
|
||||
:type: boolean
|
||||
@ -2006,18 +2004,11 @@ Main panel
|
||||
:type: boolean
|
||||
:default: true
|
||||
|
||||
Defines whether to display the :guilabel:`PHP information` and
|
||||
Defines whether to display the
|
||||
:guilabel:`Change password` links and form for creating database or not at
|
||||
the starting main (right) frame. This setting does not check MySQL commands
|
||||
entered directly.
|
||||
|
||||
Please note that to block the usage of ``phpinfo()`` in scripts, you have to
|
||||
put this in your :file:`php.ini`:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
disable_functions = phpinfo()
|
||||
|
||||
Also note that enabling the :guilabel:`Change password` link has no effect
|
||||
with config authentication mode: because of the hard coded password value
|
||||
in the configuration file, end users can't be allowed to change their
|
||||
@ -3087,7 +3078,6 @@ Developer
|
||||
Enable to let server present itself as demo server.
|
||||
This is used for `phpMyAdmin demo server <https://www.phpmyadmin.net/try>`_.
|
||||
|
||||
|
||||
.. _config-examples:
|
||||
|
||||
Examples
|
||||
|
||||
@ -288,7 +288,8 @@ simple configuration may look like this:
|
||||
|
||||
|
||||
<?php
|
||||
$cfg['blowfish_secret'] = 'ba17c1ec07d65003'; // use here a value of your choice
|
||||
// use here a value of your choice at least 32 chars long
|
||||
$cfg['blowfish_secret'] = '1{dd0`<Q),5XP_:R9UK%%8\"EEcyH#{o';
|
||||
|
||||
$i=0;
|
||||
$i++;
|
||||
|
||||
@ -74,11 +74,11 @@ function Die_error($e)
|
||||
|
||||
|
||||
/* Need to have cookie visible from parent directory */
|
||||
session_set_cookie_params(0, '/', '', false);
|
||||
session_set_cookie_params(0, '/', '', true, true);
|
||||
/* Create signon session */
|
||||
$session_name = 'SignonSession';
|
||||
session_name($session_name);
|
||||
session_start();
|
||||
@session_start();
|
||||
|
||||
// Determine realm and return_to
|
||||
$base = 'http';
|
||||
|
||||
@ -12,13 +12,13 @@
|
||||
*/
|
||||
|
||||
/* Need to have cookie visible from parent directory */
|
||||
session_set_cookie_params(0, '/', '', false);
|
||||
session_set_cookie_params(0, '/', '', true, true);
|
||||
/* Create signon session */
|
||||
$session_name = 'SignonSession';
|
||||
session_name($session_name);
|
||||
// Uncomment and change the following line to match your $cfg['SessionSavePath']
|
||||
//session_save_path('/foobar');
|
||||
session_start();
|
||||
@session_start();
|
||||
|
||||
/* Was data posted? */
|
||||
if (isset($_POST['user'])) {
|
||||
@ -31,7 +31,7 @@ if (isset($_POST['user'])) {
|
||||
$_SESSION['PMA_single_signon_cfgupdate'] = array('verbose' => 'Signon test');
|
||||
$id = session_id();
|
||||
/* Close that session */
|
||||
session_write_close();
|
||||
@session_write_close();
|
||||
/* Redirect to phpMyAdmin (should use absolute URL here!) */
|
||||
header('Location: ../index.php');
|
||||
} else {
|
||||
|
||||
14
import.php
14
import.php
@ -11,6 +11,11 @@ use PMA\libraries\File;
|
||||
use PMA\libraries\URL;
|
||||
use PMA\libraries\Bookmark;
|
||||
|
||||
/* Enable LOAD DATA LOCAL INFILE for LDI plugin */
|
||||
if (isset($_POST['format']) && $_POST['format'] == 'ldi') {
|
||||
define('PMA_ENABLE_LDI', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the variables sent or posted to this script and a core script
|
||||
*/
|
||||
@ -445,6 +450,15 @@ if (! empty($local_import_file) && ! empty($cfg['UploadDir'])) {
|
||||
$import_file = PMA\libraries\Util::userDir($cfg['UploadDir'])
|
||||
. $local_import_file;
|
||||
|
||||
/*
|
||||
* Do not allow symlinks to avoid security issues
|
||||
* (user can create symlink to file he can not access,
|
||||
* but phpMyAdmin can).
|
||||
*/
|
||||
if (@is_link($import_file)) {
|
||||
$import_file = 'none';
|
||||
}
|
||||
|
||||
} elseif (empty($import_file) || ! is_uploaded_file($import_file)) {
|
||||
$import_file = 'none';
|
||||
}
|
||||
|
||||
37
index.php
37
index.php
@ -321,7 +321,7 @@ if ($server > 0 && $GLOBALS['cfg']['ShowServerInfo']) {
|
||||
. ' </div>';
|
||||
}
|
||||
|
||||
if ($GLOBALS['cfg']['ShowServerInfo'] || $GLOBALS['cfg']['ShowPhpInfo']) {
|
||||
if ($GLOBALS['cfg']['ShowServerInfo']) {
|
||||
echo '<div class="group">';
|
||||
echo '<h2>' , __('Web server') , '</h2>';
|
||||
echo '<ul>';
|
||||
@ -361,15 +361,6 @@ if ($GLOBALS['cfg']['ShowServerInfo'] || $GLOBALS['cfg']['ShowPhpInfo']) {
|
||||
}
|
||||
}
|
||||
|
||||
if ($cfg['ShowPhpInfo']) {
|
||||
PMA_printListItem(
|
||||
__('Show PHP information'),
|
||||
'li_phpinfo',
|
||||
'phpinfo.php' . $common_url_query,
|
||||
null,
|
||||
'_blank'
|
||||
);
|
||||
}
|
||||
echo ' </ul>';
|
||||
echo ' </div>';
|
||||
}
|
||||
@ -523,15 +514,23 @@ if ($GLOBALS['cfg']['LoginCookieStore'] != 0
|
||||
/**
|
||||
* Check if user does not have defined blowfish secret and it is being used.
|
||||
*/
|
||||
if (! empty($_SESSION['encryption_key'])
|
||||
&& empty($GLOBALS['cfg']['blowfish_secret'])
|
||||
) {
|
||||
trigger_error(
|
||||
__(
|
||||
'The configuration file now needs a secret passphrase (blowfish_secret).'
|
||||
),
|
||||
E_USER_WARNING
|
||||
);
|
||||
if (! empty($_SESSION['encryption_key'])) {
|
||||
if (empty($GLOBALS['cfg']['blowfish_secret'])) {
|
||||
trigger_error(
|
||||
__(
|
||||
'The configuration file now needs a secret passphrase (blowfish_secret).'
|
||||
),
|
||||
E_USER_WARNING
|
||||
);
|
||||
}
|
||||
if (strlen($GLOBALS['cfg']['blowfish_secret']) < 32) {
|
||||
trigger_error(
|
||||
__(
|
||||
'The secret passphrase in configuration (blowfish_secret) is too short.'
|
||||
),
|
||||
E_USER_WARNING
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -4117,7 +4117,16 @@ AJAX.registerOnload('functions.js', function () {
|
||||
* Load version information asynchronously.
|
||||
*/
|
||||
if ($('li.jsversioncheck').length > 0) {
|
||||
$.getJSON('version_check.php', {'server' : PMA_commonParams.get('server')}, PMA_current_version);
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url: 'version_check.php',
|
||||
method: "POST",
|
||||
data: {
|
||||
"server": PMA_commonParams.get('server'),
|
||||
"token": PMA_commonParams.get('token'),
|
||||
},
|
||||
success: PMA_current_version
|
||||
});
|
||||
}
|
||||
|
||||
if ($('#is_git_revision').length > 0) {
|
||||
|
||||
@ -23,7 +23,7 @@ function setDropdownValues($dropdown, values, selectedValue) {
|
||||
// add an empty string to the beginning for empty selection
|
||||
values.unshift('');
|
||||
$.each(values, function () {
|
||||
optionsAsString += "<option value='" + this + "'" + (selectedValue == this ? " selected='selected'" : "") + ">" + this + "</option>";
|
||||
optionsAsString += "<option value='" + escapeHtml(this) + "'" + (selectedValue == this ? " selected='selected'" : "") + ">" + escapeHtml(this) + "</option>";
|
||||
});
|
||||
$dropdown.append($(optionsAsString));
|
||||
}
|
||||
|
||||
@ -356,10 +356,10 @@ class DbSearch
|
||||
$html_output .= '<td><a name="delete_search" class="ajax" href="'
|
||||
. $delete_result_path . '" onclick="deleteResult(\''
|
||||
. $delete_result_path . '\' , \''
|
||||
. sprintf(
|
||||
. Sanitize::escapeJsString(sprintf(
|
||||
__('Delete the matches for the %s table?'),
|
||||
htmlspecialchars($each_table)
|
||||
)
|
||||
))
|
||||
. '\');return false;">'
|
||||
. __('Delete') . '</a></td>';
|
||||
} else {
|
||||
|
||||
@ -117,12 +117,17 @@ class Error extends Message
|
||||
{
|
||||
$result = array();
|
||||
|
||||
$members = array('file', 'line', 'function', 'class', 'type');
|
||||
$members = array('line', 'function', 'class', 'type');
|
||||
|
||||
foreach ($backtrace as $idx => $step) {
|
||||
/* Create new backtrace entry */
|
||||
$result[$idx] = array();
|
||||
|
||||
/* Make path relative */
|
||||
if (isset($step['file'])) {
|
||||
$result[$idx]['file'] = Error::relPath($step['file']);
|
||||
}
|
||||
|
||||
/* Store members we want */
|
||||
foreach ($members as $name) {
|
||||
if (isset($step[$name])) {
|
||||
|
||||
@ -420,6 +420,11 @@ class File
|
||||
$this->setName(
|
||||
Util::userDir($GLOBALS['cfg']['UploadDir']) . PMA_securePath($name)
|
||||
);
|
||||
if (@is_link($this->getName())) {
|
||||
$this->_error_message = __('File is a symbolic link');
|
||||
$this->setName(null);
|
||||
return false;
|
||||
}
|
||||
if (! $this->isReadable()) {
|
||||
$this->_error_message = Message::error(__('File could not be read!'));
|
||||
$this->setName(null);
|
||||
|
||||
@ -35,7 +35,7 @@ class Logging
|
||||
@syslog(
|
||||
LOG_WARNING,
|
||||
'user denied: ' . $user . ' (' . $status . ') from ' .
|
||||
$_SERVER['REMOTE_ADDR']
|
||||
PMA_getIp()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ class RecentFavoriteTable
|
||||
// Read from phpMyAdmin database, if recent tables is not in session
|
||||
$sql_query
|
||||
= " SELECT `tables` FROM " . $this->_getPmaTable() .
|
||||
" WHERE `username` = '" . $GLOBALS['cfg']['Server']['user'] . "'";
|
||||
" WHERE `username` = '" . Util::sqlAddSlashes($GLOBALS['cfg']['Server']['user']) . "'";
|
||||
|
||||
$return = array();
|
||||
$result = PMA_queryAsControlUser($sql_query, false);
|
||||
@ -121,7 +121,7 @@ class RecentFavoriteTable
|
||||
$username = $GLOBALS['cfg']['Server']['user'];
|
||||
$sql_query
|
||||
= " REPLACE INTO " . $this->_getPmaTable() . " (`username`, `tables`)" .
|
||||
" VALUES ('" . $username . "', '"
|
||||
" VALUES ('" . Util::sqlAddSlashes($username) . "', '"
|
||||
. Util::sqlAddSlashes(
|
||||
json_encode($this->_tables)
|
||||
) . "')";
|
||||
|
||||
@ -60,6 +60,13 @@ class Response
|
||||
* @var bool
|
||||
*/
|
||||
private $_isAjax;
|
||||
/**
|
||||
* Whether response object is disabled
|
||||
*
|
||||
* @access private
|
||||
* @var bool
|
||||
*/
|
||||
private $_isDisabled;
|
||||
/**
|
||||
* Whether we are servicing an ajax request for a page
|
||||
* that was fired using the generic page handler in JS.
|
||||
@ -102,6 +109,7 @@ class Response
|
||||
$this->_isSuccess = true;
|
||||
$this->_isAjax = false;
|
||||
$this->_isAjaxPage = false;
|
||||
$this->_isDisabled = false;
|
||||
if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true) {
|
||||
$this->_isAjax = true;
|
||||
}
|
||||
@ -174,6 +182,7 @@ class Response
|
||||
{
|
||||
$this->_header->disable();
|
||||
$this->_footer->disable();
|
||||
$this->_isDisabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -277,6 +286,12 @@ class Response
|
||||
*/
|
||||
private function _ajaxResponse()
|
||||
{
|
||||
/* Avoid wrapping in case we're disabled */
|
||||
if ($this->_isDisabled) {
|
||||
echo $this->_getDisplay();
|
||||
return;
|
||||
}
|
||||
|
||||
if (! isset($this->_JSON['message'])) {
|
||||
$this->_JSON['message'] = $this->_getDisplay();
|
||||
} else if ($this->_JSON['message'] instanceof Message) {
|
||||
|
||||
@ -64,6 +64,9 @@ class Sanitize
|
||||
$target = '';
|
||||
if (! empty($found[3])) {
|
||||
$target = ' target="' . $found[3] . '"';
|
||||
if ($found[3] == '_blank') {
|
||||
$target .= ' rel="noopener noreferrer"';
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct url */
|
||||
|
||||
@ -1460,7 +1460,7 @@ class Table
|
||||
|
||||
// Read from phpMyAdmin database
|
||||
$sql_query = " SELECT `prefs` FROM " . $pma_table
|
||||
. " WHERE `username` = '" . $GLOBALS['cfg']['Server']['user'] . "'"
|
||||
. " WHERE `username` = '" . Util::sqlAddSlashes($GLOBALS['cfg']['Server']['user']) . "'"
|
||||
. " AND `db_name` = '" . Util::sqlAddSlashes($this->_db_name) . "'"
|
||||
. " AND `table_name` = '" . Util::sqlAddSlashes($this->_name) . "'";
|
||||
|
||||
@ -1488,7 +1488,7 @@ class Table
|
||||
$username = $GLOBALS['cfg']['Server']['user'];
|
||||
$sql_query = " REPLACE INTO " . $pma_table
|
||||
. " (username, db_name, table_name, prefs) VALUES ('"
|
||||
. $username . "', '" . $secureDbName
|
||||
. Util::sqlAddSlashes($username) . "', '" . $secureDbName
|
||||
. "', '" . Util::sqlAddSlashes($this->_name) . "', '"
|
||||
. Util::sqlAddSlashes(json_encode($this->uiprefs)) . "')";
|
||||
|
||||
|
||||
@ -2687,7 +2687,7 @@ class Util
|
||||
$dir .= '/';
|
||||
}
|
||||
|
||||
return str_replace('%u', $GLOBALS['cfg']['Server']['user'], $dir);
|
||||
return str_replace('%u', PMA_securePath($GLOBALS['cfg']['Server']['user']), $dir);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -51,20 +51,7 @@ class VersionInformation
|
||||
session_write_close();
|
||||
}
|
||||
$file = 'https://www.phpmyadmin.net/home_page/version.json';
|
||||
if (ini_get('allow_url_fopen')) {
|
||||
$context = array(
|
||||
'http' => array(
|
||||
'request_fulluri' => true,
|
||||
'timeout' => $connection_timeout,
|
||||
)
|
||||
);
|
||||
$context = Util::handleContext($context);
|
||||
$response = file_get_contents(
|
||||
$file,
|
||||
false,
|
||||
stream_context_create($context)
|
||||
);
|
||||
} else if (function_exists('curl_init')) {
|
||||
if (function_exists('curl_init')) {
|
||||
$curl_handle = curl_init($file);
|
||||
if ($curl_handle === false) {
|
||||
return null;
|
||||
@ -86,6 +73,19 @@ class VersionInformation
|
||||
$connection_timeout
|
||||
);
|
||||
$response = curl_exec($curl_handle);
|
||||
} else if (ini_get('allow_url_fopen')) {
|
||||
$context = array(
|
||||
'http' => array(
|
||||
'request_fulluri' => true,
|
||||
'timeout' => $connection_timeout,
|
||||
)
|
||||
);
|
||||
$context = Util::handleContext($context);
|
||||
$response = file_get_contents(
|
||||
$file,
|
||||
false,
|
||||
stream_context_create($context)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -292,7 +292,6 @@ $goto_whitelist = array(
|
||||
'index.php',
|
||||
'pdf_pages.php',
|
||||
'pdf_schema.php',
|
||||
//'phpinfo.php',
|
||||
'server_binlog.php',
|
||||
'server_collations.php',
|
||||
'server_databases.php',
|
||||
|
||||
@ -1038,13 +1038,6 @@ $cfg['NavigationTreeShowEvents'] = true;
|
||||
*/
|
||||
$cfg['ShowStats'] = true;
|
||||
|
||||
/**
|
||||
* show PHP info link
|
||||
*
|
||||
* @global boolean $cfg['ShowPhpInfo']
|
||||
*/
|
||||
$cfg['ShowPhpInfo'] = false;
|
||||
|
||||
/**
|
||||
* show MySQL server and web server information
|
||||
*
|
||||
|
||||
@ -216,10 +216,22 @@ class ServerConfigChecks
|
||||
$blowfishSecret, $cookieAuthServer, $blowfishSecretSet
|
||||
) {
|
||||
if ($cookieAuthServer && $blowfishSecret === null) {
|
||||
$blowfishSecret = uniqid('', true);
|
||||
$blowfishSecret = '';
|
||||
if (! function_exists('openssl_random_pseudo_bytes')) {
|
||||
$random_func = 'phpseclib\\Crypt\\Random::string';
|
||||
} else {
|
||||
$random_func = 'openssl_random_pseudo_bytes';
|
||||
}
|
||||
while (strlen($blowfishSecret) < 32) {
|
||||
$byte = $random_func(1);
|
||||
// We want only ASCII chars
|
||||
if (ord($byte) > 32 && ord($byte) < 127) {
|
||||
$blowfishSecret .= $byte;
|
||||
}
|
||||
}
|
||||
|
||||
$blowfishSecretSet = true;
|
||||
$this->cfg->set('blowfish_secret', $blowfishSecret);
|
||||
return array($blowfishSecret, $blowfishSecretSet);
|
||||
}
|
||||
return array($blowfishSecret, $blowfishSecretSet);
|
||||
}
|
||||
@ -331,10 +343,10 @@ class ServerConfigChecks
|
||||
} else {
|
||||
$blowfishWarnings = array();
|
||||
// check length
|
||||
if (mb_strlen($blowfishSecret) < 8) {
|
||||
if (strlen($blowfishSecret) < 32) {
|
||||
// too short key
|
||||
$blowfishWarnings[] = __(
|
||||
'Key is too short, it should have at least 8 characters.'
|
||||
'Key is too short, it should have at least 32 characters.'
|
||||
);
|
||||
}
|
||||
// check used characters
|
||||
|
||||
@ -183,6 +183,7 @@ class Validator
|
||||
) {
|
||||
// static::testPHPErrorMsg();
|
||||
$error = null;
|
||||
$host = PMA_sanitizeMySQLHost($host);
|
||||
|
||||
if (DatabaseInterface::checkDbExtension('mysqli')) {
|
||||
$socket = empty($socket) || $connect_type == 'tcp' ? null : $socket;
|
||||
|
||||
@ -871,11 +871,6 @@ $strConfigShowFunctionFields_desc = __(
|
||||
$strConfigShowFunctionFields_name = __('Show function fields');
|
||||
$strConfigShowHint_desc = __('Whether to show hint or not.');
|
||||
$strConfigShowHint_name = __('Show hint');
|
||||
$strConfigShowPhpInfo_desc = __(
|
||||
'Shows link to [a@https://php.net/manual/function.phpinfo.php]phpinfo()[/a] ' .
|
||||
'output.'
|
||||
);
|
||||
$strConfigShowPhpInfo_name = __('Show phpinfo() link');
|
||||
$strConfigShowServerInfo_name = __('Show detailed MySQL server information');
|
||||
$strConfigShowSQL_desc = __(
|
||||
'Defines whether SQL queries generated by phpMyAdmin should be displayed.'
|
||||
|
||||
@ -204,7 +204,6 @@ $forms['Main_panel']['Startup'] = array(
|
||||
'ShowCreateDb',
|
||||
'ShowStats',
|
||||
'ShowServerInfo',
|
||||
'ShowPhpInfo',
|
||||
'ShowChgPassword');
|
||||
$forms['Main_panel']['DbStructure'] = array(
|
||||
'ShowDbStructureCharset',
|
||||
|
||||
@ -501,11 +501,6 @@ function PMA_sendHeaderLocation($uri, $use_refresh = false)
|
||||
|
||||
session_write_close();
|
||||
if ($response->headersSent()) {
|
||||
if (function_exists('debug_print_backtrace')) {
|
||||
echo '<pre>';
|
||||
debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
|
||||
echo '</pre>';
|
||||
}
|
||||
trigger_error(
|
||||
'PMA_sendHeaderLocation called when headers are already sent!',
|
||||
E_USER_ERROR
|
||||
@ -735,6 +730,10 @@ function PMA_linkURL($url)
|
||||
function PMA_isAllowedDomain($url)
|
||||
{
|
||||
$arr = parse_url($url);
|
||||
// Avoid URLs without hostname or with credentials
|
||||
if (empty($arr['host']) || ! empty($arr['user']) || ! empty($arr['pass'])) {
|
||||
return false;
|
||||
}
|
||||
$domain = $arr["host"];
|
||||
$domainWhiteList = array(
|
||||
/* Include current domain */
|
||||
@ -953,6 +952,50 @@ function PMA_checkExtensions()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the "true" IP address of the current user
|
||||
*
|
||||
* @return string the ip of the user
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
function PMA_getIp()
|
||||
{
|
||||
/* Get the address of user */
|
||||
if (empty($_SERVER['REMOTE_ADDR'])) {
|
||||
/* We do not know remote IP */
|
||||
return false;
|
||||
}
|
||||
|
||||
$direct_ip = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
/* Do we trust this IP as a proxy? If yes we will use it's header. */
|
||||
if (!isset($GLOBALS['cfg']['TrustedProxies'][$direct_ip])) {
|
||||
/* Return true IP */
|
||||
return $direct_ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse header in form:
|
||||
* X-Forwarded-For: client, proxy1, proxy2
|
||||
*/
|
||||
// Get header content
|
||||
$value = PMA_getenv($GLOBALS['cfg']['TrustedProxies'][$direct_ip]);
|
||||
// Grab first element what is client adddress
|
||||
$value = explode(',', $value)[0];
|
||||
// checks that the header contains only one IP address,
|
||||
$is_ip = filter_var($value, FILTER_VALIDATE_IP);
|
||||
|
||||
if ($is_ip !== false) {
|
||||
// True IP behind a proxy
|
||||
return $value;
|
||||
}
|
||||
|
||||
// We could not parse header
|
||||
return false;
|
||||
} // end of the 'PMA_getIp()' function
|
||||
|
||||
|
||||
/* Compatibility with PHP < 5.6 */
|
||||
if(! function_exists('hash_equals')) {
|
||||
|
||||
@ -970,3 +1013,135 @@ if(! function_exists('hash_equals')) {
|
||||
return ! $ret;
|
||||
}
|
||||
}
|
||||
/* Compatibility with PHP < 5.1 or PHP without hash extension */
|
||||
if (! function_exists('hash_hmac')) {
|
||||
function hash_hmac($algo, $data, $key, $raw_output = false)
|
||||
{
|
||||
$algo = strtolower($algo);
|
||||
$pack = 'H'.strlen($algo('test'));
|
||||
$size = 64;
|
||||
$opad = str_repeat(chr(0x5C), $size);
|
||||
$ipad = str_repeat(chr(0x36), $size);
|
||||
|
||||
if (strlen($key) > $size) {
|
||||
$key = str_pad(pack($pack, $algo($key)), $size, chr(0x00));
|
||||
} else {
|
||||
$key = str_pad($key, $size, chr(0x00));
|
||||
}
|
||||
|
||||
for ($i = 0; $i < strlen($key) - 1; $i++) {
|
||||
$opad[$i] = $opad[$i] ^ $key[$i];
|
||||
$ipad[$i] = $ipad[$i] ^ $key[$i];
|
||||
}
|
||||
|
||||
$output = $algo($opad.pack($pack, $algo($ipad.$data)));
|
||||
|
||||
return ($raw_output) ? pack($pack, $output) : $output;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes MySQL hostname
|
||||
*
|
||||
* * strips p: prefix
|
||||
*
|
||||
* @param string $name User given hostname
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function PMA_sanitizeMySQLHost($name)
|
||||
{
|
||||
if (strtolower(substr($name, 0, 2)) == 'p:') {
|
||||
return substr($name, 2);
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe unserializer wrapper
|
||||
*
|
||||
* It does not unserialize data containing objects
|
||||
*
|
||||
* @param string $data Data to unserialize
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function PMA_safeUnserialize($data)
|
||||
{
|
||||
if (! is_string($data)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* validate serialized data */
|
||||
$length = strlen($data);
|
||||
$depth = 0;
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$value = $data[$i];
|
||||
|
||||
switch ($value)
|
||||
{
|
||||
case '}':
|
||||
/* end of array */
|
||||
if ($depth <= 0) {
|
||||
return null;
|
||||
}
|
||||
$depth--;
|
||||
break;
|
||||
case 's':
|
||||
/* string */
|
||||
// parse sting length
|
||||
$strlen = intval($data[$i + 2]);
|
||||
// string start
|
||||
$i = strpos($data, ':', $i + 2);
|
||||
if ($i === false) {
|
||||
return null;
|
||||
}
|
||||
// skip string, quotes and ;
|
||||
$i += 2 + $strlen + 1;
|
||||
if ($data[$i] != ';') {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
case 'i':
|
||||
case 'd':
|
||||
/* bool, integer or double */
|
||||
// skip value to sepearator
|
||||
$i = strpos($data, ';', $i);
|
||||
if ($i === false) {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
/* array */
|
||||
// find array start
|
||||
$i = strpos($data, '{', $i);
|
||||
if ($i === false) {
|
||||
return null;
|
||||
}
|
||||
// remember nesting
|
||||
$depth++;
|
||||
break;
|
||||
case 'N':
|
||||
/* null */
|
||||
// skip to end
|
||||
$i = strpos($data, ';', $i);
|
||||
if ($i === false) {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* any other elements are not wanted */
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// check unterminated arrays
|
||||
if ($depth > 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return unserialize($data);
|
||||
}
|
||||
|
||||
@ -446,18 +446,19 @@ function PMA_getTableCreationQuery($db, $table)
|
||||
function PMA_getNumberOfFieldsFromRequest()
|
||||
{
|
||||
if (isset($_REQUEST['submit_num_fields'])) { // adding new fields
|
||||
$num_fields = $_REQUEST['orig_num_fields'] + $_REQUEST['added_fields'];
|
||||
$num_fields = intval($_REQUEST['orig_num_fields']) + intval($_REQUEST['added_fields']);
|
||||
} elseif (isset($_REQUEST['orig_num_fields'])) { // retaining existing fields
|
||||
$num_fields = $_REQUEST['orig_num_fields'];
|
||||
$num_fields = intval($_REQUEST['orig_num_fields']);
|
||||
} elseif (isset($_REQUEST['num_fields'])
|
||||
&& intval($_REQUEST['num_fields']) > 0
|
||||
) { // new table with specified number of fields
|
||||
$num_fields = (int) $_REQUEST['num_fields'];
|
||||
$num_fields = intval($_REQUEST['num_fields']);
|
||||
} else { // new table with unspecified number of fields
|
||||
$num_fields = 4;
|
||||
}
|
||||
|
||||
return $num_fields;
|
||||
// Limit to 4096 fields (MySQL maximal value)
|
||||
return min($num_fields, 4096);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -90,7 +90,7 @@ function PMA_getPageIdsAndNames($db)
|
||||
|
||||
$result = array();
|
||||
while ($curr_page = $GLOBALS['dbi']->fetchAssoc($page_rs)) {
|
||||
$result[$curr_page['page_nr']] = $curr_page['page_descr'];
|
||||
$result[intval($curr_page['page_nr'])] = $curr_page['page_descr'];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
@ -115,10 +115,12 @@ class DBIMysql implements DBIExtension
|
||||
|
||||
$client_flags = 0;
|
||||
|
||||
// always use CLIENT_LOCAL_FILES as defined in mysql_com.h
|
||||
// for the case where the client library was not compiled
|
||||
// with --enable-local-infile
|
||||
$client_flags |= 128;
|
||||
if (defined('PMA_ENABLE_LDI')) {
|
||||
// use CLIENT_LOCAL_FILES as defined in mysql_com.h
|
||||
// for the case where the client library was not compiled
|
||||
// with --enable-local-infile
|
||||
$client_flags |= 128;
|
||||
}
|
||||
|
||||
/* Optionally compress connection */
|
||||
if (defined('MYSQL_CLIENT_COMPRESS') && $server['compress']) {
|
||||
|
||||
@ -129,7 +129,11 @@ class DBIMysqli implements DBIExtension
|
||||
|
||||
$link = mysqli_init();
|
||||
|
||||
mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, true);
|
||||
if (defined('PMA_ENABLE_LDI')) {
|
||||
mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, true);
|
||||
} else {
|
||||
mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, false);
|
||||
}
|
||||
|
||||
$client_flags = 0;
|
||||
|
||||
|
||||
@ -252,7 +252,7 @@ function PMA_getOptionsForExportTemplates($export_type)
|
||||
. PMA\libraries\Util::backquote($cfgRelation['export_templates'])
|
||||
. " WHERE `username` = "
|
||||
. "'" . PMA\libraries\Util::sqlAddSlashes($GLOBALS['cfg']['Server']['user'])
|
||||
. "' AND `export_type` = '" . $export_type . "'"
|
||||
. "' AND `export_type` = '" . PMA\libraries\Util::sqlAddSlashes($export_type) . "'"
|
||||
. " ORDER BY `template_name`;";
|
||||
|
||||
$result = PMA_queryAsControlUser($query);
|
||||
|
||||
@ -37,7 +37,7 @@ function PMA_printGitRevision()
|
||||
'https://github.com/phpmyadmin/phpmyadmin/commit/'
|
||||
. $GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_COMMITHASH')
|
||||
)
|
||||
. '" target="_blank">' . $commit_hash . '</a>';
|
||||
. '" rel="noopener noreferrer" target="_blank">' . $commit_hash . '</a>';
|
||||
}
|
||||
|
||||
$branch = $GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_BRANCH');
|
||||
@ -47,7 +47,7 @@ function PMA_printGitRevision()
|
||||
'https://github.com/phpmyadmin/phpmyadmin/tree/'
|
||||
. $GLOBALS['PMA_Config']->get('PMA_VERSION_GIT_BRANCH')
|
||||
)
|
||||
. '" target="_blank">' . $branch . '</a>';
|
||||
. '" rel="noopener noreferrer" target="_blank">' . $branch . '</a>';
|
||||
}
|
||||
if ($branch !== false) {
|
||||
$branch = sprintf(__('%1$s from %2$s branch'), $commit_hash, $branch);
|
||||
|
||||
@ -182,7 +182,7 @@ class Pbxt extends StorageEngine
|
||||
. ' can be found on the %sPrimeBase XT Home Page%s.'
|
||||
),
|
||||
'<a href="' . PMA_linkURL('https://mariadb.com/kb/en/mariadb/about-pbxt/')
|
||||
. '" target="_blank">',
|
||||
. '" rel="noopener noreferrer" target="_blank">',
|
||||
'</a>'
|
||||
)
|
||||
. '</p>' . "\n";
|
||||
|
||||
@ -179,7 +179,24 @@ function PMA_sanitizeUrl($url)
|
||||
function PMA_sendErrorReport($report)
|
||||
{
|
||||
$data_string = json_encode($report);
|
||||
if (ini_get('allow_url_fopen')) {
|
||||
if (function_exists('curl_init')) {
|
||||
$curl_handle = curl_init(SUBMISSION_URL);
|
||||
if ($curl_handle === false) {
|
||||
return null;
|
||||
}
|
||||
$curl_handle = PMA\libraries\Util::configureCurl($curl_handle);
|
||||
curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, "POST");
|
||||
curl_setopt(
|
||||
$curl_handle, CURLOPT_HTTPHEADER,
|
||||
array('Expect:', 'Content-Type: application/json')
|
||||
);
|
||||
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $data_string);
|
||||
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
|
||||
$response = curl_exec($curl_handle);
|
||||
curl_close($curl_handle);
|
||||
|
||||
return $response;
|
||||
} else if (ini_get('allow_url_fopen')) {
|
||||
$context = array("http" =>
|
||||
array(
|
||||
'method' => 'POST',
|
||||
@ -196,26 +213,7 @@ function PMA_sendErrorReport($report)
|
||||
return $response;
|
||||
}
|
||||
|
||||
if (!function_exists('curl_init')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$curl_handle = curl_init(SUBMISSION_URL);
|
||||
if ($curl_handle === false) {
|
||||
return null;
|
||||
}
|
||||
$curl_handle = PMA\libraries\Util::configureCurl($curl_handle);
|
||||
curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, "POST");
|
||||
curl_setopt(
|
||||
$curl_handle, CURLOPT_HTTPHEADER,
|
||||
array('Expect:', 'Content-Type: application/json')
|
||||
);
|
||||
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $data_string);
|
||||
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
|
||||
$response = curl_exec($curl_handle);
|
||||
curl_close($curl_handle);
|
||||
|
||||
return $response;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -26,6 +26,7 @@ function PMA_getDirContent($dir, $expression = '')
|
||||
}
|
||||
while ($file = @readdir($handle)) {
|
||||
if (@is_file($dir . $file)
|
||||
&& ! @is_link($dir . $file)
|
||||
&& ($expression == '' || preg_match($expression, $file))
|
||||
) {
|
||||
$result[] = $file;
|
||||
|
||||
@ -129,11 +129,11 @@ abstract class GISGeometry
|
||||
. 'bound.extend(new OpenLayers.LonLat('
|
||||
. $scale_data['minX'] . ', ' . $scale_data['minY']
|
||||
. ').transform(new OpenLayers.Projection("EPSG:'
|
||||
. $srid . '"), map.getProjectionObject())); '
|
||||
. intval($srid) . '"), map.getProjectionObject())); '
|
||||
. 'bound.extend(new OpenLayers.LonLat('
|
||||
. $scale_data['maxX'] . ', ' . $scale_data['maxY']
|
||||
. ').transform(new OpenLayers.Projection("EPSG:'
|
||||
. $srid . '"), map.getProjectionObject()));';
|
||||
. intval($srid) . '"), map.getProjectionObject()));';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -222,7 +222,7 @@ abstract class GISGeometry
|
||||
// Extract coordinates of the point
|
||||
$cordinates = explode(" ", $point);
|
||||
|
||||
if (isset($cordinates[0]) && trim($cordinates[0]) != ''
|
||||
if (!empty($cordinates[0]) && trim($cordinates[0]) != ''
|
||||
&& isset($cordinates[1])
|
||||
&& trim($cordinates[1]) != ''
|
||||
) {
|
||||
@ -231,8 +231,8 @@ abstract class GISGeometry
|
||||
$y = $scale_data['height']
|
||||
- ($cordinates[1] - $scale_data['y']) * $scale_data['scale'];
|
||||
} else {
|
||||
$x = trim($cordinates[0]);
|
||||
$y = trim($cordinates[1]);
|
||||
$x = floatval(trim($cordinates[0]));
|
||||
$y = floatval(trim($cordinates[1]));
|
||||
}
|
||||
} else {
|
||||
$x = '';
|
||||
@ -394,6 +394,6 @@ abstract class GISGeometry
|
||||
{
|
||||
return '(new OpenLayers.Geometry.Point(' . $point[0] . ',' . $point[1] . '))'
|
||||
. '.transform(new OpenLayers.Projection("EPSG:'
|
||||
. $srid . '"), map.getProjectionObject())';
|
||||
. intval($srid) . '"), map.getProjectionObject())';
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,45 +7,6 @@
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets the "true" IP address of the current user
|
||||
*
|
||||
* @return string the ip of the user
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
function PMA_getIp()
|
||||
{
|
||||
/* Get the address of user */
|
||||
if (empty($_SERVER['REMOTE_ADDR'])) {
|
||||
/* We do not know remote IP */
|
||||
return false;
|
||||
}
|
||||
|
||||
$direct_ip = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
/* Do we trust this IP as a proxy? If yes we will use it's header. */
|
||||
if (!isset($GLOBALS['cfg']['TrustedProxies'][$direct_ip])) {
|
||||
/* Return true IP */
|
||||
return $direct_ip;
|
||||
}
|
||||
|
||||
$trusted_header_value
|
||||
= PMA_getenv($GLOBALS['cfg']['TrustedProxies'][$direct_ip]);
|
||||
$matches = array();
|
||||
// checks that the header contains only one IP address,
|
||||
$is_ip = filter_var($trusted_header_value, FILTER_VALIDATE_IP);
|
||||
|
||||
if ($is_ip !== false) {
|
||||
// True IP behind a proxy
|
||||
return $trusted_header_value;
|
||||
}
|
||||
|
||||
/* Return true IP */
|
||||
return $direct_ip;
|
||||
} // end of the 'PMA_getIp()' function
|
||||
|
||||
|
||||
/**
|
||||
* Matches for IPv4 or IPv6 addresses
|
||||
*
|
||||
|
||||
@ -175,7 +175,7 @@ class NavigationTree
|
||||
$query = "SELECT (COUNT(DB_first_level) DIV %d) * %d ";
|
||||
$query .= "from ( ";
|
||||
$query .= " SELECT distinct SUBSTRING_INDEX(SCHEMA_NAME, ";
|
||||
$query .= " '{$GLOBALS['cfg']['NavigationTreeDbSeparator']}', 1) ";
|
||||
$query .= " '" . Util::sqlAddSlashes($GLOBALS['cfg']['NavigationTreeDbSeparator']) . "', 1) ";
|
||||
$query .= " DB_first_level ";
|
||||
$query .= " FROM INFORMATION_SCHEMA.SCHEMATA ";
|
||||
$query .= " WHERE `SCHEMA_NAME` < '%s' ";
|
||||
|
||||
@ -434,7 +434,7 @@ class Node
|
||||
$query .= "SELECT DB_first_level ";
|
||||
$query .= "FROM ( ";
|
||||
$query .= "SELECT DISTINCT SUBSTRING_INDEX(SCHEMA_NAME, ";
|
||||
$query .= "'$dbSeparator', 1) ";
|
||||
$query .= "'" . Util::sqlAddSlashes($dbSeparator) . "', 1) ";
|
||||
$query .= "DB_first_level ";
|
||||
$query .= "FROM INFORMATION_SCHEMA.SCHEMATA ";
|
||||
$query .= $this->_getWhereClause('SCHEMA_NAME', $searchClause);
|
||||
@ -444,9 +444,9 @@ class Node
|
||||
$query .= ") t2 ";
|
||||
$query .= $this->_getWhereClause('SCHEMA_NAME', $searchClause);
|
||||
$query .= "AND 1 = LOCATE(CONCAT(DB_first_level, ";
|
||||
$query .= "'$dbSeparator'), ";
|
||||
$query .= "'" . Util::sqlAddSlashes($dbSeparator) . "'), ";
|
||||
$query .= "CONCAT(SCHEMA_NAME, ";
|
||||
$query .= "'$dbSeparator')) ";
|
||||
$query .= "'" . Util::sqlAddSlashes($dbSeparator) . "')) ";
|
||||
$query .= "ORDER BY SCHEMA_NAME ASC";
|
||||
$retval = $GLOBALS['dbi']->fetchResult($query);
|
||||
|
||||
|
||||
@ -691,7 +691,7 @@ class NodeDatabase extends Node
|
||||
. '<a href="navigation.php'
|
||||
. URL::getCommon()
|
||||
. '&showUnhideDialog=true'
|
||||
. '&dbName=' . urldecode($this->real_name) . '"'
|
||||
. '&dbName=' . urlencode($this->real_name) . '"'
|
||||
. ' class="showUnhide ajax">'
|
||||
. Util::getImage(
|
||||
'show.png',
|
||||
|
||||
@ -37,7 +37,10 @@ function PMA_getPlugin(
|
||||
if (is_file($plugins_dir . $file)) {
|
||||
//include_once $plugins_dir . $file;
|
||||
$fqnClass = 'PMA\\' . str_replace('/', '\\', $plugins_dir) . $class_name;
|
||||
return new $fqnClass;
|
||||
// check if class exists, could be caused by skip_import
|
||||
if (class_exists($fqnClass)) {
|
||||
return new $fqnClass;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@ -286,7 +286,7 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
// verify captcha status.
|
||||
$resp = $reCaptcha->verify(
|
||||
$_POST["g-recaptcha-response"],
|
||||
$_SERVER["REMOTE_ADDR"]
|
||||
PMA_getIp()
|
||||
);
|
||||
|
||||
// Check if the captcha entered is valid, if not stop the login.
|
||||
@ -324,7 +324,7 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$GLOBALS['pma_auth_server'] = $_REQUEST['pma_servername'];
|
||||
$GLOBALS['pma_auth_server'] = PMA_sanitizeMySQLHost($_REQUEST['pma_servername']);
|
||||
}
|
||||
PMA_secureSession();
|
||||
return true;
|
||||
@ -333,18 +333,8 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
// At the end, try to set the $GLOBALS['PHP_AUTH_USER']
|
||||
// and $GLOBALS['PHP_AUTH_PW'] variables from cookies
|
||||
|
||||
// servername
|
||||
if ($GLOBALS['cfg']['AllowArbitraryServer']
|
||||
&& ! empty($_COOKIE['pmaServer-' . $GLOBALS['server']])
|
||||
) {
|
||||
$GLOBALS['pma_auth_server']
|
||||
= $_COOKIE['pmaServer-' . $GLOBALS['server']];
|
||||
}
|
||||
|
||||
// check cookies
|
||||
if (empty($_COOKIE['pmaUser-' . $GLOBALS['server']])
|
||||
|| empty($_COOKIE['pma_iv-' . $GLOBALS['server']])
|
||||
) {
|
||||
if (empty($_COOKIE['pmaUser-' . $GLOBALS['server']])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -381,15 +371,26 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
}
|
||||
|
||||
// check password cookie
|
||||
if (empty($_COOKIE['pmaPass-' . $GLOBALS['server']])) {
|
||||
if (empty($_COOKIE['pmaAuth-' . $GLOBALS['server']])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$GLOBALS['PHP_AUTH_PW'] = $this->cookieDecrypt(
|
||||
$_COOKIE['pmaPass-' . $GLOBALS['server']],
|
||||
$this->_getSessionEncryptionSecret()
|
||||
$auth_data = json_decode(
|
||||
$this->cookieDecrypt(
|
||||
$_COOKIE['pmaAuth-' . $GLOBALS['server']],
|
||||
$this->_getSessionEncryptionSecret()
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
if (! is_array($auth_data) || ! isset($auth_data['password'])) {
|
||||
return false;
|
||||
}
|
||||
$GLOBALS['PHP_AUTH_PW'] = $auth_data['password'];
|
||||
if ($GLOBALS['cfg']['AllowArbitraryServer'] && ! empty($auth_data['server'])) {
|
||||
$GLOBALS['pma_auth_server'] = $auth_data['server'];
|
||||
}
|
||||
|
||||
$GLOBALS['from_cookie'] = true;
|
||||
|
||||
return true;
|
||||
@ -464,8 +465,6 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
{
|
||||
global $cfg;
|
||||
|
||||
$this->createIV();
|
||||
|
||||
// Name and password cookies need to be refreshed each time
|
||||
// Duration = one month for username
|
||||
$this->storeUsernameCookie($cfg['Server']['user']);
|
||||
@ -480,21 +479,6 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
// Set server cookies if required (once per session) and, in this case,
|
||||
// force reload to ensure the client accepts cookies
|
||||
if (! $GLOBALS['from_cookie']) {
|
||||
if ($GLOBALS['cfg']['AllowArbitraryServer']) {
|
||||
if (! empty($GLOBALS['pma_auth_server'])) {
|
||||
// Duration = one month for servername
|
||||
$GLOBALS['PMA_Config']->setCookie(
|
||||
'pmaServer-' . $GLOBALS['server'],
|
||||
$cfg['Server']['host']
|
||||
);
|
||||
} else {
|
||||
// Delete servername cookie
|
||||
$GLOBALS['PMA_Config']->removeCookie(
|
||||
'pmaServer-' . $GLOBALS['server']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// URL where to go:
|
||||
$redirect_url = './index.php';
|
||||
|
||||
@ -564,11 +548,15 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
*/
|
||||
public function storePasswordCookie($password)
|
||||
{
|
||||
$payload = array('password' => $password);
|
||||
if ($GLOBALS['cfg']['AllowArbitraryServer'] && ! empty($GLOBALS['pma_auth_server'])) {
|
||||
$payload['server'] = $GLOBALS['pma_auth_server'];
|
||||
}
|
||||
// Duration = as configured
|
||||
$GLOBALS['PMA_Config']->setCookie(
|
||||
'pmaPass-' . $GLOBALS['server'],
|
||||
'pmaAuth-' . $GLOBALS['server'],
|
||||
$this->cookieEncrypt(
|
||||
$password,
|
||||
json_encode($payload),
|
||||
$this->_getSessionEncryptionSecret()
|
||||
),
|
||||
null,
|
||||
@ -592,7 +580,7 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
global $conn_error;
|
||||
|
||||
// Deletes password cookie and displays the login form
|
||||
$GLOBALS['PMA_Config']->removeCookie('pmaPass-' . $GLOBALS['server']);
|
||||
$GLOBALS['PMA_Config']->removeCookie('pmaAuth-' . $GLOBALS['server']);
|
||||
|
||||
$conn_error = $this->getErrorMessage();
|
||||
|
||||
@ -615,8 +603,7 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
if (empty($GLOBALS['cfg']['blowfish_secret'])) {
|
||||
return $this->_getSessionEncryptionSecret();
|
||||
} else {
|
||||
// apply md5() to work around too long secrets (returns 32 characters)
|
||||
return md5($GLOBALS['cfg']['blowfish_secret']);
|
||||
return $GLOBALS['cfg']['blowfish_secret'];
|
||||
}
|
||||
}
|
||||
|
||||
@ -629,9 +616,9 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
{
|
||||
if (empty($_SESSION['encryption_key'])) {
|
||||
if (self::useOpenSSL()) {
|
||||
$_SESSION['encryption_key'] = openssl_random_pseudo_bytes(256);
|
||||
$_SESSION['encryption_key'] = openssl_random_pseudo_bytes(32);
|
||||
} else {
|
||||
$_SESSION['encryption_key'] = Crypt\Random::string(256);
|
||||
$_SESSION['encryption_key'] = Crypt\Random::string(32);
|
||||
}
|
||||
}
|
||||
return $_SESSION['encryption_key'];
|
||||
@ -647,6 +634,64 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
return ! class_exists('phpseclib\Crypt\Random');
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates secret in order to make it 16 bytes log
|
||||
*
|
||||
* This doesn't add any security, just ensures the secret
|
||||
* is long enough by copying it.
|
||||
*
|
||||
* @param string $secret Original secret
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function enlargeSecret($secret)
|
||||
{
|
||||
while (strlen($secret) < 16) {
|
||||
$secret .= $secret;
|
||||
}
|
||||
return substr($secret, 0, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives MAC secret from encryption secret.
|
||||
*
|
||||
* @param string $secret the secret
|
||||
*
|
||||
* @return string the MAC secret
|
||||
*/
|
||||
public function getMACSecret($secret)
|
||||
{
|
||||
// Grab first part, up to 16 chars
|
||||
// The MAC and AES secrets can overlap if original secret is short
|
||||
$length = strlen($secret);
|
||||
if ($length > 16) {
|
||||
return substr($secret, 0, 16);
|
||||
}
|
||||
return $this->enlargeSecret(
|
||||
$length == 1 ? $secret : substr($secret, 0, -1)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives AES secret from encryption secret.
|
||||
*
|
||||
* @param string $secret the secret
|
||||
*
|
||||
* @return string the AES secret
|
||||
*/
|
||||
public function getAESSecret($secret)
|
||||
{
|
||||
// Grab second part, up to 16 chars
|
||||
// The MAC and AES secrets can overlap if original secret is short
|
||||
$length = strlen($secret);
|
||||
if ($length > 16) {
|
||||
return substr($secret, -16);
|
||||
}
|
||||
return $this->enlargeSecret(
|
||||
$length == 1 ? $secret : substr($secret, 1)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encryption using openssl's AES or phpseclib's AES
|
||||
* (phpseclib uses mcrypt when it is available)
|
||||
@ -658,20 +703,31 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
*/
|
||||
public function cookieEncrypt($data, $secret)
|
||||
{
|
||||
$mac_secret = $this->getMACSecret($secret);
|
||||
$aes_secret = $this->getAESSecret($secret);
|
||||
$iv = $this->createIV();
|
||||
if (self::useOpenSSL()) {
|
||||
return openssl_encrypt(
|
||||
$result = openssl_encrypt(
|
||||
$data,
|
||||
'AES-128-CBC',
|
||||
$secret,
|
||||
0,
|
||||
$this->_cookie_iv
|
||||
$iv
|
||||
);
|
||||
} else {
|
||||
$cipher = new Crypt\AES(Crypt\Base::MODE_CBC);
|
||||
$cipher->setIV($this->_cookie_iv);
|
||||
$cipher->setKey($secret);
|
||||
return base64_encode($cipher->encrypt($data));
|
||||
$cipher->setIV($iv);
|
||||
$cipher->setKey($aes_secret);
|
||||
$result = base64_encode($cipher->encrypt($data));
|
||||
}
|
||||
$iv = base64_encode($iv);
|
||||
return json_encode(
|
||||
array(
|
||||
'iv' => $iv,
|
||||
'mac' => hash_hmac('sha1', $iv . $result, $mac_secret),
|
||||
'payload' => $result,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -681,33 +737,39 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
* @param string $encdata encrypted data
|
||||
* @param string $secret the secret
|
||||
*
|
||||
* @return string original data
|
||||
* @return string|bool original data, false on error
|
||||
*/
|
||||
public function cookieDecrypt($encdata, $secret)
|
||||
{
|
||||
if (is_null($this->_cookie_iv)) {
|
||||
$this->_cookie_iv = base64_decode(
|
||||
$_COOKIE['pma_iv-' . $GLOBALS['server']],
|
||||
true
|
||||
);
|
||||
$data = json_decode($encdata, true);
|
||||
|
||||
if (! is_array($data) || ! isset($data['mac']) || ! isset($data['iv']) || ! isset($data['payload'])
|
||||
|| ! is_string($data['mac']) || ! is_string($data['iv']) || ! is_string($data['payload'])
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (strlen($this->_cookie_iv) < $this->getIVSize()) {
|
||||
$this->createIV();
|
||||
|
||||
$mac_secret = $this->getMACSecret($secret);
|
||||
$aes_secret = $this->getAESSecret($secret);
|
||||
$newmac = hash_hmac('sha1', $data['iv'] . $data['payload'], $mac_secret);
|
||||
|
||||
if (! hash_equals($data['mac'], $newmac)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (self::useOpenSSL()) {
|
||||
return openssl_decrypt(
|
||||
$encdata,
|
||||
$data['payload'],
|
||||
'AES-128-CBC',
|
||||
$secret,
|
||||
0,
|
||||
$this->_cookie_iv
|
||||
base64_decode($data['iv'])
|
||||
);
|
||||
} else {
|
||||
$cipher = new Crypt\AES(Crypt\Base::MODE_CBC);
|
||||
$cipher->setIV($this->_cookie_iv);
|
||||
$cipher->setKey($secret);
|
||||
return $cipher->decrypt(base64_decode($encdata));
|
||||
$cipher->setIV(base64_decode($data['iv']));
|
||||
$cipher->setKey($aes_secret);
|
||||
return $cipher->decrypt(base64_decode($data['payload']));
|
||||
}
|
||||
}
|
||||
|
||||
@ -735,24 +797,26 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
*/
|
||||
public function createIV()
|
||||
{
|
||||
/* Testsuite shortcut only to allow predictable IV */
|
||||
if (! is_null($this->_cookie_iv)) {
|
||||
return $this->_cookie_iv;
|
||||
}
|
||||
if (self::useOpenSSL()) {
|
||||
$this->_cookie_iv = openssl_random_pseudo_bytes(
|
||||
return openssl_random_pseudo_bytes(
|
||||
$this->getIVSize()
|
||||
);
|
||||
} else {
|
||||
$this->_cookie_iv = Crypt\Random::string(
|
||||
return Crypt\Random::string(
|
||||
$this->getIVSize()
|
||||
);
|
||||
}
|
||||
$GLOBALS['PMA_Config']->setCookie(
|
||||
'pma_iv-' . $GLOBALS['server'],
|
||||
base64_encode($this->_cookie_iv)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets encryption IV to use
|
||||
*
|
||||
* This is for testing only!
|
||||
*
|
||||
* @param string $vector The IV
|
||||
*
|
||||
* @return void
|
||||
@ -784,17 +848,17 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
// -> delete password cookie(s)
|
||||
if ($GLOBALS['cfg']['LoginCookieDeleteAll']) {
|
||||
foreach ($GLOBALS['cfg']['Servers'] as $key => $val) {
|
||||
$GLOBALS['PMA_Config']->removeCookie('pmaPass-' . $key);
|
||||
if (isset($_COOKIE['pmaPass-' . $key])) {
|
||||
unset($_COOKIE['pmaPass-' . $key]);
|
||||
$GLOBALS['PMA_Config']->removeCookie('pmaAuth-' . $key);
|
||||
if (isset($_COOKIE['pmaAuth-' . $key])) {
|
||||
unset($_COOKIE['pmaAuth-' . $key]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$GLOBALS['PMA_Config']->removeCookie(
|
||||
'pmaPass-' . $GLOBALS['server']
|
||||
'pmaAuth-' . $GLOBALS['server']
|
||||
);
|
||||
if (isset($_COOKIE['pmaPass-' . $GLOBALS['server']])) {
|
||||
unset($_COOKIE['pmaPass-' . $GLOBALS['server']]);
|
||||
if (isset($_COOKIE['pmaAuth-' . $GLOBALS['server']])) {
|
||||
unset($_COOKIE['pmaAuth-' . $GLOBALS['server']]);
|
||||
}
|
||||
}
|
||||
parent::logOut();
|
||||
|
||||
@ -360,7 +360,7 @@ class ExportMediawiki extends ExportPlugin
|
||||
// see https://www.mediawiki.org/wiki/Help:Formatting
|
||||
$comment = $this->_exportCRLF();
|
||||
$comment .= '<!--' . $this->_exportCRLF();
|
||||
$comment .= $text . $this->_exportCRLF();
|
||||
$comment .= htmlspecialchars($text) . $this->_exportCRLF();
|
||||
$comment .= '-->' . str_repeat($this->_exportCRLF(), 2);
|
||||
|
||||
return $comment;
|
||||
|
||||
@ -65,6 +65,19 @@ class ExportPhparray extends ExportPlugin
|
||||
$this->properties = $exportPluginProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes end of comment from a string
|
||||
*
|
||||
* @param string $string String to replace
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function commentString($string)
|
||||
{
|
||||
return strtr($string, '*/', '-');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Outputs export header
|
||||
*
|
||||
@ -76,7 +89,7 @@ class ExportPhparray extends ExportPlugin
|
||||
'<?php' . $GLOBALS['crlf']
|
||||
. '/**' . $GLOBALS['crlf']
|
||||
. ' * Export to PHP Array plugin for PHPMyAdmin' . $GLOBALS['crlf']
|
||||
. ' * @version 0.2b' . $GLOBALS['crlf']
|
||||
. ' * @version ' . PMA_VERSION . $GLOBALS['crlf']
|
||||
. ' */' . $GLOBALS['crlf'] . $GLOBALS['crlf']
|
||||
);
|
||||
|
||||
@ -107,9 +120,9 @@ class ExportPhparray extends ExportPlugin
|
||||
$db_alias = $db;
|
||||
}
|
||||
PMA_exportOutputHandler(
|
||||
'//' . $GLOBALS['crlf']
|
||||
. '// Database ' . PMA\libraries\Util::backquote($db_alias)
|
||||
. $GLOBALS['crlf'] . '//' . $GLOBALS['crlf']
|
||||
'/**' . $GLOBALS['crlf']
|
||||
. ' * Database ' . $this->commentString(PMA\libraries\Util::backquote($db_alias))
|
||||
. $GLOBALS['crlf'] . ' */' . $GLOBALS['crlf']
|
||||
);
|
||||
|
||||
return true;
|
||||
@ -207,9 +220,9 @@ class ExportPhparray extends ExportPlugin
|
||||
$buffer = '';
|
||||
$record_cnt = 0;
|
||||
// Output table name as comment
|
||||
$buffer .= $crlf . '// '
|
||||
. PMA\libraries\Util::backquote($db_alias) . '.'
|
||||
. PMA\libraries\Util::backquote($table_alias) . $crlf;
|
||||
$buffer .= $crlf . '/* '
|
||||
. $this->commentString(PMA\libraries\Util::backquote($db_alias)) . '.'
|
||||
. $this->commentString(PMA\libraries\Util::backquote($table_alias)) . ' */' . $crlf;
|
||||
$buffer .= '$' . $tablefixed . ' = array(';
|
||||
|
||||
while ($record = $GLOBALS['dbi']->fetchRow($result)) {
|
||||
|
||||
@ -596,7 +596,16 @@ class ExportSql extends ExportPlugin
|
||||
&& $GLOBALS['sql_include_comments']
|
||||
) {
|
||||
// see https://dev.mysql.com/doc/refman/5.0/en/ansi-diff-comments.html
|
||||
return '--' . (empty($text) ? '' : ' ') . $text . $GLOBALS['crlf'];
|
||||
if (empty($text)) {
|
||||
return '--' . $GLOBALS['crlf'];
|
||||
} else {
|
||||
$lines = preg_split("/\\r\\n|\\r|\\n/", $text);
|
||||
$result = array();
|
||||
foreach ($lines as $line) {
|
||||
$result[] = '-- ' . $line . $GLOBALS['crlf'];
|
||||
}
|
||||
return implode('', $result);
|
||||
}
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
@ -1112,7 +1121,7 @@ class ExportSql extends ExportPlugin
|
||||
$dbNameColumn
|
||||
)
|
||||
. " = '" . Util::sqlAddSlashes($db) . "'"
|
||||
. " AND `page_nr` = '" . $page . "'";
|
||||
. " AND `page_nr` = '" . intval($page) . "'";
|
||||
|
||||
if (!$this->exportData(
|
||||
$cfgRelation['db'],
|
||||
|
||||
@ -185,7 +185,7 @@ class ExportXml extends ExportPlugin
|
||||
if ($names) {
|
||||
foreach ($names as $name) {
|
||||
$head .= ' <pma:' . $type . ' name="'
|
||||
. $name . '">' . $crlf;
|
||||
. htmlspecialchars($name) . '">' . $crlf;
|
||||
|
||||
// Do some formatting
|
||||
$sql = $GLOBALS['dbi']->getDefinition($db, $dbitype, $name);
|
||||
@ -232,7 +232,7 @@ class ExportXml extends ExportPlugin
|
||||
. '- version ' . PMA_VERSION . $crlf
|
||||
. '- https://www.phpmyadmin.net' . $crlf
|
||||
. '-' . $crlf
|
||||
. '- ' . __('Host:') . ' ' . $cfg['Server']['host'];
|
||||
. '- ' . __('Host:') . ' ' . htmlspecialchars($cfg['Server']['host']);
|
||||
if (!empty($cfg['Server']['port'])) {
|
||||
$head .= ':' . $cfg['Server']['port'];
|
||||
}
|
||||
@ -263,7 +263,7 @@ class ExportXml extends ExportPlugin
|
||||
$head .= ' -->' . $crlf;
|
||||
$head .= ' <pma:structure_schemas>' . $crlf;
|
||||
$head .= ' <pma:database name="' . htmlspecialchars($db)
|
||||
. '" collation="' . $db_collation . '" charset="' . $db_charset
|
||||
. '" collation="' . htmlspecialchars($db_collation) . '" charset="' . htmlspecialchars($db_charset)
|
||||
. '">' . $crlf;
|
||||
|
||||
if (count($tables) == 0) {
|
||||
@ -296,7 +296,7 @@ class ExportXml extends ExportPlugin
|
||||
continue;
|
||||
}
|
||||
|
||||
$head .= ' <pma:' . $type . ' name="' . $table . '">'
|
||||
$head .= ' <pma:' . $type . ' name="' . htmlspecialchars($table) . '">'
|
||||
. $crlf;
|
||||
|
||||
$tbl = " " . htmlspecialchars($tbl);
|
||||
@ -314,7 +314,7 @@ class ExportXml extends ExportPlugin
|
||||
foreach ($triggers as $trigger) {
|
||||
$code = $trigger['create'];
|
||||
$head .= ' <pma:trigger name="'
|
||||
. $trigger['name'] . '">' . $crlf;
|
||||
. htmlspecialchars($trigger['name']) . '">' . $crlf;
|
||||
|
||||
// Do some formatting
|
||||
$code = mb_substr(rtrim($code), 0, -3);
|
||||
@ -402,7 +402,7 @@ class ExportXml extends ExportPlugin
|
||||
) {
|
||||
$head = ' <!--' . $crlf
|
||||
. ' - ' . __('Database:') . ' ' . '\''
|
||||
. $db_alias . '\'' . $crlf
|
||||
. htmlspecialchars($db_alias) . '\'' . $crlf
|
||||
. ' -->' . $crlf . ' <database name="'
|
||||
. htmlspecialchars($db_alias) . '">' . $crlf;
|
||||
|
||||
@ -491,7 +491,7 @@ class ExportXml extends ExportPlugin
|
||||
unset($i);
|
||||
|
||||
$buffer = ' <!-- ' . __('Table') . ' '
|
||||
. $table_alias . ' -->' . $crlf;
|
||||
. htmlspecialchars($table_alias) . ' -->' . $crlf;
|
||||
if (!PMA_exportOutputHandler($buffer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -100,21 +100,24 @@ class ImportShp extends ImportPlugin
|
||||
// Extract the .dbf file and point to it.
|
||||
$extracted = PMA_zipExtract(
|
||||
$import_file,
|
||||
realpath($GLOBALS['cfg']['TempDir']),
|
||||
array($dbf_file_name)
|
||||
$dbf_file_name
|
||||
);
|
||||
if ($extracted) {
|
||||
if ($extracted !== false) {
|
||||
$dbf_file_path = realpath($GLOBALS['cfg']['TempDir'])
|
||||
. (PMA_IS_WINDOWS ? '\\' : '/') . $dbf_file_name;
|
||||
$temp_dbf_file = true;
|
||||
// Replace the .dbf with .*, as required
|
||||
// by the bsShapeFiles library.
|
||||
$file_name = mb_substr(
|
||||
$dbf_file_path,
|
||||
0,
|
||||
mb_strlen($dbf_file_path) - 4
|
||||
) . '.*';
|
||||
$shp->FileName = $file_name;
|
||||
. (PMA_IS_WINDOWS ? '\\' : '/')
|
||||
. PMA_sanitizeFilename($dbf_file_name, true);
|
||||
$handle = fopen($dbf_file_path, 'wb');
|
||||
if ($handle !== false) {
|
||||
fwrite($handle, $extracted);
|
||||
fclose($handle);
|
||||
$temp_dbf_file = true;
|
||||
// Replace the .dbf with .*, as required
|
||||
// by the bsShapeFiles library.
|
||||
$file_name = substr(
|
||||
$dbf_file_path, 0, strlen($dbf_file_path) - 4
|
||||
) . '.*';
|
||||
$shp->FileName = $file_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif (!empty($local_import_file)
|
||||
@ -134,6 +137,14 @@ class ImportShp extends ImportPlugin
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the .dbf file extracted to 'TempDir'
|
||||
if ($temp_dbf_file
|
||||
&& isset($dbf_file_path)
|
||||
&& file_exists($dbf_file_path)
|
||||
) {
|
||||
unlink($dbf_file_path);
|
||||
}
|
||||
|
||||
// Load data
|
||||
$shp->loadFromFile('');
|
||||
if ($shp->lastError != "") {
|
||||
@ -146,14 +157,6 @@ class ImportShp extends ImportPlugin
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete the .dbf file extracted to 'TempDir'
|
||||
if ($temp_dbf_file
|
||||
&& isset($dbf_file_path)
|
||||
&& file_exists($dbf_file_path)
|
||||
) {
|
||||
unlink($dbf_file_path);
|
||||
}
|
||||
|
||||
switch ($shp->shapeType) {
|
||||
// ESRI Null Shape
|
||||
case 0:
|
||||
|
||||
@ -54,7 +54,7 @@ class ExportRelationSchema
|
||||
*/
|
||||
public function setPageNumber($value)
|
||||
{
|
||||
$this->pageNumber = $value;
|
||||
$this->pageNumber = intval($value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -42,7 +42,9 @@ abstract class FormattedTransformationsPlugin extends TransformationsPlugin
|
||||
*/
|
||||
public function applyTransformation($buffer, $options = array(), $meta = '')
|
||||
{
|
||||
return $buffer;
|
||||
return '<iframe srcdoc="'
|
||||
. strtr($buffer, '"', '\'')
|
||||
. '" sandbox=""></iframe>';
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ abstract class ImageLinkTransformationsPlugin extends TransformationsPlugin
|
||||
{
|
||||
// must disable the page loader, see
|
||||
// https://wiki.phpmyadmin.net/pma/Page_loader#Bypassing_the_page_loader
|
||||
return '<a class="disableAjax" target="_new" href="transformation_wrapper.php'
|
||||
return '<a class="disableAjax" target="_blank" rel="noopener noreferrer" href="transformation_wrapper.php'
|
||||
. $options['wrapper_link'] . '" alt="[' . htmlspecialchars($buffer) . ']">[BLOB]</a>';
|
||||
}
|
||||
|
||||
|
||||
@ -82,8 +82,8 @@ abstract class ImageUploadTransformationsPlugin extends IOTransformationsPlugin
|
||||
$src = 'transformation_wrapper.php' . $options['wrapper_link'];
|
||||
}
|
||||
$html .= '<img src="' . $src . '" width="'
|
||||
. (isset($options[0]) ? $options[0] : '100') . '" height="'
|
||||
. (isset($options[1]) ? $options[1] : '100') . '" alt="'
|
||||
. (isset($options[0]) ? intval($options[0]) : '100') . '" height="'
|
||||
. (isset($options[1]) ? intval($options[1]) : '100') . '" alt="'
|
||||
. __('Image preview here') . '"/>';
|
||||
$html .= '<br/><input type="file" name="fields_upload'
|
||||
. $column_name_appendix . '" accept="image/*" class="image-upload"/>';
|
||||
|
||||
@ -51,10 +51,10 @@ abstract class InlineTransformationsPlugin extends TransformationsPlugin
|
||||
if (PMA_IS_GD2) {
|
||||
return '<a href="transformation_wrapper.php'
|
||||
. $options['wrapper_link']
|
||||
. '" target="_blank"><img src="transformation_wrapper.php'
|
||||
. '" rel="noopener noreferrer" target="_blank"><img src="transformation_wrapper.php'
|
||||
. $options['wrapper_link'] . '&resize=jpeg&newWidth='
|
||||
. (isset($options[0]) ? $options[0] : '100') . '&newHeight='
|
||||
. (isset($options[1]) ? $options[1] : 100)
|
||||
. (isset($options[0]) ? intval($options[0]) : '100') . '&newHeight='
|
||||
. (isset($options[1]) ? intval($options[1]) : 100)
|
||||
. '" alt="[' . htmlspecialchars($buffer) . ']" border="0" /></a>';
|
||||
} else {
|
||||
return '<img src="transformation_wrapper.php'
|
||||
|
||||
@ -50,7 +50,7 @@ abstract class RegexValidationTransformationsPlugin extends IOTransformationsPlu
|
||||
$this->success = false;
|
||||
$this->error = sprintf(
|
||||
__('Validation failed for the input string %s.'),
|
||||
$buffer
|
||||
htmlspecialchars($buffer)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -49,13 +49,13 @@ abstract class TextImageLinkTransformationsPlugin extends TransformationsPlugin
|
||||
$url = (isset($options[0]) ? $options[0] : '') . $buffer;
|
||||
$parsed = parse_url($url);
|
||||
/* Do not allow javascript links */
|
||||
if (isset($parsed['scheme']) && $parsed['scheme'] == 'javascript') {
|
||||
if (! isset($parsed['scheme']) || ! in_array(strtolower($parsed['scheme']), array('http', 'https', 'ftp', 'mailto'))) {
|
||||
return htmlspecialchars($url);
|
||||
}
|
||||
return '<a href="' . htmlspecialchars($url)
|
||||
. '" target="_blank"><img src="' . htmlspecialchars($url)
|
||||
. '" border="0" width="' . (isset($options[1]) ? $options[1] : 100)
|
||||
. '" height="' . (isset($options[2]) ? $options[2] : 50) . '" />'
|
||||
. '" rel="noopener noreferrer" target="_blank"><img src="' . htmlspecialchars($url)
|
||||
. '" border="0" width="' . (isset($options[1]) ? intval($options[1]) : 100)
|
||||
. '" height="' . (isset($options[2]) ? intval($options[2]) : 50) . '" />'
|
||||
. htmlspecialchars($buffer) . '</a>';
|
||||
}
|
||||
|
||||
|
||||
@ -49,14 +49,14 @@ abstract class TextLinkTransformationsPlugin extends TransformationsPlugin
|
||||
$url = (isset($options[0]) ? $options[0] : '') . ((isset($options[2]) && $options[2]) ? '' : $buffer);
|
||||
$parsed = parse_url($url);
|
||||
/* Do not allow javascript links */
|
||||
if (isset($parsed['scheme']) && $parsed['scheme'] == 'javascript') {
|
||||
if (! isset($parsed['scheme']) || ! in_array(strtolower($parsed['scheme']), array('http', 'https', 'ftp', 'mailto'))) {
|
||||
return htmlspecialchars($url);
|
||||
}
|
||||
return '<a href="'
|
||||
. htmlspecialchars($url)
|
||||
. '" title="'
|
||||
. htmlspecialchars(isset($options[1]) ? $options[1] : '')
|
||||
. '" target="_new">'
|
||||
. '" target="_blank" rel="noopener noreferrer">'
|
||||
. htmlspecialchars(isset($options[1]) ? $options[1] : $buffer)
|
||||
. '</a>';
|
||||
}
|
||||
|
||||
@ -261,7 +261,7 @@ function PMA_getTablePositions($pg)
|
||||
1 AS `H`
|
||||
FROM " . PMA\libraries\Util::backquote($cfgRelation['db'])
|
||||
. "." . PMA\libraries\Util::backquote($cfgRelation['table_coords']) . "
|
||||
WHERE pdf_page_number = " . $pg;
|
||||
WHERE pdf_page_number = " . intval($pg);
|
||||
|
||||
$tab_pos = $GLOBALS['dbi']->fetchResult(
|
||||
$query,
|
||||
@ -290,7 +290,7 @@ function PMA_getPageName($pg)
|
||||
$query = "SELECT `page_descr`"
|
||||
. " FROM " . PMA\libraries\Util::backquote($cfgRelation['db'])
|
||||
. "." . PMA\libraries\Util::backquote($cfgRelation['pdf_pages'])
|
||||
. " WHERE " . PMA\libraries\Util::backquote('page_nr') . " = " . $pg;
|
||||
. " WHERE " . PMA\libraries\Util::backquote('page_nr') . " = " . intval($pg);
|
||||
$page_name = $GLOBALS['dbi']->fetchResult(
|
||||
$query,
|
||||
null,
|
||||
@ -317,7 +317,7 @@ function PMA_deletePage($pg)
|
||||
|
||||
$query = "DELETE FROM " . PMA\libraries\Util::backquote($cfgRelation['db'])
|
||||
. "." . PMA\libraries\Util::backquote($cfgRelation['table_coords'])
|
||||
. " WHERE " . PMA\libraries\Util::backquote('pdf_page_number') . " = " . $pg;
|
||||
. " WHERE " . PMA\libraries\Util::backquote('pdf_page_number') . " = " . intval($pg);
|
||||
$success = PMA_queryAsControlUser(
|
||||
$query, true, PMA\libraries\DatabaseInterface::QUERY_STORE
|
||||
);
|
||||
@ -325,7 +325,7 @@ function PMA_deletePage($pg)
|
||||
if ($success) {
|
||||
$query = "DELETE FROM " . PMA\libraries\Util::backquote($cfgRelation['db'])
|
||||
. "." . PMA\libraries\Util::backquote($cfgRelation['pdf_pages'])
|
||||
. " WHERE " . PMA\libraries\Util::backquote('page_nr') . " = " . $pg;
|
||||
. " WHERE " . PMA\libraries\Util::backquote('page_nr') . " = " . intval($pg);
|
||||
$success = PMA_queryAsControlUser(
|
||||
$query, true, PMA\libraries\DatabaseInterface::QUERY_STORE
|
||||
);
|
||||
@ -364,7 +364,7 @@ function PMA_getDefaultPage($db)
|
||||
);
|
||||
|
||||
if (count($default_page_no)) {
|
||||
return $default_page_no[0];
|
||||
return intval($default_page_no[0]);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -406,7 +406,7 @@ function PMA_getLoadingPage($db)
|
||||
$page_no = $min_page_no[0];
|
||||
}
|
||||
}
|
||||
return $page_no;
|
||||
return intval($page_no);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1666,7 +1666,7 @@ function PMA_REL_renameTable($source_db, $target_db, $source_table, $target_tabl
|
||||
* @param array $cfgRelation Relation configuration
|
||||
* @param string $db database name
|
||||
*
|
||||
* @return string $pdf_page_number
|
||||
* @return int $pdf_page_number
|
||||
*/
|
||||
function PMA_REL_createPage($newpage, $cfgRelation, $db)
|
||||
{
|
||||
|
||||
@ -295,7 +295,7 @@ function PMA_Replication_connectToMaster(
|
||||
$server = array();
|
||||
$server['user'] = $user;
|
||||
$server['password'] = $password;
|
||||
$server["host"] = $host;
|
||||
$server["host"] = PMA_sanitizeMySQLHost($host);
|
||||
$server["port"] = $port;
|
||||
$server["socket"] = $socket;
|
||||
|
||||
|
||||
@ -549,7 +549,7 @@ function PMA_getHtmlForReplicationStatusTable($type, $hidden = false, $title = t
|
||||
foreach (${"{$type}_variables"} as $variable) {
|
||||
$html .= ' <tr class="' . ($odd_row ? 'odd' : 'even') . '">';
|
||||
$html .= ' <td class="name">';
|
||||
$html .= $variable;
|
||||
$html .= htmlspecialchars($variable);
|
||||
$html .= ' </td>';
|
||||
$html .= ' <td class="value">';
|
||||
|
||||
@ -572,13 +572,13 @@ function PMA_getHtmlForReplicationStatusTable($type, $hidden = false, $title = t
|
||||
'Replicate_Do_Table', 'Replicate_Ignore_Table',
|
||||
'Replicate_Wild_Do_Table', 'Replicate_Wild_Ignore_Table');
|
||||
if (in_array($variable, $variables_wrap)) {
|
||||
$html .= str_replace(
|
||||
$html .= htmlspecialchars(str_replace(
|
||||
',',
|
||||
', ',
|
||||
${"server_{$type}_replication"}[0][$variable]
|
||||
);
|
||||
));
|
||||
} else {
|
||||
$html .= ${"server_{$type}_replication"}[0][$variable];
|
||||
$html .= htmlspecialchars(${"server_{$type}_replication"}[0][$variable]);
|
||||
}
|
||||
$html .= '</span>';
|
||||
|
||||
@ -807,7 +807,7 @@ function PMA_getHtmlForAddUserLoginForm($username_length)
|
||||
. (empty($_REQUEST['username']) ? '' : ' value="'
|
||||
. (isset($GLOBALS['new_username'])
|
||||
? $GLOBALS['new_username']
|
||||
: $_REQUEST['username']) . '"')
|
||||
: htmlspecialchars($_REQUEST['username'])) . '"')
|
||||
. ' />'
|
||||
. '</div>';
|
||||
|
||||
@ -837,7 +837,7 @@ function PMA_getHtmlForTableInfoForm($hostname_length)
|
||||
. '</span>'
|
||||
. '<input type="text" name="hostname" id="pma_hostname" maxlength="'
|
||||
. $hostname_length . '" value="'
|
||||
. (isset($_REQUEST['hostname']) ? $_REQUEST['hostname'] : '')
|
||||
. (isset($_REQUEST['hostname']) ? htmlspecialchars($_REQUEST['hostname']) : '')
|
||||
. '" title="' . __('Host')
|
||||
. '" />'
|
||||
. PMA\libraries\Util::showHint(
|
||||
|
||||
@ -2390,13 +2390,13 @@ function PMA_getHtmlTableBodyForSpecificDbRoutinePrivs($db, $odd_row, $index_che
|
||||
. 'id="checkbox_sel_users_' . ($index_checkbox++) . '" '
|
||||
. 'value="' . $value . '" /></td>';
|
||||
|
||||
$html_output .= '<td>' . $row['User']
|
||||
$html_output .= '<td>' . htmlspecialchars($row['User'])
|
||||
. '</td>'
|
||||
. '<td>' . $row['Host']
|
||||
. '<td>' . htmlspecialchars($row['Host'])
|
||||
. '</td>'
|
||||
. '<td>' . 'routine'
|
||||
. '</td>'
|
||||
. '<td>' . '<code>' . $row['Routine_name'] . '</code>'
|
||||
. '<td>' . '<code>' . htmlspecialchars($row['Routine_name']) . '</code>'
|
||||
. '</td>'
|
||||
. '<td>' . 'Yes'
|
||||
. '</td>';
|
||||
|
||||
@ -285,7 +285,7 @@ function PMA_getHtmlForRenderVariables($ServerStatusData, $alerts, $strShowStatu
|
||||
$retval .= '<span class="allfine">';
|
||||
}
|
||||
}
|
||||
$retval .= $value;
|
||||
$retval .= htmlspecialchars($value);
|
||||
if (isset($alerts[$name])) {
|
||||
$retval .= '</span>';
|
||||
}
|
||||
|
||||
@ -352,7 +352,7 @@ function PMA_editUserGroup($userGroup, $new = false)
|
||||
}
|
||||
$tabName = $tabGroupName . '_' . $tab;
|
||||
$allowed = isset($_REQUEST[$tabName]) && $_REQUEST[$tabName] == 'Y';
|
||||
$sql_query .= "('" . $userGroup . "', '" . $tabName . "', '"
|
||||
$sql_query .= "('" . PMA_Util::sqlAddSlashes($userGroup) . "', '" . $tabName . "', '"
|
||||
. ($allowed ? "Y" : "N") . "')";
|
||||
$first = false;
|
||||
}
|
||||
|
||||
@ -75,7 +75,23 @@ function PMA_sessionFailed($errors)
|
||||
{
|
||||
$messages = array();
|
||||
foreach ($errors as $error) {
|
||||
$messages[] = $error->getMessage();
|
||||
/*
|
||||
* Remove path from open() in error message to avoid path disclossure
|
||||
*
|
||||
* This can happen with PHP 5 when nonexisting session ID is provided,
|
||||
* since PHP 7, session existence is checked first.
|
||||
*
|
||||
* This error can also happen in case of session backed error (eg.
|
||||
* read only filesystem) on any PHP version.
|
||||
*
|
||||
* The message string is currently hardcoded in PHP, so hopefully it
|
||||
* will not change in future.
|
||||
*/
|
||||
$messages[] = preg_replace(
|
||||
'/open(.*, O_RDWR)/',
|
||||
'open(SESSION_FILE, O_RDWR)',
|
||||
$error->getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -393,9 +393,7 @@ function PMA_getHtmlForTableVersionDetails(
|
||||
function PMA_getTableLastVersionNumber($sql_result)
|
||||
{
|
||||
$maxversion = $GLOBALS['dbi']->fetchArray($sql_result);
|
||||
$last_version = $maxversion['version'];
|
||||
|
||||
return $last_version;
|
||||
return intval($maxversion['version']);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -867,7 +865,10 @@ function PMA_getHtmlForSchemaSnapshot($url_query)
|
||||
);
|
||||
|
||||
// Unserialize snapshot
|
||||
$temp = unserialize($data['schema_snapshot']);
|
||||
$temp = PMA_safeUnserialize($data['schema_snapshot']);
|
||||
if ($temp === null) {
|
||||
$temp = array('COLUMNS' => array(), 'INDEXES' => array());
|
||||
}
|
||||
$columns = $temp['COLUMNS'];
|
||||
$indexes = $temp['INDEXES'];
|
||||
$html .= PMA_getHtmlForColumns($columns);
|
||||
|
||||
@ -143,19 +143,18 @@ function PMA_getNoOfFilesInZip($file)
|
||||
/**
|
||||
* Extracts a set of files from the given zip archive to a given destinations.
|
||||
*
|
||||
* @param string $zip_path path to the zip archive
|
||||
* @param string $destination destination to extract files
|
||||
* @param array $entries files in archive that should be extracted
|
||||
* @param string $zip_path path to the zip archive
|
||||
* @param string $entry file in the archive that should be extracted
|
||||
*
|
||||
* @return bool true on success, false otherwise
|
||||
* @return string|bool data on sucess, false otherwise
|
||||
*/
|
||||
function PMA_zipExtract($zip_path, $destination, $entries)
|
||||
function PMA_zipExtract($zip_path, $entry)
|
||||
{
|
||||
$zip = new ZipArchive;
|
||||
if ($zip->open($zip_path) === true) {
|
||||
$zip->extractTo($destination, $entries);
|
||||
$result = $zip->getFromName($entry);
|
||||
$zip->close();
|
||||
return true;
|
||||
return $result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
2
lint.php
2
lint.php
@ -7,6 +7,8 @@
|
||||
*/
|
||||
use PMA\libraries\Linter;
|
||||
|
||||
$_GET['ajax_request'] = 'true';
|
||||
|
||||
/**
|
||||
* Loading common files. Used to check for authorization, localization and to
|
||||
* load the parsing library.
|
||||
|
||||
@ -27,7 +27,7 @@ if (isset($_REQUEST['getColumns'])) {
|
||||
exit;
|
||||
}
|
||||
if (isset($_REQUEST['splitColumn'])) {
|
||||
$num_fields = $_REQUEST['numFields'];
|
||||
$num_fields = min(4096, intval($_REQUEST['numFields']));
|
||||
$html = PMA_getHtmlForCreateNewColumn($num_fields, $db, $table);
|
||||
$html .= URL::getHiddenInputs($db, $table);
|
||||
echo $html;
|
||||
|
||||
20
phpinfo.php
20
phpinfo.php
@ -1,20 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* phpinfo() wrapper to allow displaying only when configured to do so.
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets core libraries and defines some variables
|
||||
*/
|
||||
require_once 'libraries/common.inc.php';
|
||||
PMA\libraries\Response::getInstance()->disable();
|
||||
|
||||
/**
|
||||
* Displays PHP information
|
||||
*/
|
||||
if ($GLOBALS['cfg']['ShowPhpInfo']) {
|
||||
phpinfo();
|
||||
}
|
||||
@ -43,10 +43,13 @@ if (isset($_REQUEST['submit_num_fields'])) {
|
||||
if (isset($_REQUEST['orig_field_where'])) {
|
||||
$_REQUEST['field_where'] = $_REQUEST['orig_field_where'];
|
||||
}
|
||||
$num_fields = $_REQUEST['orig_num_fields'] + $_REQUEST['added_fields'];
|
||||
$num_fields = min(
|
||||
intval($_REQUEST['orig_num_fields']) + intval($_REQUEST['added_fields']),
|
||||
4096
|
||||
);
|
||||
$regenerate = true;
|
||||
} elseif (isset($_REQUEST['num_fields']) && intval($_REQUEST['num_fields']) > 0) {
|
||||
$num_fields = (int) $_REQUEST['num_fields'];
|
||||
$num_fields = min(4096, intval($_REQUEST['num_fields']));
|
||||
} else {
|
||||
$num_fields = 1;
|
||||
}
|
||||
|
||||
@ -21,6 +21,10 @@
|
||||
? ' target="' . $url['target'] . '"'
|
||||
: null;
|
||||
?>
|
||||
<?= !empty($url['target']) && $url['target'] == '_blank'
|
||||
? ' rel="noopener noreferrer"'
|
||||
: null;
|
||||
?>
|
||||
<?= !empty($url['id']) ? ' id="' . $url['id'] . '"' : null; ?>
|
||||
<?= !empty($url['class'])
|
||||
? ' class="' . $url['class'] . '"'
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
<input type="hidden" name="dbstats" value="1" />
|
||||
<?php endif; ?>
|
||||
|
||||
<input type="text" name="new_db" value="<?= $GLOBALS['db_to_create']; ?>"
|
||||
<input type="text" name="new_db" value="<?= htmlspecialchars($GLOBALS['db_to_create']); ?>"
|
||||
maxlength="64" class="textfield" id="text_create_db" required
|
||||
placeholder="<?= __('Database name'); ?>" />
|
||||
<?= PMA\libraries\Charsets::getCollationDropdownBox('db_collation', null, null, true); ?>
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
<select name="visualizationSettings[labelColumn]" id="labelColumn" class="autosubmit">
|
||||
<option value=""><?= __("-- None --"); ?></option>
|
||||
<?php foreach ($labelCandidates as $value): ?>
|
||||
<option value="<?= $value; ?>" <?= ($value == $visualizationSettings['labelColumn'] ? 'selected="selected"' : ''); ?>>
|
||||
<?= $value; ?>
|
||||
<option value="<?= htmlspecialchars($value); ?>" <?= ($value == $visualizationSettings['labelColumn'] ? 'selected="selected"' : ''); ?>>
|
||||
<?= htmlspecialchars($value); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
@ -20,8 +20,8 @@
|
||||
</label>
|
||||
<select name="visualizationSettings[spatialColumn]" id="spatialColumn" class="autosubmit">
|
||||
<?php foreach ($spatialCandidates as $value): ?>
|
||||
<option value="<?= $value; ?>" <?= ($value == $visualizationSettings['spatialColumn'] ? 'selected="selected"' : ''); ?>>
|
||||
<?= $value; ?>
|
||||
<option value="<?= htmlspecialchars($value); ?>" <?= ($value == $visualizationSettings['spatialColumn'] ? 'selected="selected"' : ''); ?>>
|
||||
<?= htmlspecialchars($value); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
</a>
|
||||
</center>
|
||||
<div id="querydata" style="display:none">
|
||||
<?= json_encode($data); ?>
|
||||
<?= htmlspecialchars(json_encode($data)); ?>
|
||||
</div>
|
||||
<div id="querychart"></div>
|
||||
<button class="button-reset">
|
||||
|
||||
@ -187,7 +187,7 @@ $rownum = 0; $odd_row = true; ?>
|
||||
$tmp_partition_description = $firstPartition->getDescription();
|
||||
|
||||
$removeSQL = "ALTER TABLE " . Util::backquote($table) . " REMOVE PARTITIONING";
|
||||
$removeUrl = 'sql.php' . $url_query . '&sql_query=' . urldecode($removeSQL);
|
||||
$removeUrl = 'sql.php' . $url_query . '&sql_query=' . urlencode($removeSQL);
|
||||
|
||||
echo Template::get('table/structure/display_partitions')->render(
|
||||
array(
|
||||
|
||||
@ -1363,7 +1363,7 @@ class DisplayResultsTest extends PMATestCase
|
||||
$meta,
|
||||
$url_params,
|
||||
null,
|
||||
'<a href="1001" title="" target="_new">1001</a>'
|
||||
'1001'
|
||||
),
|
||||
array(
|
||||
false,
|
||||
@ -1492,7 +1492,7 @@ class DisplayResultsTest extends PMATestCase
|
||||
0,
|
||||
'binary',
|
||||
'<td class="left grid_edit transformed hex">'
|
||||
. '<a href="1001" title="" target="_new">1001</a></td>'
|
||||
. '1001</td>'
|
||||
),
|
||||
array(
|
||||
'noblob',
|
||||
|
||||
@ -252,7 +252,7 @@ class PbxtTest extends PMATestCase
|
||||
. ' can be found on the %sPrimeBase XT Home Page%s.'
|
||||
),
|
||||
'<a href="' . PMA_linkURL('https://mariadb.com/kb/en/mariadb/about-pbxt/')
|
||||
. '" target="_blank">',
|
||||
. '" rel="noopener noreferrer" target="_blank">',
|
||||
'</a>'
|
||||
)
|
||||
. '</p>' . "\n"
|
||||
|
||||
@ -454,12 +454,12 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
$GLOBALS['cfg']['LoginCookieDeleteAll'] = true;
|
||||
$GLOBALS['cfg']['Servers'] = array(1);
|
||||
|
||||
$_COOKIE['pmaPass-0'] = 'test';
|
||||
$_COOKIE['pmaAuth-0'] = 'test';
|
||||
|
||||
$this->object->logOut();
|
||||
|
||||
$this->assertFalse(
|
||||
isset($_COOKIE['pmaPass-0'])
|
||||
isset($_COOKIE['pmaAuth-0'])
|
||||
);
|
||||
$attrInstance->setValue($restoreInstance);
|
||||
}
|
||||
@ -496,12 +496,12 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
$GLOBALS['cfg']['Servers'] = array(1);
|
||||
$GLOBALS['server'] = 1;
|
||||
|
||||
$_COOKIE['pmaPass-1'] = 'test';
|
||||
$_COOKIE['pmaAuth-1'] = 'test';
|
||||
|
||||
$this->object->logOut();
|
||||
|
||||
$this->assertFalse(
|
||||
isset($_COOKIE['pmaPass-1'])
|
||||
isset($_COOKIE['pmaAuth-1'])
|
||||
);
|
||||
$attrInstance->setValue($restoreInstance);
|
||||
}
|
||||
@ -541,7 +541,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
);
|
||||
|
||||
$this->assertFalse(
|
||||
isset($_COOKIE['pmaPass-1'])
|
||||
isset($_COOKIE['pmaAuth-1'])
|
||||
);
|
||||
}
|
||||
|
||||
@ -550,25 +550,19 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAuthCheckIV()
|
||||
public function testAuthCheckInvalidCookie()
|
||||
{
|
||||
$GLOBALS['cfg']['AllowArbitraryServer'] = true;
|
||||
$_REQUEST['pma_servername'] = 'testPMAServer';
|
||||
$_REQUEST['pma_password'] = 'testPMAPSWD';
|
||||
$_REQUEST['pma_username'] = '';
|
||||
$GLOBALS['server'] = 1;
|
||||
$_COOKIE['pmaServer-1'] = 'pmaServ1';
|
||||
$_COOKIE['pmaUser-1'] = '';
|
||||
$_COOKIE['pma_iv-1'] = base64_encode('testiv09testiv09');
|
||||
|
||||
$this->assertFalse(
|
||||
$this->object->authCheck()
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'pmaServ1',
|
||||
$GLOBALS['pma_auth_server']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -582,7 +576,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
$_COOKIE['pmaServer-1'] = 'pmaServ1';
|
||||
$_COOKIE['pmaUser-1'] = 'pmaUser1';
|
||||
$_COOKIE['pma_iv-1'] = base64_encode('testiv09testiv09');
|
||||
$_COOKIE['pmaPass-1'] = '';
|
||||
$_COOKIE['pmaAuth-1'] = '';
|
||||
$GLOBALS['cfg']['blowfish_secret'] = 'secret';
|
||||
$_SESSION['last_access_time'] = time() - 1000;
|
||||
$GLOBALS['cfg']['LoginCookieValidity'] = 1440;
|
||||
@ -642,7 +636,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
$_REQUEST['pma_username'] = '';
|
||||
$_COOKIE['pmaServer-1'] = 'pmaServ1';
|
||||
$_COOKIE['pmaUser-1'] = 'pmaUser1';
|
||||
$_COOKIE['pmaPass-1'] = 'pmaPass1';
|
||||
$_COOKIE['pmaAuth-1'] = 'pmaAuth1';
|
||||
$_COOKIE['pma_iv-1'] = base64_encode('testiv09testiv09');
|
||||
$GLOBALS['cfg']['blowfish_secret'] = 'secret';
|
||||
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = '';
|
||||
@ -658,7 +652,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
|
||||
$this->object->expects($this->at(1))
|
||||
->method('cookieDecrypt')
|
||||
->will($this->returnValue(''));
|
||||
->will($this->returnValue('{"password":""}'));
|
||||
|
||||
$this->assertTrue(
|
||||
$this->object->authCheck()
|
||||
@ -756,7 +750,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
);
|
||||
|
||||
$this->assertTrue(
|
||||
isset($_COOKIE['pmaPass-1'])
|
||||
isset($_COOKIE['pmaAuth-1'])
|
||||
);
|
||||
|
||||
$arr['password'] = 'testPW';
|
||||
@ -828,10 +822,6 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
$this->object->authSetUser();
|
||||
$this->object->storeUserCredentials();
|
||||
|
||||
$this->assertTrue(
|
||||
isset($_COOKIE['pmaServer-2'])
|
||||
);
|
||||
|
||||
$attrInstance->setValue($restoreInstance);
|
||||
}
|
||||
|
||||
@ -879,7 +869,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
->getMock();
|
||||
|
||||
$GLOBALS['server'] = 2;
|
||||
$_COOKIE['pmaPass-2'] = 'pass';
|
||||
$_COOKIE['pmaAuth-2'] = 'pass';
|
||||
|
||||
$GLOBALS['login_without_password_is_forbidden'] = '1';
|
||||
|
||||
@ -904,7 +894,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
->getMock();
|
||||
|
||||
$GLOBALS['server'] = 2;
|
||||
$_COOKIE['pmaPass-2'] = 'pass';
|
||||
$_COOKIE['pmaAuth-2'] = 'pass';
|
||||
|
||||
$GLOBALS['login_without_password_is_forbidden'] = '';
|
||||
$GLOBALS['allowDeny_forbidden'] = '1';
|
||||
@ -928,7 +918,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
->getMock();
|
||||
|
||||
$GLOBALS['server'] = 2;
|
||||
$_COOKIE['pmaPass-2'] = 'pass';
|
||||
$_COOKIE['pmaAuth-2'] = 'pass';
|
||||
|
||||
$GLOBALS['allowDeny_forbidden'] = '';
|
||||
$GLOBALS['no_activity'] = '1';
|
||||
@ -953,7 +943,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
->getMock();
|
||||
|
||||
$GLOBALS['server'] = 2;
|
||||
$_COOKIE['pmaPass-2'] = 'pass';
|
||||
$_COOKIE['pmaAuth-2'] = 'pass';
|
||||
|
||||
$dbi = $this->getMockBuilder('PMA\libraries\DatabaseInterface')
|
||||
->disableOriginalConstructor()
|
||||
@ -995,7 +985,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
|
||||
$GLOBALS['dbi'] = $dbi;
|
||||
$GLOBALS['server'] = 2;
|
||||
$_COOKIE['pmaPass-2'] = 'pass';
|
||||
$_COOKIE['pmaAuth-2'] = 'pass';
|
||||
|
||||
unset($GLOBALS['errno']);
|
||||
|
||||
@ -1034,7 +1024,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
256,
|
||||
32,
|
||||
strlen($result)
|
||||
);
|
||||
}
|
||||
@ -1057,7 +1047,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
$result = $method->invoke($this->object, null);
|
||||
|
||||
$this->assertEquals(
|
||||
md5('notEmpty'),
|
||||
'notEmpty',
|
||||
$result
|
||||
);
|
||||
}
|
||||
@ -1072,7 +1062,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
$this->object->setIV('testiv09testiv09');
|
||||
// works with the openssl extension active or inactive
|
||||
$this->assertEquals(
|
||||
'+coP/up/ZBTBwbiEpCUVXQ==',
|
||||
'{"iv":"dGVzdGl2MDl0ZXN0aXYwOQ==","mac":"347aa45ae1ade00c980f31129ec2defef18b2bfd","payload":"YDEaxOfP9nD9q\/2pC6hjfQ=="}',
|
||||
$this->object->cookieEncrypt('data123', 'sec321')
|
||||
);
|
||||
}
|
||||
@ -1084,16 +1074,101 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
*/
|
||||
public function testCookieDecrypt()
|
||||
{
|
||||
$this->object->setIV('testiv09testiv09');
|
||||
// works with the openssl extension active or inactive
|
||||
$this->assertEquals(
|
||||
'data123',
|
||||
$this->object->cookieDecrypt(
|
||||
'+coP/up/ZBTBwbiEpCUVXQ==',
|
||||
'{"iv":"dGVzdGl2MDl0ZXN0aXYwOQ==","mac":"347aa45ae1ade00c980f31129ec2defef18b2bfd","payload":"YDEaxOfP9nD9q\/2pC6hjfQ=="}',
|
||||
'sec321'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for PMA\libraries\plugins\auth\AuthenticationConfig::cookieDecrypt
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCookieDecryptInvalid()
|
||||
{
|
||||
// works with the openssl extension active or inactive
|
||||
$this->assertEquals(
|
||||
false,
|
||||
$this->object->cookieDecrypt(
|
||||
'{"iv":0,"mac":0,"payload":0}',
|
||||
'sec321'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for secret splitting using getAESSecret
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @dataProvider secretsProvider
|
||||
*/
|
||||
public function testMACSecretSplit($secret, $mac, $aes)
|
||||
{
|
||||
$this->assertEquals(
|
||||
$mac,
|
||||
$this->object->getMACSecret($secret)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for secret splitting using getMACSecret and getAESSecret
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @dataProvider secretsProvider
|
||||
*/
|
||||
public function testAESSecretSplit($secret, $mac, $aes)
|
||||
{
|
||||
$this->assertEquals(
|
||||
$aes,
|
||||
$this->object->getAESSecret($secret)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for secrets splitting.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function secretsProvider()
|
||||
{
|
||||
return array(
|
||||
// Optimal case
|
||||
array(
|
||||
'1234567890123456abcdefghijklmnop',
|
||||
'1234567890123456',
|
||||
'abcdefghijklmnop',
|
||||
),
|
||||
// Overlapping secret
|
||||
array(
|
||||
'12345678901234567',
|
||||
'1234567890123456',
|
||||
'2345678901234567',
|
||||
),
|
||||
// Short secret
|
||||
array(
|
||||
'1234567890123456',
|
||||
'1234567890123451',
|
||||
'2345678901234562',
|
||||
),
|
||||
// Really short secret
|
||||
array(
|
||||
'12',
|
||||
'1111111111111111',
|
||||
'2222222222222222',
|
||||
),
|
||||
// Too short secret
|
||||
array(
|
||||
'1',
|
||||
'1111111111111111',
|
||||
'1111111111111111',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,7 +162,7 @@ class ExportPhparrayTest extends PMATestCase
|
||||
*/
|
||||
public function testExportDBHeader()
|
||||
{
|
||||
$GLOBALS['crlf'] = ' ';
|
||||
$GLOBALS['crlf'] = "\n";
|
||||
|
||||
ob_start();
|
||||
$this->assertTrue(
|
||||
@ -171,7 +171,7 @@ class ExportPhparrayTest extends PMATestCase
|
||||
$result = ob_get_clean();
|
||||
|
||||
$this->assertContains(
|
||||
'// Database `db` ',
|
||||
"/**\n * Database `db`\n */",
|
||||
$result
|
||||
);
|
||||
}
|
||||
@ -252,7 +252,7 @@ class ExportPhparrayTest extends PMATestCase
|
||||
$result = ob_get_clean();
|
||||
|
||||
$this->assertEquals(
|
||||
"\n" . '// `db`.`table`' . "\n" .
|
||||
"\n" . '/* `db`.`table` */' . "\n" .
|
||||
'$table = array(' . "\n" .
|
||||
' array(\'c1\' => 1,\'\' => \'a\')' . "\n" .
|
||||
');' . "\n",
|
||||
|
||||
@ -528,6 +528,8 @@ class ExportXmlTest extends PMATestCase
|
||||
public function testExportData()
|
||||
{
|
||||
$GLOBALS['xml_export_contents'] = true;
|
||||
$GLOBALS['asfile'] = true;
|
||||
$GLOBALS['output_charset_conversion'] = false;
|
||||
|
||||
$dbi = $this->getMockBuilder('PMA\libraries\DatabaseInterface')
|
||||
->disableOriginalConstructor()
|
||||
@ -586,33 +588,33 @@ class ExportXmlTest extends PMATestCase
|
||||
$result = ob_get_clean();
|
||||
|
||||
$this->assertContains(
|
||||
"<!-- Table ta<ble -->",
|
||||
"<!-- Table ta<ble -->",
|
||||
$result
|
||||
);
|
||||
|
||||
$this->assertContains(
|
||||
"<table name="ta&lt;ble">",
|
||||
"<table name=\"ta<ble\">",
|
||||
$result
|
||||
);
|
||||
|
||||
$this->assertContains(
|
||||
"<column name="fName1">NULL</column>",
|
||||
"<column name=\"fName1\">NULL</column>",
|
||||
$result
|
||||
);
|
||||
|
||||
$this->assertContains(
|
||||
"<column name="fNa&quot;me2">&lt;a&gt;" .
|
||||
"</column>",
|
||||
"<column name=\"fNa"me2\"><a>" .
|
||||
"</column>",
|
||||
$result
|
||||
);
|
||||
|
||||
$this->assertContains(
|
||||
"<column name="fName3">NULL</column>",
|
||||
"<column name=\"fName3\">NULL</column>",
|
||||
$result
|
||||
);
|
||||
|
||||
$this->assertContains(
|
||||
"</table>",
|
||||
"</table>",
|
||||
$result
|
||||
);
|
||||
}
|
||||
|
||||
@ -778,8 +778,8 @@ class TransformationPluginsTest extends PMATestCase
|
||||
array("./image/", "200", "wrapper_link"=>"PMA_wrapper_link")
|
||||
),
|
||||
'<a href="transformation_wrapper.phpPMA_wrapper_link" '
|
||||
. 'target="_blank"><img src="transformation_wrapper.php'
|
||||
. 'PMA_wrapper_link&resize=jpeg&newWidth=./image/&'
|
||||
. 'rel="noopener noreferrer" target="_blank"><img src="transformation_wrapper.php'
|
||||
. 'PMA_wrapper_link&resize=jpeg&newWidth=0&'
|
||||
. 'newHeight=200" alt="[PMA_JPEG_Inline]" border="0" /></a>'
|
||||
),
|
||||
array(
|
||||
@ -788,7 +788,7 @@ class TransformationPluginsTest extends PMATestCase
|
||||
'PMA_IMAGE_LINK',
|
||||
array("./image/", "200", "wrapper_link"=>"PMA_wrapper_link")
|
||||
),
|
||||
'<a class="disableAjax" target="_new"'
|
||||
'<a class="disableAjax" target="_blank" rel="noopener noreferrer"'
|
||||
. ' href="transformation_wrapper.phpPMA_wrapper_link"'
|
||||
. ' alt="[PMA_IMAGE_LINK]">[BLOB]</a>'
|
||||
),
|
||||
@ -799,9 +799,9 @@ class TransformationPluginsTest extends PMATestCase
|
||||
array("./image/", "200", "wrapper_link"=>"PMA_wrapper_link")
|
||||
),
|
||||
'<a href="transformation_wrapper.phpPMA_wrapper_link"'
|
||||
. ' target="_blank"><img src="transformation_wrapper.php'
|
||||
. ' rel="noopener noreferrer" target="_blank"><img src="transformation_wrapper.php'
|
||||
. 'PMA_wrapper_link&'
|
||||
. 'resize=jpeg&newWidth=./image/&newHeight=200" '
|
||||
. 'resize=jpeg&newWidth=0&newHeight=200" '
|
||||
. 'alt="[PMA_PNG_Inline]" border="0" /></a>'
|
||||
),
|
||||
array(
|
||||
@ -866,7 +866,25 @@ class TransformationPluginsTest extends PMATestCase
|
||||
"<a ref='https://www.example.com/'>PMA_BUFFER</a>",
|
||||
array("option1", "option2")
|
||||
),
|
||||
"<a ref='https://www.example.com/'>PMA_BUFFER</a>"
|
||||
"<iframe srcdoc=\"<a ref='https://www.example.com/'>PMA_BUFFER</a>\" sandbox=\"\"></iframe>"
|
||||
),
|
||||
array(
|
||||
new Text_Plain_Formatted(),
|
||||
array(
|
||||
"<a ref=\"https://www.example.com/\">PMA_BUFFER</a>",
|
||||
array("option1", "option2")
|
||||
),
|
||||
"<iframe srcdoc=\"<a ref='https://www.example.com/'>PMA_BUFFER</a>\" sandbox=\"\"></iframe>"
|
||||
),
|
||||
array(
|
||||
new Text_Plain_Imagelink(),
|
||||
array(
|
||||
'PMA_IMAGE',
|
||||
array("http://image/", "200")
|
||||
),
|
||||
'<a href="http://image/PMA_IMAGE" rel="noopener noreferrer" target="_blank">'
|
||||
. '<img src="http://image/PMA_IMAGE" border="0" width="200" '
|
||||
. 'height="50" />PMA_IMAGE</a>'
|
||||
),
|
||||
array(
|
||||
new Text_Plain_Imagelink(),
|
||||
@ -874,9 +892,7 @@ class TransformationPluginsTest extends PMATestCase
|
||||
'PMA_IMAGE',
|
||||
array("./image/", "200")
|
||||
),
|
||||
'<a href="./image/PMA_IMAGE" target="_blank">'
|
||||
. '<img src="./image/PMA_IMAGE" border="0" width="200" '
|
||||
. 'height="50" />PMA_IMAGE</a>'
|
||||
'./image/PMA_IMAGE'
|
||||
),
|
||||
array(
|
||||
new Text_Plain_Sql(),
|
||||
@ -894,8 +910,32 @@ class TransformationPluginsTest extends PMATestCase
|
||||
'PMA_TXT_LINK',
|
||||
array("./php/", "text_name")
|
||||
),
|
||||
'<a href="./php/PMA_TXT_LINK"'
|
||||
. ' title="text_name" target="_new">text_name</a>'
|
||||
'./php/PMA_TXT_LINK'
|
||||
),
|
||||
array(
|
||||
new Text_Plain_Link(),
|
||||
array(
|
||||
'PMA_TXT_LINK',
|
||||
array(),
|
||||
),
|
||||
'PMA_TXT_LINK'
|
||||
),
|
||||
array(
|
||||
new Text_Plain_Link(),
|
||||
array(
|
||||
'https://example.com/PMA_TXT_LINK',
|
||||
array(),
|
||||
),
|
||||
'<a href="https://example.com/PMA_TXT_LINK" title=""'
|
||||
. ' target="_blank" rel="noopener noreferrer">https://example.com/PMA_TXT_LINK</a>'
|
||||
),
|
||||
array(
|
||||
new Text_Plain_Link(),
|
||||
array(
|
||||
'PMA_TXT_LINK',
|
||||
array("./php/", "text_name")
|
||||
),
|
||||
'./php/PMA_TXT_LINK'
|
||||
),
|
||||
array(
|
||||
new Text_Plain_Longtoipv4(),
|
||||
|
||||
@ -44,39 +44,64 @@ class PMA_Ip_Allow_Deny_Test extends PHPUnit_Framework_TestCase
|
||||
$GLOBALS['cfg']['Server']['AllowDeny']['rules'][] = "deny % 255.255.0.0/8";
|
||||
$GLOBALS['cfg']['Server']['AllowDeny']['rules'][]
|
||||
= "deny % from 255.255.0.0/8";
|
||||
include_once 'libraries/ip_allow_deny.lib.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for PMA_getIp
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @dataProvider proxyIPs
|
||||
*/
|
||||
public function testGetIp()
|
||||
public function testGetIp($remote, $header, $expected, $proxyip = null)
|
||||
{
|
||||
//$_SERVER['REMOTE_ADDR'] is empty
|
||||
unset($_SERVER['REMOTE_ADDR']);
|
||||
unset($_SERVER['TEST_FORWARDED_HEADER']);
|
||||
$GLOBALS['cfg']['TrustedProxies'] = array();
|
||||
|
||||
if (!is_null($remote)) {
|
||||
$_SERVER['REMOTE_ADDR'] = $remote;
|
||||
}
|
||||
|
||||
if (!is_null($header)) {
|
||||
if (is_null($proxyip)) {
|
||||
$proxyip = $remote;
|
||||
}
|
||||
$GLOBALS['cfg']['TrustedProxies'][$proxyip] = 'TEST_FORWARDED_HEADER';
|
||||
$_SERVER['TEST_FORWARDED_HEADER'] = $header;
|
||||
}
|
||||
|
||||
$this->assertEquals(
|
||||
false,
|
||||
$expected,
|
||||
PMA_getIp()
|
||||
);
|
||||
|
||||
$_SERVER['REMOTE_ADDR'] = "101.0.0.25";
|
||||
$this->assertEquals(
|
||||
"101.0.0.25",
|
||||
PMA_getIp()
|
||||
);
|
||||
unset($_SERVER['REMOTE_ADDR']);
|
||||
unset($_SERVER['TEST_FORWARDED_HEADER']);
|
||||
$GLOBALS['cfg']['TrustedProxies'] = array();
|
||||
}
|
||||
|
||||
//proxy
|
||||
$var_name = "direct_ip";
|
||||
$direct_ip = $_SERVER['REMOTE_ADDR'];
|
||||
$GLOBALS['cfg']['TrustedProxies'][$direct_ip] = $var_name;
|
||||
$_SERVER[$var_name] = "192.168.0.1";
|
||||
$this->assertEquals(
|
||||
"192.168.0.1",
|
||||
PMA_getIp()
|
||||
/**
|
||||
* Data provider for PMA_getIp tests
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function proxyIPs()
|
||||
{
|
||||
return array(
|
||||
// Nothing set
|
||||
array(null, null, false),
|
||||
// Remote IP set
|
||||
array('101.0.0.25', null, '101.0.0.25'),
|
||||
// Proxy
|
||||
array('101.0.0.25', '192.168.10.10', '192.168.10.10'),
|
||||
// Several proxies
|
||||
array('101.0.0.25', '192.168.10.1, 192.168.100.100', '192.168.10.1'),
|
||||
// Invalid proxy
|
||||
array('101.0.0.25', 'invalid', false),
|
||||
// Direct IP with proxy enabled
|
||||
array('101.0.0.25', '192.168.10.10', '101.0.0.25', '10.10.10.10'),
|
||||
);
|
||||
unset($_SERVER[$var_name]);
|
||||
unset($GLOBALS['cfg']['TrustedProxies'][$direct_ip]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -118,10 +118,16 @@ class PMA_ZipExtension_Test extends PHPUnit_Framework_TestCase
|
||||
public function testZipExtract()
|
||||
{
|
||||
$this->assertEquals(
|
||||
false,
|
||||
PMA_zipExtract(
|
||||
'./test/test_data/test.zip', './test/test_data/', 'wrongName'
|
||||
),
|
||||
true
|
||||
'./test/test_data/test.zip', 'wrongName'
|
||||
)
|
||||
);
|
||||
$this->assertEquals(
|
||||
"TEST FILE\n",
|
||||
PMA_zipExtract(
|
||||
'./test/test_data/test.zip', 'test.file'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
53
test/libraries/core/PMA_isAllowedDomain_test.php
Normal file
53
test/libraries/core/PMA_isAllowedDomain_test.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Test for PMA_isAllowedDomain
|
||||
*
|
||||
* @package PhpMyAdmin-test
|
||||
*/
|
||||
|
||||
/*
|
||||
* Include to test.
|
||||
*/
|
||||
require_once 'libraries/core.lib.php';
|
||||
|
||||
class PMA_isAllowedDomain_test extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* Test for unserializing
|
||||
*
|
||||
* @param string $url URL to test
|
||||
* @param mixed $expected Expected result
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @dataProvider provideURLs
|
||||
*/
|
||||
function testIsAllowedDomain($url, $expected)
|
||||
{
|
||||
$_SERVER['SERVER_NAME'] = 'server.local';
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
PMA_isAllowedDomain($url)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test data provider
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function provideURLs()
|
||||
{
|
||||
return array(
|
||||
array('https://www.phpmyadmin.net/', true),
|
||||
array('http://duckduckgo.com\\@github.com', false),
|
||||
array('https://github.com/', true),
|
||||
array('https://server.local/', true),
|
||||
array('./relative/', false),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
55
test/libraries/core/PMA_safeUnserialize_test.php
Normal file
55
test/libraries/core/PMA_safeUnserialize_test.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Test for PMA_safeUnserialize
|
||||
*
|
||||
* @package PhpMyAdmin-test
|
||||
*/
|
||||
|
||||
/*
|
||||
* Include to test.
|
||||
*/
|
||||
require_once 'libraries/core.lib.php';
|
||||
|
||||
class PMA_safeUnserialize_test extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* Test for unserializing
|
||||
*
|
||||
* @param string $data Serialized data
|
||||
* @param mixed $expected Expected result
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @dataProvider provideMySQLHosts
|
||||
*/
|
||||
function testSanitizeMySQLHost($data, $expected)
|
||||
{
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
PMA_safeUnserialize($data)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test data provider
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function provideMySQLHosts()
|
||||
{
|
||||
return array(
|
||||
array('s:6:"foobar";', 'foobar'),
|
||||
array('foobar', null),
|
||||
array('b:0;', false),
|
||||
array('O:1:"a":1:{s:5:"value";s:3:"100";}', null),
|
||||
array('O:8:"stdClass":1:{s:5:"field";O:8:"stdClass":0:{}}', null),
|
||||
array(serialize(array(1, 2, 3)), array(1, 2, 3)),
|
||||
array(serialize('string""'), 'string""'),
|
||||
array(serialize(array('foo' => 'bar')), array('foo' => 'bar')),
|
||||
array(serialize(array('1', new stdClass(), '2')), null),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
48
test/libraries/core/PMA_sanitizeMySQLHost_test.php
Normal file
48
test/libraries/core/PMA_sanitizeMySQLHost_test.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Test for PMA_sanitizeMySQLHost
|
||||
*
|
||||
* @package PhpMyAdmin-test
|
||||
*/
|
||||
|
||||
/*
|
||||
* Include to test.
|
||||
*/
|
||||
require_once 'libraries/core.lib.php';
|
||||
|
||||
class PMA_sanitizeMySQLHost_test extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* Test for MySQL host sanitizing
|
||||
*
|
||||
* @param string $host Test host name
|
||||
* @param string $expected Expected result
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @dataProvider provideMySQLHosts
|
||||
*/
|
||||
function testSanitizeMySQLHost($host, $expected)
|
||||
{
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
PMA_sanitizeMySQLHost($host)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test data provider
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function provideMySQLHosts()
|
||||
{
|
||||
return array(
|
||||
array('p:foo.bar', 'foo.bar'),
|
||||
array('bar.baz', 'bar.baz'),
|
||||
array('P:example.com', 'example.com'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -23,7 +23,7 @@ $hash = '#pma_' . preg_replace('/([0-9]*)\.([0-9]*)\..*/', '\1_\2', PMA_VERSI
|
||||
$url = PMA_linkURL('https://www.phpmyadmin.net/themes/') . $hash;
|
||||
$output = '<h1>phpMyAdmin - ' . __('Theme') . '</h1>';
|
||||
$output .= '<p>';
|
||||
$output .= '<a href="' . $url . '" class="_blank">';
|
||||
$output .= '<a href="' . $url . '" rel="noopener noreferrer" class="_blank">';
|
||||
$output .= __('Get more themes!');
|
||||
$output .= '</a>';
|
||||
$output .= '</p>';
|
||||
|
||||
@ -34,9 +34,20 @@ $request_params = array(
|
||||
'transform_key',
|
||||
'where_clause'
|
||||
);
|
||||
$size_params = array(
|
||||
'newHeight',
|
||||
'newWidth',
|
||||
);
|
||||
foreach ($request_params as $one_request_param) {
|
||||
if (isset($_REQUEST[$one_request_param])) {
|
||||
$GLOBALS[$one_request_param] = $_REQUEST[$one_request_param];
|
||||
if (in_array($one_request_param, $size_params)) {
|
||||
$GLOBALS[$one_request_param] = intval($_REQUEST[$one_request_param]);
|
||||
if ($GLOBALS[$one_request_param] > 2000) {
|
||||
$GLOBALS[$one_request_param] = 2000;
|
||||
}
|
||||
} else {
|
||||
$GLOBALS[$one_request_param] = $_REQUEST[$one_request_param];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,7 +102,7 @@ $response->getHeader()->sendHttpHeaders();
|
||||
if (isset($ct) && ! empty($ct)) {
|
||||
$mime_type = $ct;
|
||||
} else {
|
||||
$mime_type = (isset($mime_map[$transform_key]['mimetype'])
|
||||
$mime_type = (!empty($mime_map[$transform_key]['mimetype'])
|
||||
? str_replace('_', '/', $mime_map[$transform_key]['mimetype'])
|
||||
: $default_ct)
|
||||
. (isset($mime_options['charset']) ? $mime_options['charset'] : '');
|
||||
@ -100,7 +111,11 @@ if (isset($ct) && ! empty($ct)) {
|
||||
PMA_downloadHeader($cn, $mime_type);
|
||||
|
||||
if (! isset($_REQUEST['resize'])) {
|
||||
echo $row[$transform_key];
|
||||
if (stripos($mime_type, 'html') === false) {
|
||||
echo $row[$transform_key];
|
||||
} else {
|
||||
echo htmlspecialchars($row[$transform_key]);
|
||||
}
|
||||
} else {
|
||||
// if image_*__inline.inc.php finds that we can resize,
|
||||
// it sets the resize parameter to jpeg or png
|
||||
|
||||
5
url.php
5
url.php
@ -13,6 +13,11 @@ use PMA\libraries\Sanitize;
|
||||
define('PMA_MINIMUM_COMMON', true);
|
||||
require_once './libraries/common.inc.php';
|
||||
|
||||
// Only output the http headers
|
||||
$response = PMA\libraries\Response::getInstance();
|
||||
$response->getHeader()->sendHttpHeaders();
|
||||
$response->disable();
|
||||
|
||||
if (! PMA_isValid($_REQUEST['url'])
|
||||
|| ! preg_match('/^https:\/\/[^\n\r]*$/', $_REQUEST['url'])
|
||||
|| ! PMA_isAllowedDomain($_REQUEST['url'])
|
||||
|
||||
@ -121,6 +121,9 @@ function PMA_setChangePasswordMsg()
|
||||
__('The passwords aren\'t the same!')
|
||||
);
|
||||
$error = true;
|
||||
} elseif (strlen($_REQUEST['pma_pw']) > 256) {
|
||||
$message = PMA_Message::error(__('Password is too long!'));
|
||||
$error = true;
|
||||
}
|
||||
}
|
||||
return array('error' => $error, 'msg' => $message);
|
||||
|
||||
@ -9,9 +9,12 @@
|
||||
// Sets up the session
|
||||
use PMA\libraries\VersionInformation;
|
||||
|
||||
define('PMA_MINIMUM_COMMON', true);
|
||||
$_GET['ajax_request'] = 'true';
|
||||
|
||||
require_once 'libraries/common.inc.php';
|
||||
require_once 'libraries/VersionInformation.php';
|
||||
|
||||
// Disabling standard response.
|
||||
PMA\libraries\Response::getInstance()->disable();
|
||||
|
||||
// Always send the correct headers
|
||||
PMA_headerJSON();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user