Merge remote-tracking branch 'security/QA_4_6-security' into QA_4_6
This commit is contained in:
commit
0f6b76b578
@ -3,7 +3,7 @@ imports:
|
||||
- javascript
|
||||
- php
|
||||
filter:
|
||||
excluded_paths: [libraries/php-gettext/*, libraries/tcpdf/*, libraries/bfShapeFiles/*, libraries/phpseclib/*, libraries/plugins/auth/recaptchalib.php, libraries/plugins/auth/swekey/swekey.php, libraries/sql-formatter/*, js/jquery/*, js/jqplot/*, js/openlayers/*, js/codemirror/*, js/canvg/*, js/tracekit/*, js/OpenStreetMap.js, js/sprintf.js, test/libraries/php-gettext/*, test/libraries/sql-formatter/*]
|
||||
excluded_paths: [libraries/php-gettext/*, libraries/tcpdf/*, libraries/bfShapeFiles/*, libraries/phpseclib/*, libraries/plugins/auth/recaptchalib.php, libraries/sql-formatter/*, js/jquery/*, js/jqplot/*, js/openlayers/*, js/codemirror/*, js/canvg/*, js/tracekit/*, js/OpenStreetMap.js, js/sprintf.js, test/libraries/php-gettext/*, test/libraries/sql-formatter/*]
|
||||
tools:
|
||||
php_code_sniffer:
|
||||
config:
|
||||
|
||||
@ -55,7 +55,7 @@
|
||||
<arg line="${source_comma_sep}
|
||||
xml
|
||||
codesize,design,naming,unusedcode
|
||||
--exclude test,build,tcpdf,php-gettext,bfShapeFiles,phpseclib,recaptchalib.php,swekey.php,vendor,sql-parser
|
||||
--exclude test,build,tcpdf,php-gettext,bfShapeFiles,phpseclib,recaptchalib.php,vendor,sql-parser
|
||||
--reportfile '${basedir}/build/logs/pmd.xml'" />
|
||||
</exec>
|
||||
</target>
|
||||
@ -71,7 +71,6 @@
|
||||
--exclude libraries/bfShapeFiles
|
||||
--exclude libraries/phpseclib
|
||||
--exclude libraries/plugins/auth/recaptcha/recaptchalib.php
|
||||
--exclude libraries/plugins/auth/swekey/swekey.php
|
||||
--exclude libraries/sql-parser
|
||||
${source}" />
|
||||
</exec>
|
||||
@ -88,7 +87,6 @@
|
||||
--exclude libraries/bfShapeFiles
|
||||
--exclude libraries/phpseclib
|
||||
--exclude libraries/plugins/auth/recaptcha/recaptchalib.php
|
||||
--exclude libraries/plugins/auth/swekey/swekey.php
|
||||
--exclude libraries/sql-parser
|
||||
${source}" />
|
||||
</exec>
|
||||
@ -103,7 +101,7 @@
|
||||
<target name="phpcs" description="Generate checkstyle.xml using PHP_CodeSniffer excluding third party libraries" depends="phpcs-config">
|
||||
<exec executable="phpcs">
|
||||
<arg line="
|
||||
--ignore=*/php-gettext/*,*/vendor/*,*/tcpdf/*,*/canvg/*,*/codemirror/*,*/openlayers/*,*/jquery/*,*/jqplot/*,*/build/*,*/bfShapeFiles/*,*/phpseclib/*,*/recaptcha/*,*/swekey/*,*/sql-parser/*
|
||||
--ignore=*/php-gettext/*,*/vendor/*,*/tcpdf/*,*/canvg/*,*/codemirror/*,*/openlayers/*,*/jquery/*,*/jqplot/*,*/build/*,*/bfShapeFiles/*,*/phpseclib/*,*/recaptcha/*,*/sql-parser/*
|
||||
--report=checkstyle
|
||||
--extensions=php
|
||||
--report-file='${basedir}/build/logs/checkstyle.xml'
|
||||
|
||||
@ -13,6 +13,7 @@ require 'libraries/common.inc.php';
|
||||
|
||||
$response = PMA\libraries\Response::getInstance();
|
||||
$response->disable();
|
||||
$response->getHeader()->sendHttpHeaders();
|
||||
|
||||
$filename = CHANGELOG_FILE;
|
||||
|
||||
@ -154,6 +155,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! */
|
||||
|
||||
@ -64,8 +64,6 @@ $cfg['Servers'][$i]['AllowNoPassword'] = false;
|
||||
// $cfg['Servers'][$i]['central_columns'] = 'pma__central_columns';
|
||||
// $cfg['Servers'][$i]['designer_settings'] = 'pma__designer_settings';
|
||||
// $cfg['Servers'][$i]['export_templates'] = 'pma__export_templates';
|
||||
/* Contrib / Swekey authentication */
|
||||
// $cfg['Servers'][$i]['auth_swekey_config'] = '/etc/swekey-pma.conf';
|
||||
|
||||
/**
|
||||
* End of servers configuration
|
||||
|
||||
@ -414,15 +414,6 @@ Server connection settings
|
||||
"phpMyAdmin " and either :config:option:`$cfg['Servers'][$i]['verbose']` or
|
||||
:config:option:`$cfg['Servers'][$i]['host']` will be used.
|
||||
|
||||
.. _servers_auth_swekey_config:
|
||||
.. config:option:: $cfg['Servers'][$i]['auth_swekey_config']
|
||||
|
||||
:type: string
|
||||
:default: ``''``
|
||||
|
||||
The name of the file containing :ref:`swekey` ids and login names for hardware
|
||||
authentication. Leave empty to deactivate this feature.
|
||||
|
||||
.. _servers_user:
|
||||
.. config:option:: $cfg['Servers'][$i]['user']
|
||||
|
||||
@ -1473,7 +1464,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::
|
||||
|
||||
@ -1833,11 +1827,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
|
||||
@ -1848,18 +1837,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
|
||||
|
||||
@ -248,7 +248,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++;
|
||||
@ -738,40 +739,6 @@ Config authentication mode
|
||||
of which are beyond the scope of this manual but easily searchable
|
||||
with Google).
|
||||
|
||||
.. index:: pair: Swekey; Authentication mode
|
||||
|
||||
.. _swekey:
|
||||
|
||||
Swekey authentication mode
|
||||
--------------------------
|
||||
|
||||
The Swekey is a low cost authentication USB key that can be used in
|
||||
web applications. When Swekey authentication is activated, phpMyAdmin
|
||||
requires the users's Swekey to be plugged before entering the login
|
||||
page (currently supported for cookie authentication mode only). Swekey
|
||||
Authentication is disabled by default. To enable it, add the following
|
||||
line to :file:`config.inc.php`:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$cfg['Servers'][$i]['auth_swekey_config'] = '/etc/swekey.conf';
|
||||
|
||||
You then have to create the ``swekey.conf`` file that will associate
|
||||
each user with their Swekey Id. It is important to place this file
|
||||
outside of your web server's document root (in the example, it is
|
||||
located in ``/etc``). Feel free to use it with your own users'
|
||||
information. If you want to purchase a Swekey please visit
|
||||
`https://www.phpmyadmin.net/auth\_key/ <https://www.phpmyadmin.net/auth_key/>`_
|
||||
since this link provides funding for phpMyAdmin.
|
||||
|
||||
A self documented sample file is provided in the
|
||||
file :file:`examples/swekey.sample.conf`:
|
||||
|
||||
.. literalinclude:: ../examples/swekey.sample.conf
|
||||
:language: sh
|
||||
|
||||
.. seealso:: :config:option:`$cfg['Servers'][$i]['auth_swekey_config']`
|
||||
|
||||
|
||||
Securing your phpMyAdmin installation
|
||||
+++++++++++++++++++++++++++++++++++++
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -1,44 +0,0 @@
|
||||
# This is a typical file used to enable Swekey hardware authentication.
|
||||
#
|
||||
# To activate the Swekey authentication add the following line to your config.inc.php file.
|
||||
# $cfg['Servers'][$i]['auth_swekey_config'] = '/etc/swekey-pma.conf';
|
||||
# Then rename this file "swekey-pma.conf" and copy it to the /etc directory.
|
||||
# Add all the Swekey ids you want to grant access to in the file.
|
||||
# After each Swekey id put the corresponding user name.
|
||||
#
|
||||
# If you don't know the id of a Swekey just visit http://www.swekey.com?sel=support
|
||||
# while your Swekey is connected.
|
||||
#
|
||||
# If you need to purchase a Swekey please visit https://www.phpmyadmin.net/auth_key/
|
||||
# since this link provides funding to PhpMyAdmin.
|
||||
#
|
||||
|
||||
0000000000000000000000000000763A:root
|
||||
000000000000000000000000000089E4:steve
|
||||
0000000000000000000000000000231E:scott
|
||||
|
||||
#
|
||||
# It is recommended to include the following lines to contact the
|
||||
# authentication servers in SSL mode.
|
||||
#
|
||||
|
||||
SERVER_CHECK=https://auth-check-ssl.musbe.net
|
||||
SERVER_RNDTOKEN=https://auth-rnd-gen-ssl.musbe.net
|
||||
SERVER_STATUS=https://auth-status-ssl.musbe.net
|
||||
|
||||
#
|
||||
# The path of the root certificate file used to ensure a secure
|
||||
# communication with the authentication servers in SSL mode.
|
||||
# If not specified, will use musbe-ca.crt found in your
|
||||
# phpMyAdmin/libraries/auth/swekey.
|
||||
#
|
||||
|
||||
#CA_FILE=/var/http-root/phpmyadmin/libraries/auth/swekey/musbe-ca.crt
|
||||
|
||||
#
|
||||
# If your server receives many login requests, you can enable the random
|
||||
# token caching to accelerate the authentication process.
|
||||
# Token caching is enabled by default.
|
||||
#
|
||||
|
||||
#ENABLE_TOKEN_CACHE=0
|
||||
@ -10,59 +10,7 @@
|
||||
define('PMA_MINIMUM_COMMON', true);
|
||||
require_once 'libraries/common.inc.php';
|
||||
|
||||
/* For chart exporting */
|
||||
if (isset($_REQUEST['filename']) && isset($_REQUEST['image'])) {
|
||||
$allowed = array(
|
||||
'image/png' => 'png',
|
||||
'image/svg+xml' => 'svg',
|
||||
);
|
||||
|
||||
/* Check whether MIME type is allowed */
|
||||
if (! isset($allowed[$_REQUEST['type']])) {
|
||||
PMA_fatalError(__('Invalid export type'));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check file name to match mime type and not contain new lines
|
||||
* to prevent response splitting.
|
||||
*/
|
||||
$extension = $allowed[$_REQUEST['type']];
|
||||
$valid_match = '/^[^\n\r]*\.' . $extension . '$/';
|
||||
if (! preg_match($valid_match, $_REQUEST['filename'])) {
|
||||
if (! preg_match('/^[^\n\r]*$/', $_REQUEST['filename'])) {
|
||||
/* Filename is unsafe, discard it */
|
||||
$filename = 'download.' . $extension;
|
||||
} else {
|
||||
/* Add extension */
|
||||
$filename = $_REQUEST['filename'] . '.' . $extension;
|
||||
}
|
||||
} else {
|
||||
/* Filename from request should be safe here */
|
||||
$filename = $_REQUEST['filename'];
|
||||
}
|
||||
|
||||
/* Decode data */
|
||||
if ($extension != 'svg') {
|
||||
$data = mb_substr(
|
||||
$_REQUEST['image'],
|
||||
mb_strpos($_REQUEST['image'], ',') + 1
|
||||
);
|
||||
$data = base64_decode($data);
|
||||
} else {
|
||||
$data = $_REQUEST['image'];
|
||||
}
|
||||
|
||||
/* Send download header */
|
||||
PMA_downloadHeader(
|
||||
$filename,
|
||||
$_REQUEST['type'],
|
||||
strlen($data)
|
||||
);
|
||||
|
||||
/* Send data */
|
||||
echo $data;
|
||||
|
||||
} else if (isset($_REQUEST['monitorconfig'])) {
|
||||
if (isset($_REQUEST['monitorconfig'])) {
|
||||
/* For monitor chart config export */
|
||||
PMA_downloadHeader('monitor.cfg', 'application/json; charset=UTF-8');
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
|
||||
14
import.php
14
import.php
@ -7,6 +7,11 @@
|
||||
*/
|
||||
use PMA\libraries\plugins\ImportPlugin;
|
||||
|
||||
/* 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
|
||||
*/
|
||||
@ -435,6 +440,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
@ -317,7 +317,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>';
|
||||
@ -357,15 +357,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>';
|
||||
}
|
||||
@ -519,15 +510,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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -4105,7 +4105,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));
|
||||
}
|
||||
|
||||
@ -353,10 +353,10 @@ class DbSearch
|
||||
$html_output .= '<td><a name="delete_search" class="ajax" href="'
|
||||
. $delete_result_path . '" onclick="deleteResult(\''
|
||||
. $delete_result_path . '\' , \''
|
||||
. sprintf(
|
||||
. PMA_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 = __('File could not be read!');
|
||||
$this->setName(null);
|
||||
|
||||
@ -96,7 +96,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);
|
||||
@ -119,7 +119,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) {
|
||||
|
||||
@ -1494,7 +1494,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) . "'";
|
||||
|
||||
@ -1522,7 +1522,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)) . "')";
|
||||
|
||||
|
||||
@ -2691,7 +2691,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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -309,7 +309,6 @@ $goto_whitelist = array(
|
||||
'index.php',
|
||||
'pdf_pages.php',
|
||||
'pdf_schema.php',
|
||||
//'phpinfo.php',
|
||||
'server_binlog.php',
|
||||
'server_collations.php',
|
||||
'server_databases.php',
|
||||
|
||||
@ -236,14 +236,6 @@ $cfg['Servers'][$i]['auth_type'] = 'cookie';
|
||||
*/
|
||||
$cfg['Servers'][$i]['auth_http_realm'] = '';
|
||||
|
||||
/**
|
||||
* File containing Swekey ids and login names (see /contrib);
|
||||
* leave empty to deactivate Swekey hardware authentication
|
||||
*
|
||||
* @global string $cfg['Servers'][$i]['auth_swekey_config']
|
||||
*/
|
||||
$cfg['Servers'][$i]['auth_swekey_config'] = '';
|
||||
|
||||
/**
|
||||
* MySQL user
|
||||
*
|
||||
@ -1046,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
|
||||
*
|
||||
|
||||
@ -214,10 +214,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);
|
||||
}
|
||||
@ -329,10 +341,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;
|
||||
|
||||
@ -632,12 +632,6 @@ $strConfigServers_SessionTimeZone_desc = __(
|
||||
$strConfigServers_auth_http_realm_desc
|
||||
= __('HTTP Basic Auth Realm name to display when doing HTTP Auth.');
|
||||
$strConfigServers_auth_http_realm_name = __('HTTP Realm');
|
||||
$strConfigServers_auth_swekey_config_desc = __(
|
||||
'The path for the config file for SweKey hardware '
|
||||
. 'authentication (not located in your document root; suggested: '
|
||||
. '/etc/swekey.conf).'
|
||||
);
|
||||
$strConfigServers_auth_swekey_config_name = __('SweKey config file');
|
||||
$strConfigServers_auth_type_desc = __('Authentication method to use.');
|
||||
$strConfigServers_auth_type_name = __('Authentication type');
|
||||
$strConfigServers_bookmarktable_desc = __(
|
||||
@ -871,11 +865,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.'
|
||||
|
||||
@ -41,9 +41,6 @@ $forms['Servers']['Server_auth'] = array('Servers' => array(1 => array(
|
||||
'user',
|
||||
'password',
|
||||
':group:end',
|
||||
':group:' . __('Cookie authentication'),
|
||||
'auth_swekey_config' => './swekey.conf',
|
||||
':group:end',
|
||||
':group:' . __('HTTP authentication'),
|
||||
'auth_http_realm',
|
||||
':group:end',
|
||||
@ -206,7 +203,6 @@ $forms['Main_panel']['Startup'] = array(
|
||||
'ShowCreateDb',
|
||||
'ShowStats',
|
||||
'ShowServerInfo',
|
||||
'ShowPhpInfo',
|
||||
'ShowChgPassword');
|
||||
$forms['Main_panel']['DbStructure'] = array(
|
||||
'ShowDbStructureComment',
|
||||
|
||||
@ -510,11 +510,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
|
||||
@ -759,6 +754,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 */
|
||||
@ -985,3 +984,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);
|
||||
}
|
||||
|
||||
@ -445,13 +445,16 @@ 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 = min(
|
||||
4096,
|
||||
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 = min(4096, 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 = min(4096, intval($_REQUEST['num_fields']));
|
||||
} else { // new table with unspecified number of fields
|
||||
$num_fields = 4;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -124,10 +124,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') && $cfg['Server']['compress']) {
|
||||
|
||||
@ -138,7 +138,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;
|
||||
|
||||
|
||||
@ -250,7 +250,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";
|
||||
|
||||
@ -178,7 +178,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',
|
||||
@ -195,26 +212,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())';
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,14 +30,21 @@ function PMA_getIp()
|
||||
return $direct_ip;
|
||||
}
|
||||
|
||||
$trusted_header_value
|
||||
= PMA_getenv($GLOBALS['cfg']['TrustedProxies'][$direct_ip]);
|
||||
$matches = array();
|
||||
/**
|
||||
* 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];
|
||||
// Extract IP address
|
||||
// the $ checks that the header contains only one IP address,
|
||||
// ?: makes sure the () don't capture
|
||||
$matches = array();
|
||||
$is_ip = preg_match(
|
||||
'|^(?:[0-9]{1,3}\.){3,3}[0-9]{1,3}$|',
|
||||
$trusted_header_value, $matches
|
||||
$value, $matches
|
||||
);
|
||||
|
||||
if ($is_ip && (count($matches) == 1)) {
|
||||
@ -45,8 +52,8 @@ function PMA_getIp()
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
/* Return true IP */
|
||||
return $direct_ip;
|
||||
// We could not parse header
|
||||
return false;
|
||||
} // end of the 'PMA_getIp()' function
|
||||
|
||||
|
||||
|
||||
@ -174,7 +174,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);
|
||||
|
||||
|
||||
@ -690,7 +690,7 @@ class NodeDatabase extends Node
|
||||
. '<a href="navigation.php'
|
||||
. PMA_URL_getCommon()
|
||||
. '&showUnhideDialog=true'
|
||||
. '&dbName=' . urldecode($this->real_name) . '"'
|
||||
. '&dbName=' . urlencode($this->real_name) . '"'
|
||||
. ' class="showUnhide ajax">'
|
||||
. Util::getImage(
|
||||
'lightbulb.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;
|
||||
|
||||
@ -27,11 +27,6 @@ if (! empty($_REQUEST['target'])) {
|
||||
$GLOBALS['target'] = basename(PMA_getenv('SCRIPT_NAME'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Swekey authentication functions.
|
||||
*/
|
||||
require './libraries/plugins/auth/swekey/swekey.auth.lib.php';
|
||||
|
||||
/**
|
||||
* Handles the cookie authentication method
|
||||
*
|
||||
@ -229,10 +224,6 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
echo '</fieldset>
|
||||
</form>';
|
||||
|
||||
// BEGIN Swekey Integration
|
||||
Swekey_login('input_username', 'input_go');
|
||||
// END Swekey Integration
|
||||
|
||||
if ($GLOBALS['error_handler']->hasDisplayErrors()) {
|
||||
echo '<div id="pma_errors">';
|
||||
$GLOBALS['error_handler']->dispErrors();
|
||||
@ -279,12 +270,6 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
$GLOBALS['PHP_AUTH_USER'] = $GLOBALS['PHP_AUTH_PW'] = '';
|
||||
$GLOBALS['from_cookie'] = false;
|
||||
|
||||
// BEGIN Swekey Integration
|
||||
if (! Swekey_Auth_check()) {
|
||||
return false;
|
||||
}
|
||||
// END Swekey Integration
|
||||
|
||||
if (! empty($_REQUEST['pma_username'])) {
|
||||
|
||||
// Verify Captcha if it is required.
|
||||
@ -341,7 +326,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;
|
||||
@ -350,18 +335,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;
|
||||
}
|
||||
|
||||
@ -398,17 +373,23 @@ 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 ($GLOBALS['PHP_AUTH_PW'] == "\xff(blank)") {
|
||||
$GLOBALS['PHP_AUTH_PW'] = '';
|
||||
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;
|
||||
@ -485,8 +466,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']);
|
||||
@ -501,21 +480,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';
|
||||
|
||||
@ -585,11 +549,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(
|
||||
! empty($password) ? $password : "\xff(blank)",
|
||||
json_encode($payload),
|
||||
$this->_getSessionEncryptionSecret()
|
||||
),
|
||||
null,
|
||||
@ -613,7 +581,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();
|
||||
|
||||
@ -636,8 +604,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'];
|
||||
}
|
||||
}
|
||||
|
||||
@ -650,9 +617,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'];
|
||||
@ -672,6 +639,64 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
@ -683,20 +708,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,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -706,33 +742,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']));
|
||||
}
|
||||
}
|
||||
|
||||
@ -760,24 +802,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
|
||||
@ -809,17 +853,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();
|
||||
|
||||
@ -1,176 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Authentication functions
|
||||
*
|
||||
* @package Swekey
|
||||
*/
|
||||
?>
|
||||
|
||||
<script>
|
||||
|
||||
var g_SwekeyPlugin = null;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Create the swekey plugin if it does not exists
|
||||
function Swekey_Plugin()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (g_SwekeyPlugin != null)
|
||||
return g_SwekeyPlugin;
|
||||
|
||||
if (window.ActiveXObject)
|
||||
{
|
||||
g_SwekeyPlugin = document.getElementById("swekey_activex");
|
||||
if (g_SwekeyPlugin == null)
|
||||
{
|
||||
// we must create the activex that way instead of
|
||||
// new ActiveXObject("FbAuthAx.FbAuthCtl");
|
||||
// otherwise SetClientSite is not called and
|
||||
// we can not get the url
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML='<object id="swekey_activex" style="display:none" CLASSID="CLSID:8E02E3F9-57AA-4EE1-AA68-A42DD7B0FADE"></object>';
|
||||
|
||||
// Never append to the body because it may still loading and it breaks IE
|
||||
document.body.insertBefore(div, document.body.firstChild);
|
||||
g_SwekeyPlugin = document.getElementById("swekey_activex");
|
||||
}
|
||||
return g_SwekeyPlugin;
|
||||
}
|
||||
|
||||
g_SwekeyPlugin = document.getElementById("swekey_plugin");
|
||||
if (g_SwekeyPlugin != null)
|
||||
return g_SwekeyPlugin;
|
||||
|
||||
for (i = 0; i < navigator.plugins.length; i ++)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (navigator.plugins[i] == null)
|
||||
{
|
||||
navigator.plugins.refresh();
|
||||
}
|
||||
else if (navigator.plugins[i][0] != null && navigator.plugins[i][0].type == "application/fbauth-plugin")
|
||||
{
|
||||
var x = document.createElement('embed');
|
||||
x.setAttribute('type', 'application/fbauth-plugin');
|
||||
x.setAttribute('id', 'swekey_plugin');
|
||||
x.setAttribute('width', '0');
|
||||
x.setAttribute('height', '0');
|
||||
x.style.dislay='none';
|
||||
|
||||
//document.body.appendChild(x);
|
||||
document.body.insertBefore(x, document.body.firstChild);
|
||||
g_SwekeyPlugin = document.getElementById("swekey_plugin");
|
||||
return g_SwekeyPlugin;
|
||||
}
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
navigator.plugins.refresh();
|
||||
//alert ('Failed to create plugin: ' + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
//alert("Swekey_Plugin " + e);
|
||||
g_SwekeyPlugin = null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Returns true if the swekey plugin is installed
|
||||
function Swekey_Installed()
|
||||
{
|
||||
return (Swekey_Plugin() != null);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// List the id of the Swekey connected to the PC
|
||||
// Returns a string containing comma separated Swekey Ids
|
||||
// A Swekey is a 32 char hexadecimal value.
|
||||
function Swekey_ListKeyIds()
|
||||
{
|
||||
try
|
||||
{
|
||||
return Swekey_Plugin().list();
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
// alert("Swekey_ListKeyIds " + e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Ask the Connected Swekey to generate an OTP
|
||||
// id: The id of the connected Swekey (returne by Swekey_ListKeyIds())
|
||||
// rt: A random token
|
||||
// return: The calculated OTP encoded in a 64 chars hexadecimal value.
|
||||
function Swekey_GetOtp(id, rt)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Swekey_Plugin().getotp(id, rt);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
// alert("Swekey_GetOtp " + e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Ask the Connected Swekey to generate a OTP linked to the current https host
|
||||
// id: The id of the connected Swekey (returne by Swekey_ListKeyIds())
|
||||
// rt: A random token
|
||||
// return: The calculated OTP encoded in a 64 chars hexadecimal value.
|
||||
// or "" if the current url does not start with https
|
||||
function Swekey_GetLinkedOtp(id, rt)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Swekey_Plugin().getlinkedotp(id, rt);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
// alert("Swekey_GetSOtp " + e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Calls Swekey_GetOtp or Swekey_GetLinkedOtp depending if we are in
|
||||
// an https page or not.
|
||||
// id: The id of the connected Swekey (returne by Swekey_ListKeyIds())
|
||||
// rt: A random token
|
||||
// return: The calculated OTP encoded in a 64 chars hexadecimal value.
|
||||
function Swekey_GetSmartOtp(id, rt)
|
||||
{
|
||||
var res = Swekey_GetLinkedOtp(id, rt);
|
||||
if (res == "")
|
||||
res = Swekey_GetOtp(id, rt);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Set a unplug handler (url) to the specified connected feebee
|
||||
// id: The id of the connected Swekey (returne by Swekey_ListKeyIds())
|
||||
// key: The key that index that url, (aplhanumeric values only)
|
||||
// url: The url that will be launched ("" deletes the url)
|
||||
function Swekey_SetUnplugUrl(id, key, url)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Swekey_Plugin().setunplugurl(id, key, url);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
// alert("Swekey_SetUnplugUrl " + e);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
@ -1,25 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEKjCCAxKgAwIBAgIJAMjw7QcLWCd6MA0GCSqGSIb3DQEBBQUAMGsxCzAJBgNV
|
||||
BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQKEwtNdXNiZSwgSW5j
|
||||
LjESMBAGA1UEAxMJbXVzYmUuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQG11c2Jl
|
||||
LmNvbTAeFw0wODA5MDQxNDE2MTNaFw0zNzEyMjExNDE2MTNaMGsxCzAJBgNVBAYT
|
||||
AlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQKEwtNdXNiZSwgSW5jLjES
|
||||
MBAGA1UEAxMJbXVzYmUuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQG11c2JlLmNv
|
||||
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOBhOljxVzQfK4gted2I
|
||||
d3BemcjW4abAUOzn3KYWXpPO5xIfVeXNDGkDbyH+X+7fo94sX25/ewuKNFDSOcvo
|
||||
tXHq7uQenTHB35r+a+LY81KceUHgW90a3XsqPAkwAjyYcgo3zmM2DtLvw+5Yod8T
|
||||
wAHk9m3qavnQ1uk99jBTwL7RZ9jIZHh9pFCL93uJc2obtd8O96Iycbn2q0w/AWbb
|
||||
+eUVWIHzvLtfPvROeL3lJzr/Uz5LjKapxJ3qyqASflfHpnj9pU8l6g2TQ6Hg5KT5
|
||||
tLFkRe7uGhOfRtOQ/+NjaWrEuNCFnpyN4Q5Fv+5qA1Ip1IpH0200sWbAf/k2u0Qp
|
||||
Sx0CAwEAAaOB0DCBzTAdBgNVHQ4EFgQUczJrQ7hCvtsnzcqiDIZ/GSn/CiwwgZ0G
|
||||
A1UdIwSBlTCBkoAUczJrQ7hCvtsnzcqiDIZ/GSn/Ciyhb6RtMGsxCzAJBgNVBAYT
|
||||
AlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQKEwtNdXNiZSwgSW5jLjES
|
||||
MBAGA1UEAxMJbXVzYmUuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQG11c2JlLmNv
|
||||
bYIJAMjw7QcLWCd6MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGxk
|
||||
8xzIljeBDQWWVRr0NEALVSv3i09V4jAKkyEOfmZ8lKMKJi0atwbtjrXTzLnNYj+Q
|
||||
pyUbyY/8ItWvV7pnVxMiF9qcer7e9X4vw358GZuMVE/da1nWxz+CwzTm5oO30RzA
|
||||
antM9bISFFr9lJq69bDWOnCUi1IG8DSL3TxtlABso7S4vqiZ+sB33l6k1K4a/Njb
|
||||
QkU9UejKhKkVVZTsOrumfnOJ4MCmPfX8Y/AY2o670y5HnzpxerIYziCVzApPVrW7
|
||||
sKH0tuVGturMfQOKgstYe4/m9glBTeTLMkjD+6MJC2ONBD7GAiOO95gNl5M1fzJQ
|
||||
FEe5CJ7DCYl0GdmLXXw=
|
||||
-----END CERTIFICATE-----
|
||||
@ -1,315 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Swekey
|
||||
*
|
||||
* @package Swekey
|
||||
*/
|
||||
|
||||
use PMA\libraries\Message;
|
||||
|
||||
/**
|
||||
* Checks Swekey authentication.
|
||||
*
|
||||
* @return boolean whether authentication succeeded or not
|
||||
*/
|
||||
function Swekey_Auth_check()
|
||||
{
|
||||
global $cfg;
|
||||
$confFile = $cfg['Server']['auth_swekey_config'];
|
||||
|
||||
if (! isset($_SESSION['SWEKEY'])) {
|
||||
$_SESSION['SWEKEY'] = array();
|
||||
}
|
||||
|
||||
$_SESSION['SWEKEY']['ENABLED'] = (! empty($confFile) && @file_exists($confFile));
|
||||
|
||||
// Load the swekey.conf file the first time
|
||||
if ($_SESSION['SWEKEY']['ENABLED']
|
||||
&& empty($_SESSION['SWEKEY']['CONF_LOADED'])
|
||||
) {
|
||||
$_SESSION['SWEKEY']['CONF_LOADED'] = true;
|
||||
$_SESSION['SWEKEY']['VALID_SWEKEYS'] = array();
|
||||
$valid_swekeys = explode("\n", @file_get_contents($confFile));
|
||||
foreach ($valid_swekeys as $line) {
|
||||
if (preg_match("/^[0-9A-F]{32}:.+$/", $line) != false) {
|
||||
$items = explode(":", $line);
|
||||
if (count($items) == 2) {
|
||||
$_SESSION['SWEKEY']['VALID_SWEKEYS'][$items[0]]
|
||||
= trim($items[1]);
|
||||
}
|
||||
} elseif (preg_match("/^[A-Z_]+=.*$/", $line) != false) {
|
||||
$items = explode("=", $line);
|
||||
$_SESSION['SWEKEY']['CONF_' . trim($items[0])] = trim($items[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Set default values for settings
|
||||
if (! isset($_SESSION['SWEKEY']['CONF_SERVER_CHECK'])) {
|
||||
$_SESSION['SWEKEY']['CONF_SERVER_CHECK'] = "";
|
||||
}
|
||||
if (! isset($_SESSION['SWEKEY']['CONF_SERVER_RNDTOKEN'])) {
|
||||
$_SESSION['SWEKEY']['CONF_SERVER_RNDTOKEN'] = "";
|
||||
}
|
||||
if (! isset($_SESSION['SWEKEY']['CONF_SERVER_STATUS'])) {
|
||||
$_SESSION['SWEKEY']['CONF_SERVER_STATUS'] = "";
|
||||
}
|
||||
if (! isset($_SESSION['SWEKEY']['CONF_CA_FILE'])) {
|
||||
$_SESSION['SWEKEY']['CONF_CA_FILE'] = "";
|
||||
}
|
||||
if (! isset($_SESSION['SWEKEY']['CONF_ENABLE_TOKEN_CACHE'])) {
|
||||
$_SESSION['SWEKEY']['CONF_ENABLE_TOKEN_CACHE'] = true;
|
||||
}
|
||||
if (! isset($_SESSION['SWEKEY']['CONF_DEBUG'])) {
|
||||
$_SESSION['SWEKEY']['CONF_DEBUG'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// check if a web key has been authenticated
|
||||
if ($_SESSION['SWEKEY']['ENABLED']) {
|
||||
if (empty($_SESSION['SWEKEY']['AUTHENTICATED_SWEKEY'])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle Swekey authentication error.
|
||||
*
|
||||
* @return string HTML
|
||||
*/
|
||||
function Swekey_Auth_error()
|
||||
{
|
||||
if (! isset($_SESSION['SWEKEY'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $_SESSION['SWEKEY']['ENABLED']) {
|
||||
return null;
|
||||
}
|
||||
|
||||
include_once './libraries/plugins/auth/swekey/authentication.inc.php';
|
||||
|
||||
?>
|
||||
<script>
|
||||
function Swekey_GetValidKey()
|
||||
{
|
||||
var valids = "<?php
|
||||
foreach ($_SESSION['SWEKEY']['VALID_SWEKEYS'] as $key => $value) {
|
||||
echo $key , ',';
|
||||
}
|
||||
?>";
|
||||
var connected_keys = Swekey_ListKeyIds().split(",");
|
||||
for (i in connected_keys) {
|
||||
if (connected_keys[i] != null && connected_keys[i].length == 32) {
|
||||
if (valids.indexOf(connected_keys[i]) >= 0) {
|
||||
return connected_keys[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (connected_keys.length > 0) {
|
||||
if (connected_keys[0].length == 32) {
|
||||
return "unknown_key_" + connected_keys[0];
|
||||
}
|
||||
}
|
||||
|
||||
return "none";
|
||||
}
|
||||
|
||||
var key = Swekey_GetValidKey();
|
||||
|
||||
function timedCheck()
|
||||
{
|
||||
if (key != Swekey_GetValidKey()) {
|
||||
window.location.search = "?swekey_reset";
|
||||
} else {
|
||||
setTimeout("timedCheck()",1000);
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout("timedCheck()",1000);
|
||||
</script>
|
||||
<?php
|
||||
|
||||
if (! empty($_SESSION['SWEKEY']['AUTHENTICATED_SWEKEY'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (count($_SESSION['SWEKEY']['VALID_SWEKEYS']) == 0) {
|
||||
return sprintf(
|
||||
__('File %s does not contain any key id'),
|
||||
$GLOBALS['cfg']['Server']['auth_swekey_config']
|
||||
);
|
||||
}
|
||||
|
||||
include_once "libraries/plugins/auth/swekey/swekey.php";
|
||||
|
||||
Swekey_SetCheckServer($_SESSION['SWEKEY']['CONF_SERVER_CHECK']);
|
||||
Swekey_SetRndTokenServer($_SESSION['SWEKEY']['CONF_SERVER_RNDTOKEN']);
|
||||
Swekey_SetStatusServer($_SESSION['SWEKEY']['CONF_SERVER_STATUS']);
|
||||
Swekey_EnableTokenCache($_SESSION['SWEKEY']['CONF_ENABLE_TOKEN_CACHE']);
|
||||
|
||||
$caFile = $_SESSION['SWEKEY']['CONF_CA_FILE'];
|
||||
if (empty($caFile)) {
|
||||
$caFile = __FILE__;
|
||||
$pos = strrpos($caFile, '/');
|
||||
if ($pos === false) {
|
||||
$pos = strrpos($caFile, '\\'); // windows
|
||||
}
|
||||
$caFile = substr($caFile, 0, $pos + 1) . 'musbe-ca.crt';
|
||||
// echo "\n<!-- $caFile -->\n";
|
||||
// if (file_exists($caFile))
|
||||
// echo "<!-- exists -->\n";
|
||||
}
|
||||
|
||||
if (@file_exists($caFile)) {
|
||||
Swekey_SetCAFile($caFile);
|
||||
} elseif (! empty($caFile)
|
||||
&& (substr($_SESSION['SWEKEY']['CONF_SERVER_CHECK'], 0, 8) == "https://")
|
||||
) {
|
||||
return "Internal Error: CA File $caFile not found";
|
||||
}
|
||||
|
||||
$result = null;
|
||||
$swekey_id = $_GET['swekey_id'];
|
||||
$swekey_otp = $_GET['swekey_otp'];
|
||||
|
||||
if (isset($swekey_id)) {
|
||||
unset($_SESSION['SWEKEY']['AUTHENTICATED_SWEKEY']);
|
||||
if (! isset($_SESSION['SWEKEY']['RND_TOKEN'])) {
|
||||
unset($swekey_id);
|
||||
} else {
|
||||
if (strlen($swekey_id) == 32) {
|
||||
$res = Swekey_CheckOtp(
|
||||
$swekey_id, $_SESSION['SWEKEY']['RND_TOKEN'], $swekey_otp
|
||||
);
|
||||
unset($_SESSION['SWEKEY']['RND_TOKEN']);
|
||||
if (! $res) {
|
||||
$result = __('Hardware authentication failed!') . ' (' . Swekey_GetLastError() . ')';
|
||||
} else {
|
||||
$_SESSION['SWEKEY']['AUTHENTICATED_SWEKEY'] = $swekey_id;
|
||||
$_SESSION['SWEKEY']['FORCE_USER']
|
||||
= $_SESSION['SWEKEY']['VALID_SWEKEYS'][$swekey_id];
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
$result = __('No valid authentication key plugged');
|
||||
if ($_SESSION['SWEKEY']['CONF_DEBUG']) {
|
||||
$result .= "<br/>" . htmlspecialchars($swekey_id);
|
||||
}
|
||||
unset($_SESSION['SWEKEY']['CONF_LOADED']); // reload the conf file
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unset($_SESSION['SWEKEY']);
|
||||
}
|
||||
|
||||
$_SESSION['SWEKEY']['RND_TOKEN'] = Swekey_GetFastRndToken();
|
||||
if (strlen($_SESSION['SWEKEY']['RND_TOKEN']) != 64) {
|
||||
$result = __('Hardware authentication failed!') . ' (' . Swekey_GetLastError() . ')';
|
||||
unset($_SESSION['SWEKEY']['CONF_LOADED']); // reload the conf file
|
||||
}
|
||||
|
||||
if (! isset($swekey_id)) {
|
||||
?>
|
||||
<script>
|
||||
if (key.length != 32) {
|
||||
window.location.search="?swekey_id=" + key + "&token=<?php echo $_SESSION[' PMA_token ']; ?>";
|
||||
} else {
|
||||
var url = "" + window.location;
|
||||
if (url.indexOf("?") > 0) {
|
||||
url = url.substr(0, url.indexOf("?"));
|
||||
}
|
||||
Swekey_SetUnplugUrl(key, "pma_login", url + "?session_to_unset=<?php echo session_id();?>&token=<?php echo $_SESSION[' PMA_token ']; ?>");
|
||||
var otp = Swekey_GetOtp(key, <?php echo '"' , $_SESSION['SWEKEY']['RND_TOKEN'] , '"';?>);
|
||||
window.location.search="?swekey_id=" + key + "&swekey_otp=" + otp + "&token=<?php echo $_SESSION[' PMA_token ']; ?>";
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
return __('Authenticating…');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform login using Swekey.
|
||||
*
|
||||
* @param string $input_name Input "Name"
|
||||
* @param string $input_go Input "Go"
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function Swekey_login($input_name, $input_go)
|
||||
{
|
||||
$swekeyErr = Swekey_Auth_error();
|
||||
if ($swekeyErr != null) {
|
||||
Message::error($swekeyErr)->display();
|
||||
if ($GLOBALS['error_handler']->hasDisplayErrors()) {
|
||||
echo '<div>';
|
||||
$GLOBALS['error_handler']->dispErrors();
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_SESSION['SWEKEY']) && $_SESSION['SWEKEY']['ENABLED']) {
|
||||
echo '<script type="text/javascript">';
|
||||
if (empty($_SESSION['SWEKEY']['FORCE_USER'])) {
|
||||
echo 'var user = null;';
|
||||
} else {
|
||||
echo 'var user = "' . $_SESSION['SWEKEY']['FORCE_USER'] . '";';
|
||||
}
|
||||
|
||||
?>
|
||||
function open_swekey_site()
|
||||
{
|
||||
window.open("<?php echo PMA_linkURL('https://www.phpmyadmin.net/auth_key/'); ?>");
|
||||
}
|
||||
|
||||
var input_username = document.getElementById("<?php echo $input_name; ?>");
|
||||
var input_go = document.getElementById("<?php echo $input_go; ?>");
|
||||
var swekey_status = document.createElement('img');
|
||||
swekey_status.setAttribute('onclick', 'open_swekey_site()');
|
||||
swekey_status.setAttribute('style', 'width:8px; height:16px; border:0px; vspace:0px; hspace:0px; frameborder:no');
|
||||
if (user == null) {
|
||||
swekey_status.setAttribute('src', 'http://artwork.swekey.com/unplugged-8x16.png');
|
||||
//swekey_status.setAttribute('title', 'No swekey plugged');
|
||||
input_go.disabled = true;
|
||||
} else {
|
||||
swekey_status.setAttribute('src', 'http://artwork.swekey.com/plugged-8x16.png');
|
||||
//swekey_status.setAttribute('title', 'swekey plugged');
|
||||
input_username.value = user;
|
||||
}
|
||||
input_username.readOnly = true;
|
||||
|
||||
if (input_username.nextSibling == null) {
|
||||
input_username.parentNode.appendChild(swekey_status);
|
||||
} else {
|
||||
input_username.parentNode.insertBefore(swekey_status, input_username.nextSibling);
|
||||
}
|
||||
|
||||
<?php
|
||||
echo '</script>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($_GET['session_to_unset'])) {
|
||||
session_write_close();
|
||||
session_id($_GET['session_to_unset']);
|
||||
session_start();
|
||||
$_SESSION = array();
|
||||
session_write_close();
|
||||
session_destroy();
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_GET['swekey_reset'])) {
|
||||
unset($_SESSION['SWEKEY']);
|
||||
}
|
||||
|
||||
@ -1,536 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Library that provides common functions that are used to help integrating Swekey Authentication in a PHP web site
|
||||
* Version 1.0
|
||||
*
|
||||
* History:
|
||||
* 1.2 Use curl (widely installed) to query the server
|
||||
* Fixed a possible tempfile race attack
|
||||
* Random token cache can now be disabled
|
||||
* 1.1 Added Swekey_HttpGet function that support faulty servers
|
||||
* Support for custom servers
|
||||
* 1.0 First release
|
||||
*
|
||||
* @package Swekey
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Errors codes
|
||||
*/
|
||||
define("SWEKEY_ERR_INVALID_DEV_STATUS", 901); // The satus of the device is not SWEKEY_STATUS_OK
|
||||
define("SWEKEY_ERR_INTERNAL", 902); // Should never occurd
|
||||
define("SWEKEY_ERR_OUTDATED_RND_TOKEN", 910); // You random token is too old
|
||||
define("SWEKEY_ERR_INVALID_OTP", 911); // The otp was not correct
|
||||
|
||||
/**
|
||||
* Those errors are considered as an attack and your site will be blacklisted during one minute
|
||||
* if you receive one of those errors
|
||||
*/
|
||||
define("SWEKEY_ERR_BADLY_ENCODED_REQUEST", 920);
|
||||
define("SWEKEY_ERR_INVALID_RND_TOKEN", 921);
|
||||
define("SWEKEY_ERR_DEV_NOT_FOUND", 922);
|
||||
|
||||
/**
|
||||
* Default values for configuration.
|
||||
*/
|
||||
define('SWEKEY_DEFAULT_CHECK_SERVER', 'https://auth-check.musbe.net');
|
||||
define('SWEKEY_DEFAULT_RND_SERVER', 'https://auth-rnd-gen.musbe.net');
|
||||
define('SWEKEY_DEFAULT_STATUS_SERVER', 'https://auth-status.musbe.net');
|
||||
|
||||
/**
|
||||
* The last error of an operation is alway put in this global var
|
||||
*/
|
||||
|
||||
global $gSwekeyLastError;
|
||||
$gSwekeyLastError = 0;
|
||||
|
||||
global $gSwekeyLastResult;
|
||||
$gSwekeyLastResult = "<not set>";
|
||||
|
||||
/**
|
||||
* Servers addresses
|
||||
* Use the Swekey_SetXxxServer($server) functions to set them
|
||||
*/
|
||||
|
||||
global $gSwekeyCheckServer;
|
||||
if (! isset($gSwekeyCheckServer)) {
|
||||
$gSwekeyCheckServer = SWEKEY_DEFAULT_CHECK_SERVER;
|
||||
}
|
||||
|
||||
global $gSwekeyRndTokenServer;
|
||||
if (! isset($gSwekeyRndTokenServer)) {
|
||||
$gSwekeyRndTokenServer = SWEKEY_DEFAULT_RND_SERVER;
|
||||
}
|
||||
|
||||
global $gSwekeyStatusServer;
|
||||
if (! isset($gSwekeyStatusServer)) {
|
||||
$gSwekeyStatusServer = SWEKEY_DEFAULT_STATUS_SERVER;
|
||||
}
|
||||
|
||||
global $gSwekeyCA;
|
||||
|
||||
global $gSwekeyTokenCacheEnabled;
|
||||
if (! isset($gSwekeyTokenCacheEnabled)) {
|
||||
$gSwekeyTokenCacheEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the address of the Check server.
|
||||
* If $server is empty the default value 'http://auth-check.musbe.net' will be used
|
||||
*
|
||||
* @param int $server The protocol and hostname to use
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_SetCheckServer($server)
|
||||
{
|
||||
global $gSwekeyCheckServer;
|
||||
if (empty($server)) {
|
||||
$gSwekeyCheckServer = SWEKEY_DEFAULT_CHECK_SERVER;
|
||||
} else {
|
||||
$gSwekeyCheckServer = $server;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the address of the Random Token Generator server.
|
||||
* If $server is empty the default value 'http://auth-rnd-gen.musbe.net' will be used
|
||||
*
|
||||
* @param int $server The protocol and hostname to use
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_SetRndTokenServer($server)
|
||||
{
|
||||
global $gSwekeyRndTokenServer;
|
||||
if (empty($server)) {
|
||||
$gSwekeyRndTokenServer = SWEKEY_DEFAULT_RND_SERVER;
|
||||
} else {
|
||||
$gSwekeyRndTokenServer = $server;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the address of the Satus server.
|
||||
* If $server is empty the default value 'http://auth-status.musbe.net' will be used
|
||||
*
|
||||
* @param int $server The protocol and hostname to use
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_SetStatusServer($server)
|
||||
{
|
||||
global $gSwekeyStatusServer;
|
||||
if (empty($server)) {
|
||||
$gSwekeyStatusServer = SWEKEY_DEFAULT_STATUS_SERVER;
|
||||
} else {
|
||||
$gSwekeyStatusServer = $server;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the certificat file in case of the the severs use https instead of http
|
||||
*
|
||||
* @param string $cafile The path of the crt file to use
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_SetCAFile($cafile)
|
||||
{
|
||||
global $gSwekeyCA;
|
||||
$gSwekeyCA = $cafile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable the random token caching
|
||||
* Because everybody has full access to the cache file, it can be a DOS vulnerability
|
||||
* So disable it if you are running in a non secure enviromnement
|
||||
*
|
||||
* @param $enable
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_EnableTokenCache($enable)
|
||||
{
|
||||
global $gSwekeyTokenCacheEnabled;
|
||||
$gSwekeyTokenCacheEnabled = ! empty($enable);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the last error.
|
||||
*
|
||||
* @return string The Last Error
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetLastError()
|
||||
{
|
||||
global $gSwekeyLastError;
|
||||
return $gSwekeyLastError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the last result.
|
||||
*
|
||||
* @return string The Last Error
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetLastResult()
|
||||
{
|
||||
global $gSwekeyLastResult;
|
||||
return $gSwekeyLastResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a synchronous request to the server.
|
||||
* This function manages timeout then will not block if one of the server is down
|
||||
*
|
||||
* @param string $url The url to get
|
||||
* @param string $response_code The response code
|
||||
*
|
||||
* @return string The body of the response or "" in case of error
|
||||
* @access private
|
||||
*/
|
||||
function Swekey_HttpGet($url, &$response_code)
|
||||
{
|
||||
global $gSwekeyLastError;
|
||||
$gSwekeyLastError = 0;
|
||||
global $gSwekeyLastResult;
|
||||
$gSwekeyLastResult = "<not set>";
|
||||
|
||||
// use curl if available
|
||||
if (function_exists('curl_init')) {
|
||||
$sess = curl_init($url);
|
||||
if (substr($url, 0, 8) == "https://") {
|
||||
global $gSwekeyCA;
|
||||
|
||||
if (! empty($gSwekeyCA)) {
|
||||
if (file_exists($gSwekeyCA)) {
|
||||
if (! curl_setopt($sess, CURLOPT_CAINFO, $gSwekeyCA)) {
|
||||
error_log(
|
||||
"SWEKEY_ERROR:Could not set CA file : ".curl_error($sess)
|
||||
);
|
||||
} else {
|
||||
$caFileOk = true;
|
||||
}
|
||||
} else {
|
||||
error_log(
|
||||
"SWEKEY_ERROR:Could not find CA file $gSwekeyCA getting $url"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
curl_setopt($sess, CURLOPT_SSL_VERIFYHOST, '2');
|
||||
curl_setopt($sess, CURLOPT_SSL_VERIFYPEER, '1');
|
||||
curl_setopt($sess, CURLOPT_CONNECTTIMEOUT, '20');
|
||||
curl_setopt($sess, CURLOPT_TIMEOUT, '20');
|
||||
} else {
|
||||
curl_setopt($sess, CURLOPT_CONNECTTIMEOUT, '3');
|
||||
curl_setopt($sess, CURLOPT_TIMEOUT, '5');
|
||||
}
|
||||
|
||||
curl_setopt($sess, CURLOPT_RETURNTRANSFER, '1');
|
||||
$res=curl_exec($sess);
|
||||
$response_code = curl_getinfo($sess, CURLINFO_HTTP_CODE);
|
||||
$curlerr = curl_error($sess);
|
||||
curl_close($sess);
|
||||
|
||||
if ($response_code == 200) {
|
||||
$gSwekeyLastResult = $res;
|
||||
return $res;
|
||||
}
|
||||
|
||||
if (! empty($response_code)) {
|
||||
$gSwekeyLastError = $response_code;
|
||||
error_log(
|
||||
"SWEKEY_ERROR:Error $gSwekeyLastError ($curlerr) getting $url"
|
||||
);
|
||||
return "";
|
||||
}
|
||||
|
||||
$response_code = 408; // Request Timeout
|
||||
$gSwekeyLastError = $response_code;
|
||||
error_log("SWEKEY_ERROR:Error $curlerr getting $url");
|
||||
return "";
|
||||
}
|
||||
|
||||
// use pecl_http if available
|
||||
if (class_exists('HttpRequest')) {
|
||||
// retry if one of the server is down
|
||||
for ($num=1; $num <= 3; $num++ ) {
|
||||
$r = new HttpRequest($url);
|
||||
$options = array('timeout' => '3');
|
||||
|
||||
if (substr($url, 0, 6) == "https:") {
|
||||
$sslOptions = array();
|
||||
$sslOptions['verifypeer'] = true;
|
||||
$sslOptions['verifyhost'] = true;
|
||||
|
||||
$capath = __FILE__;
|
||||
$name = strrchr($capath, '/');
|
||||
// windows
|
||||
if (empty($name)) {
|
||||
$name = strrchr($capath, '\\');
|
||||
}
|
||||
$capath = substr($capath, 0, strlen($capath) - strlen($name) + 1)
|
||||
. 'musbe-ca.crt';
|
||||
|
||||
if (! empty($gSwekeyCA)) {
|
||||
$sslOptions['cainfo'] = $gSwekeyCA;
|
||||
}
|
||||
|
||||
$options['ssl'] = $sslOptions;
|
||||
}
|
||||
|
||||
$r->setOptions($options);
|
||||
|
||||
/*
|
||||
try
|
||||
{
|
||||
*/
|
||||
$reply = $r->send();
|
||||
$res = $reply->getBody();
|
||||
$info = $r->getResponseInfo();
|
||||
$response_code = $info['response_code'];
|
||||
if ($response_code != 200) {
|
||||
$gSwekeyLastError = $response_code;
|
||||
error_log(
|
||||
"SWEKEY_ERROR:Error ".$gSwekeyLastError." getting ".$url
|
||||
);
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
$gSwekeyLastResult = $res;
|
||||
return $res;
|
||||
/*
|
||||
}
|
||||
catch (HttpException $e)
|
||||
{
|
||||
error_log("SWEKEY_WARNING:HttpException ".$e." getting ".$url);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
$response_code = 408; // Request Timeout
|
||||
$gSwekeyLastError = $response_code;
|
||||
error_log("SWEKEY_ERROR:Error ".$gSwekeyLastError." getting ".$url);
|
||||
return "";
|
||||
}
|
||||
|
||||
global $http_response_header;
|
||||
$res = @file_get_contents($url);
|
||||
$response_code = substr($http_response_header[0], 9, 3); //HTTP/1.0
|
||||
if ($response_code == 200) {
|
||||
$gSwekeyLastResult = $res;
|
||||
return $res;
|
||||
}
|
||||
|
||||
$gSwekeyLastError = $response_code;
|
||||
error_log("SWEKEY_ERROR:Error ".$response_code." getting ".$url);
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Random Token from a Token Server
|
||||
* The RT is a 64 vhars hexadecimal value
|
||||
* You should better use Swekey_GetFastRndToken() for performance
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetRndToken()
|
||||
{
|
||||
global $gSwekeyRndTokenServer;
|
||||
return Swekey_HttpGet($gSwekeyRndTokenServer.'/FULL-RND-TOKEN', $response_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Half Random Token from a Token Server
|
||||
* The RT is a 64 vhars hexadecimal value
|
||||
* Use this value if you want to make your own Swekey_GetFastRndToken()
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetHalfRndToken()
|
||||
{
|
||||
global $gSwekeyRndTokenServer;
|
||||
return Swekey_HttpGet($gSwekeyRndTokenServer.'/HALF-RND-TOKEN', $response_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Half Random Token
|
||||
* The RT is a 64 vhars hexadecimal value
|
||||
* This function get a new random token and reuse it.
|
||||
* Token are refetched from the server only once every 30 seconds.
|
||||
* You should always use this function to get half random token.
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetFastHalfRndToken()
|
||||
{
|
||||
global $gSwekeyTokenCacheEnabled;
|
||||
|
||||
$res = "";
|
||||
$cachefile = "";
|
||||
|
||||
// We check if we have a valid RT is the session
|
||||
if (isset($_SESSION['rnd-token-date'])) {
|
||||
if (time() - $_SESSION['rnd-token-date'] < 30) {
|
||||
$res = $_SESSION['rnd-token'];
|
||||
}
|
||||
}
|
||||
|
||||
// If not we try to get it from a temp file (PHP >= 5.2.1 only)
|
||||
if (strlen($res) != 32 && $gSwekeyTokenCacheEnabled) {
|
||||
if (function_exists('sys_get_temp_dir')) {
|
||||
$tempdir = sys_get_temp_dir();
|
||||
$cachefile = $tempdir."/swekey-rnd-token-".get_current_user();
|
||||
$modif = filemtime($cachefile);
|
||||
if ($modif != false) {
|
||||
if (time() - $modif < 30) {
|
||||
$res = @file_get_contents($cachefile);
|
||||
if (strlen($res) != 32) {
|
||||
$res = "";
|
||||
} else {
|
||||
$_SESSION['rnd-token'] = $res;
|
||||
$_SESSION['rnd-token-date'] = $modif;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we don't have a valid RT here we have to get it from the server
|
||||
if (strlen($res) != 32) {
|
||||
$res = substr(Swekey_GetHalfRndToken(), 0, 32);
|
||||
$_SESSION['rnd-token'] = $res;
|
||||
$_SESSION['rnd-token-date'] = time();
|
||||
if (! empty($cachefile)) {
|
||||
// we unlink the file so no possible tempfile race attack
|
||||
unlink($cachefile);
|
||||
$file = fopen($cachefile, "x");
|
||||
if ($file != false) {
|
||||
@fwrite($file, $res);
|
||||
@fclose($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $res."00000000000000000000000000000000";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Random Token
|
||||
* The RT is a 64 vhars hexadecimal value
|
||||
* This function generates a unique random token for each call but call the
|
||||
* server only once every 30 seconds.
|
||||
* You should always use this function to get random token.
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetFastRndToken()
|
||||
{
|
||||
$res = Swekey_GetFastHalfRndToken();
|
||||
if (strlen($res) == 64) {
|
||||
return substr($res, 0, 32).strtoupper(md5("Musbe Authentication Key" . mt_rand() . date(DATE_ATOM)));
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks that an OTP generated by a Swekey is valid
|
||||
*
|
||||
* @param mixed $id The id of the swekey
|
||||
* @param mixed $rt The random token used to generate the otp
|
||||
* @param mixed $otp The otp generated by the swekey
|
||||
*
|
||||
* @return boolean Success
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_CheckOtp($id, $rt, $otp)
|
||||
{
|
||||
global $gSwekeyCheckServer;
|
||||
$res = Swekey_HttpGet(
|
||||
$gSwekeyCheckServer.'/CHECK-OTP/'.$id.'/'.$rt.'/'.$otp,
|
||||
$response_code
|
||||
);
|
||||
return $response_code == 200 && $res == "OK";
|
||||
}
|
||||
|
||||
/**
|
||||
* Values that are associated with a key.
|
||||
* The following values can be returned by the Swekey_GetStatus() function
|
||||
*/
|
||||
define("SWEKEY_STATUS_OK", 0);
|
||||
define("SWEKEY_STATUS_NOT_FOUND", 1); // The key does not exist in the db
|
||||
define("SWEKEY_STATUS_INACTIVE", 2); // The key has never been activated
|
||||
define("SWEKEY_STATUS_LOST", 3); // The user has lost his key
|
||||
define("SWEKEY_STATUS_STOLEN", 4); // The key was stolen
|
||||
define("SWEKEY_STATUS_FEE_DUE", 5); // The annual fee was not paid
|
||||
define("SWEKEY_STATUS_OBSOLETE", 6); // The hardware is no longer supported
|
||||
define("SWEKEY_STATUS_UNKOWN", 201); // We could not connect to the authentication server
|
||||
|
||||
/**
|
||||
* Values that are associated with a key.
|
||||
* The Javascript Api can also return the following values
|
||||
*/
|
||||
define("SWEKEY_STATUS_REPLACED", 100); // This key has been replaced by a backup key
|
||||
define("SWEKEY_STATUS_BACKUP_KEY", 101); // This key is a backup key that is not activated yet
|
||||
define("SWEKEY_STATUS_NOTPLUGGED", 200); // This key is not plugged in the computer
|
||||
|
||||
|
||||
/**
|
||||
* Return the text corresponding to the integer status of a key
|
||||
*
|
||||
* @param int $status The status
|
||||
*
|
||||
* @return string The text corresponding to the status
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetStatusStr($status)
|
||||
{
|
||||
switch($status)
|
||||
{
|
||||
case SWEKEY_STATUS_OK :
|
||||
return 'OK';
|
||||
case SWEKEY_STATUS_NOT_FOUND :
|
||||
return 'Key does not exist in the db';
|
||||
case SWEKEY_STATUS_INACTIVE :
|
||||
return 'Key not activated';
|
||||
case SWEKEY_STATUS_LOST :
|
||||
return 'Key was lost';
|
||||
case SWEKEY_STATUS_STOLEN :
|
||||
return 'Key was stolen';
|
||||
case SWEKEY_STATUS_FEE_DUE :
|
||||
return 'The annual fee was not paid';
|
||||
case SWEKEY_STATUS_OBSOLETE :
|
||||
return 'Key no longer supported';
|
||||
case SWEKEY_STATUS_REPLACED :
|
||||
return 'This key has been replaced by a backup key';
|
||||
case SWEKEY_STATUS_BACKUP_KEY :
|
||||
return 'This key is a backup key that is not activated yet';
|
||||
case SWEKEY_STATUS_NOTPLUGGED :
|
||||
return 'This key is not plugged in the computer';
|
||||
case SWEKEY_STATUS_UNKOWN :
|
||||
return 'Unknow Status, could not connect to the authentication server';
|
||||
}
|
||||
return 'unknown status '.$status;
|
||||
}
|
||||
|
||||
/**
|
||||
* If your web site requires a key to login you should check that the key
|
||||
* is still valid (has not been lost or stolen) before requiring it.
|
||||
* A key can be authenticated only if its status is SWEKEY_STATUS_OK
|
||||
*
|
||||
* @param mixed $id The id of the swekey
|
||||
*
|
||||
* @return int The status of the swekey
|
||||
* @access public
|
||||
*/
|
||||
function Swekey_GetStatus($id)
|
||||
{
|
||||
global $gSwekeyStatusServer;
|
||||
$res = Swekey_HttpGet($gSwekeyStatusServer.'/GET-STATUS/'.$id, $response_code);
|
||||
if ($response_code == 200) {
|
||||
return intval($res);
|
||||
}
|
||||
return SWEKEY_STATUS_UNKOWN;
|
||||
}
|
||||
@ -360,7 +360,7 @@ class ExportMediawiki extends ExportPlugin
|
||||
// see http://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)) {
|
||||
|
||||
@ -595,7 +595,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;
|
||||
}
|
||||
|
||||
@ -96,21 +96,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)
|
||||
@ -130,6 +133,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 != "") {
|
||||
@ -142,14 +153,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);
|
||||
}
|
||||
|
||||
$esri_types = array(
|
||||
0 => 'Null Shape',
|
||||
1 => 'Point',
|
||||
|
||||
@ -53,7 +53,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1665,7 +1665,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)
|
||||
{
|
||||
|
||||
@ -293,13 +293,13 @@ function PMA_Replication_connectToMaster(
|
||||
$user, $password, $host = null, $port = null, $socket = null
|
||||
) {
|
||||
$server = array();
|
||||
$server["host"] = $host;
|
||||
$server["host"] = PMA_sanitizeMySQLHost($host);
|
||||
$server["port"] = $port;
|
||||
$server["socket"] = $socket;
|
||||
|
||||
// 5th parameter set to true means that it's an auxiliary connection
|
||||
// and we must not go back to login page if it fails
|
||||
return $GLOBALS['dbi']->connect($user, $password, false, $server, true);
|
||||
return PMA_DBI_connect($user, $password, false, $server, true);
|
||||
}
|
||||
/**
|
||||
* Fetches position and file of current binary log on master
|
||||
|
||||
@ -548,7 +548,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">';
|
||||
|
||||
@ -571,13 +571,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>';
|
||||
|
||||
@ -806,7 +806,7 @@ function PMA_getHtmlForAddUserLoginForm($username_length)
|
||||
. (empty($_REQUEST['username']) ? '' : ' value="'
|
||||
. (isset($GLOBALS['new_username'])
|
||||
? $GLOBALS['new_username']
|
||||
: $_REQUEST['username']) . '"')
|
||||
: htmlspecialchars($_REQUEST['username'])) . '"')
|
||||
. ' />'
|
||||
. '</div>';
|
||||
|
||||
@ -836,7 +836,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(
|
||||
|
||||
@ -54,6 +54,9 @@ function PMA_replaceBBLink($found)
|
||||
$target = '';
|
||||
if (! empty($found[3])) {
|
||||
$target = ' target="' . $found[3] . '"';
|
||||
if ($found[3] == '_blank') {
|
||||
$target .= ' rel="noopener noreferrer"';
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct url */
|
||||
|
||||
@ -2400,13 +2400,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>';
|
||||
|
||||
@ -284,7 +284,7 @@ function PMA_getHtmlForRenderVariables($ServerStatusData, $alerts, $strShowStatu
|
||||
$retval .= '<span class="allfine">';
|
||||
}
|
||||
}
|
||||
$retval .= $value;
|
||||
$retval .= htmlspecialchars($value);
|
||||
if (isset($alerts[$name])) {
|
||||
$retval .= '</span>';
|
||||
}
|
||||
|
||||
@ -351,7 +351,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;
|
||||
}
|
||||
|
||||
@ -73,7 +73,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()
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -388,9 +388,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']);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -862,7 +860,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.
|
||||
|
||||
@ -26,7 +26,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 .= PMA_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();
|
||||
}
|
||||
@ -48,7 +48,6 @@
|
||||
<directory suffix=".php">libraries/bfShapeFiles</directory>
|
||||
<directory suffix=".php">libraries/php-gettext</directory>
|
||||
<directory suffix=".php">libraries/phpseclib</directory>
|
||||
<directory suffix=".php">libraries/plugins/auth/swekey/</directory>
|
||||
<directory suffix=".php">libraries/sql-parser</directory>
|
||||
<directory suffix=".php">libraries/tcpdf</directory>
|
||||
<!-- examples for users -->
|
||||
|
||||
@ -42,10 +42,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_generateCharsetDropdownBox(PMA_CSDROPDOWN_COLLATION, 'db_collation', null, null, true); ?>
|
||||
@ -33,4 +33,4 @@
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
@ -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">
|
||||
@ -96,4 +96,4 @@
|
||||
</table>
|
||||
</div>
|
||||
<input type="hidden" id="queryID" name="sql_query" />
|
||||
</form>
|
||||
</form>
|
||||
|
||||
@ -186,7 +186,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(
|
||||
@ -222,4 +222,4 @@ $rownum = 0; $odd_row = true; ?>
|
||||
<?php if ($GLOBALS['cfg']['ShowStats']): ?>
|
||||
<?= $tablestats; ?>
|
||||
<?php endif; ?>
|
||||
<div class="clearfloat"></div>
|
||||
<div class="clearfloat"></div>
|
||||
|
||||
@ -1385,7 +1385,7 @@ class DisplayResultsTest extends PMATestCase
|
||||
$meta,
|
||||
$url_params,
|
||||
null,
|
||||
'<a href="1001" title="" target="_new">1001</a>'
|
||||
'1001'
|
||||
),
|
||||
array(
|
||||
false,
|
||||
@ -1514,7 +1514,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"
|
||||
|
||||
@ -404,22 +404,6 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
$attrInstance->setValue($restoreInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for PMA\libraries\plugins\auth\AuthenticationConfig::authCheck
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAuthCheckSwekey()
|
||||
{
|
||||
$GLOBALS['cfg']['Server']['auth_swekey_config'] = 'testConfigSwekey';
|
||||
|
||||
file_put_contents('testConfigSwekey', '');
|
||||
$this->assertFalse(
|
||||
$this->object->authCheck()
|
||||
);
|
||||
@unlink('testConfigSwekey');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for PMA\libraries\plugins\auth\AuthenticationConfig::authCheck
|
||||
*
|
||||
@ -427,7 +411,6 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
*/
|
||||
public function testAuthCheckCaptcha()
|
||||
{
|
||||
$GLOBALS['cfg']['Server']['auth_swekey_config'] = '';
|
||||
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = 'testprivkey';
|
||||
$GLOBALS['cfg']['CaptchaLoginPublicKey'] = 'testpubkey';
|
||||
$_POST["g-recaptcha-response"] = '';
|
||||
@ -470,18 +453,17 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
$attrInstance->setAccessible(true);
|
||||
$attrInstance->setValue($mockResponse);
|
||||
|
||||
$GLOBALS['cfg']['Server']['auth_swekey_config'] = '';
|
||||
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = '';
|
||||
$GLOBALS['cfg']['CaptchaLoginPublicKey'] = '';
|
||||
$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);
|
||||
}
|
||||
@ -512,19 +494,18 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
$attrInstance = new ReflectionProperty('PMA\libraries\Response', '_instance');
|
||||
$attrInstance->setAccessible(true);
|
||||
$attrInstance->setValue($mockResponse);
|
||||
$GLOBALS['cfg']['Server']['auth_swekey_config'] = '';
|
||||
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = '';
|
||||
$GLOBALS['cfg']['CaptchaLoginPublicKey'] = '';
|
||||
$GLOBALS['cfg']['LoginCookieDeleteAll'] = false;
|
||||
$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);
|
||||
}
|
||||
@ -536,7 +517,6 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
*/
|
||||
public function testAuthCheckArbitrary()
|
||||
{
|
||||
$GLOBALS['cfg']['Server']['auth_swekey_config'] = '';
|
||||
$GLOBALS['cfg']['CaptchaLoginPrivateKey'] = '';
|
||||
$GLOBALS['cfg']['CaptchaLoginPublicKey'] = '';
|
||||
$_REQUEST['old_usr'] = '';
|
||||
@ -565,7 +545,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
);
|
||||
|
||||
$this->assertFalse(
|
||||
isset($_COOKIE['pmaPass-1'])
|
||||
isset($_COOKIE['pmaAuth-1'])
|
||||
);
|
||||
}
|
||||
|
||||
@ -574,26 +554,19 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAuthCheckIV()
|
||||
public function testAuthCheckInvalidCookie()
|
||||
{
|
||||
$GLOBALS['cfg']['AllowArbitraryServer'] = true;
|
||||
$GLOBALS['cfg']['Server']['auth_swekey_config'] = '';
|
||||
$_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']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -603,12 +576,11 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
*/
|
||||
public function testAuthCheckExpires()
|
||||
{
|
||||
$GLOBALS['cfg']['Server']['auth_swekey_config'] = '';
|
||||
$GLOBALS['server'] = 1;
|
||||
$_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;
|
||||
@ -625,7 +597,6 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
*/
|
||||
public function testAuthCheckDecryptUser()
|
||||
{
|
||||
$GLOBALS['cfg']['Server']['auth_swekey_config'] = 'testConfigSwekey';
|
||||
$GLOBALS['server'] = 1;
|
||||
$_REQUEST['old_usr'] = '';
|
||||
$_REQUEST['pma_username'] = '';
|
||||
@ -664,13 +635,12 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
*/
|
||||
public function testAuthCheckDecryptPassword()
|
||||
{
|
||||
$GLOBALS['cfg']['Server']['auth_swekey_config'] = 'testConfigSwekey';
|
||||
$GLOBALS['server'] = 1;
|
||||
$_REQUEST['old_usr'] = '';
|
||||
$_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'] = '';
|
||||
@ -686,7 +656,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
|
||||
$this->object->expects($this->at(1))
|
||||
->method('cookieDecrypt')
|
||||
->will($this->returnValue("\xff(blank)"));
|
||||
->will($this->returnValue('{"password":""}'));
|
||||
|
||||
$this->assertTrue(
|
||||
$this->object->authCheck()
|
||||
@ -710,7 +680,6 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
*/
|
||||
public function testAuthCheckAuthFails()
|
||||
{
|
||||
$GLOBALS['cfg']['Server']['auth_swekey_config'] = 'testConfigSwekey';
|
||||
$GLOBALS['server'] = 1;
|
||||
$_REQUEST['old_usr'] = '';
|
||||
$_REQUEST['pma_username'] = '';
|
||||
@ -785,7 +754,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
);
|
||||
|
||||
$this->assertTrue(
|
||||
isset($_COOKIE['pmaPass-1'])
|
||||
isset($_COOKIE['pmaAuth-1'])
|
||||
);
|
||||
|
||||
$arr['password'] = 'testPW';
|
||||
@ -857,10 +826,6 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
$this->object->authSetUser();
|
||||
$this->object->storeUserCredentials();
|
||||
|
||||
$this->assertTrue(
|
||||
isset($_COOKIE['pmaServer-2'])
|
||||
);
|
||||
|
||||
$attrInstance->setValue($restoreInstance);
|
||||
}
|
||||
|
||||
@ -908,7 +873,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
->getMock();
|
||||
|
||||
$GLOBALS['server'] = 2;
|
||||
$_COOKIE['pmaPass-2'] = 'pass';
|
||||
$_COOKIE['pmaAuth-2'] = 'pass';
|
||||
|
||||
$GLOBALS['login_without_password_is_forbidden'] = '1';
|
||||
|
||||
@ -933,7 +898,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';
|
||||
@ -957,7 +922,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
->getMock();
|
||||
|
||||
$GLOBALS['server'] = 2;
|
||||
$_COOKIE['pmaPass-2'] = 'pass';
|
||||
$_COOKIE['pmaAuth-2'] = 'pass';
|
||||
|
||||
|
||||
$GLOBALS['allowDeny_forbidden'] = '';
|
||||
@ -983,7 +948,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
->getMock();
|
||||
|
||||
$GLOBALS['server'] = 2;
|
||||
$_COOKIE['pmaPass-2'] = 'pass';
|
||||
$_COOKIE['pmaAuth-2'] = 'pass';
|
||||
|
||||
|
||||
$dbi = $this->getMockBuilder('PMA\libraries\DatabaseInterface')
|
||||
@ -1026,7 +991,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
|
||||
$GLOBALS['dbi'] = $dbi;
|
||||
$GLOBALS['server'] = 2;
|
||||
$_COOKIE['pmaPass-2'] = 'pass';
|
||||
$_COOKIE['pmaAuth-2'] = 'pass';
|
||||
|
||||
unset($GLOBALS['errno']);
|
||||
|
||||
@ -1065,7 +1030,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
256,
|
||||
32,
|
||||
strlen($result)
|
||||
);
|
||||
}
|
||||
@ -1088,7 +1053,7 @@ class AuthenticationCookieTest extends PMATestCase
|
||||
$result = $method->invoke($this->object, null);
|
||||
|
||||
$this->assertEquals(
|
||||
md5('notEmpty'),
|
||||
'notEmpty',
|
||||
$result
|
||||
);
|
||||
}
|
||||
@ -1103,7 +1068,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":"34367a80e4276906637b5eaecf8c3931547aae68","payload":"+coP\/up\/ZBTBwbiEpCUVXQ=="}',
|
||||
$this->object->cookieEncrypt('data123', 'sec321')
|
||||
);
|
||||
}
|
||||
@ -1115,16 +1080,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":"34367a80e4276906637b5eaecf8c3931547aae68","payload":"+coP\/up\/ZBTBwbiEpCUVXQ=="}',
|
||||
'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',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,7 +163,7 @@ class ExportPhparrayTest extends PMATestCase
|
||||
*/
|
||||
public function testExportDBHeader()
|
||||
{
|
||||
$GLOBALS['crlf'] = ' ';
|
||||
$GLOBALS['crlf'] = "\n";
|
||||
|
||||
ob_start();
|
||||
$this->assertTrue(
|
||||
@ -172,7 +172,7 @@ class ExportPhparrayTest extends PMATestCase
|
||||
$result = ob_get_clean();
|
||||
|
||||
$this->assertContains(
|
||||
'// Database `db` ',
|
||||
"/**\n * Database `db`\n */",
|
||||
$result
|
||||
);
|
||||
}
|
||||
@ -253,7 +253,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",
|
||||
|
||||
@ -529,6 +529,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()
|
||||
@ -587,33 +589,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(),
|
||||
|
||||
@ -51,32 +51,58 @@ class PMA_Ip_Allow_Deny_Test extends PHPUnit_Framework_TestCase
|
||||
* 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'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -21,7 +21,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
@ -16,6 +16,11 @@ require_once './libraries/common.inc.php';
|
||||
*/
|
||||
require_once './libraries/js_escape.lib.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'])
|
||||
|
||||
@ -120,6 +120,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);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user