Merge branch 'master' of https://github.com/phpmyadmin/phpmyadmin
This commit is contained in:
commit
00dee1085c
1
.gitignore
vendored
1
.gitignore
vendored
@ -46,4 +46,5 @@ phpunit.xml
|
||||
# Ant cache
|
||||
cache.properties
|
||||
# Composer
|
||||
composer.lock
|
||||
/vendor/
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- "7.0"
|
||||
- "5.6"
|
||||
- "5.5"
|
||||
- "5.4"
|
||||
@ -61,6 +62,8 @@ matrix:
|
||||
env: PHPUNIT_ARGS="--exclude-group selenium"
|
||||
- php: nightly
|
||||
env: PHPUNIT_ARGS="--exclude-group selenium"
|
||||
- php: "7.0"
|
||||
env: PHPUNIT_ARGS="--exclude-group selenium"
|
||||
fast_finish: true
|
||||
include:
|
||||
- php: 5.6
|
||||
|
||||
19
ChangeLog
19
ChangeLog
@ -87,9 +87,26 @@ phpMyAdmin - ChangeLog
|
||||
+ Upgrade TCPDF to version 6.2.9
|
||||
+ issue #6102 Add SHA256 security password support
|
||||
- issue #10250 Displayed git revision info is not set
|
||||
+ Improved schema SVG export
|
||||
- issue #10726 Do not try to set port 80 for https requests
|
||||
+ issue #11394 Export/import Designer view
|
||||
+ Partition support in table Structure
|
||||
+ issue #11414 Unclear export options / organization / hierarchy
|
||||
Set minimum required PHP version to 5.5 (older versions are EOL)
|
||||
- issue #11407 ALTER TABLE failing on import when table exists
|
||||
|
||||
4.4.14.0 (not yet released)
|
||||
4.4.15.0 (not yet released)
|
||||
|
||||
4.4.14.0 (2015-08-20)
|
||||
- issue #11367 Export after search, missing WHERE clause
|
||||
- issue #11380 Incomplete message after import
|
||||
- issue Incorrect scalar type declaration (reported under PHP 7)
|
||||
- issue #11389 ReCaptcha produces deprecated messages under PHP 7
|
||||
- issue #11387 phpseclib < 2.0 produces deprecated messages on PHP 7
|
||||
- issue #11404 "Switch to copied table" doesn't work
|
||||
- issue #11406 Missing quotes after calling "distinct values"
|
||||
- issue #11386 Cannot import database with long data in one column
|
||||
- issue #11410 SPATIAL index option is not clickable
|
||||
|
||||
4.4.13.1 (2015-08-08)
|
||||
- issue #11368 SQL error when importing phpMyAdmin dump file
|
||||
|
||||
@ -9,12 +9,6 @@
|
||||
<exclude name="PEAR.Commenting.FunctionComment" />
|
||||
<exclude name="Generic.Commenting.DocComment" />
|
||||
</rule>
|
||||
<rule ref="Generic.Files.LineLength">
|
||||
<properties>
|
||||
<property name="lineLimit" value="85"/>
|
||||
<property name="absoluteLineLimit" value="0"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="Generic.Metrics.NestingLevel" />
|
||||
<!-- There MUST NOT be trailing whitespace at the end of lines. -->
|
||||
<rule ref="Squiz.WhiteSpace.SuperfluousWhitespace" />
|
||||
|
||||
@ -24,6 +24,13 @@
|
||||
"require-dev": {
|
||||
"satooshi/php-coveralls": ">=0.6",
|
||||
"phpunit/phpunit": ">=3.7",
|
||||
"phpunit/phpunit-selenium": ">=1.2"
|
||||
}
|
||||
"phpunit/phpunit-selenium": ">=1.2",
|
||||
"squizlabs/php_codesniffer": "2.*"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "composer",
|
||||
"url": "https://www.phpmyadmin.net"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -36,12 +36,8 @@ if (isset($_REQUEST['dialog'])) {
|
||||
if (isset($_REQUEST['operation'])) {
|
||||
|
||||
if ($_REQUEST['operation'] == 'deletePage') {
|
||||
$result = PMA_deletePage($_REQUEST['selected_page']);
|
||||
if ($result) {
|
||||
$response->isSuccess(true);
|
||||
} else {
|
||||
$response->isSuccess(false);
|
||||
}
|
||||
$success = PMA_deletePage($_REQUEST['selected_page']);
|
||||
$response->isSuccess($success);
|
||||
} elseif ($_REQUEST['operation'] == 'savePage') {
|
||||
if ($_REQUEST['save_page'] == 'same') {
|
||||
$page = $_REQUEST['selected_page'];
|
||||
@ -49,11 +45,8 @@ if (isset($_REQUEST['operation'])) {
|
||||
$page = PMA_createNewPage($_REQUEST['selected_value'], $GLOBALS['db']);
|
||||
$response->addJSON('id', $page);
|
||||
}
|
||||
if (PMA_saveTablePositions($page)) {
|
||||
$response->isSuccess(true);
|
||||
} else {
|
||||
$response->isSuccess(false);
|
||||
}
|
||||
$success = PMA_saveTablePositions($page);
|
||||
$response->isSuccess($success);
|
||||
} elseif ($_REQUEST['operation'] == 'setDisplayField') {
|
||||
PMA_saveDisplayField(
|
||||
$_REQUEST['db'], $_REQUEST['table'], $_REQUEST['field']
|
||||
@ -81,56 +74,8 @@ if (isset($_REQUEST['operation'])) {
|
||||
$response->isSuccess($success);
|
||||
$response->addJSON('message', $message);
|
||||
} elseif ($_REQUEST['operation'] == 'save_setting_value') {
|
||||
$cfgRelation = PMA_getRelationsParam();
|
||||
|
||||
$cfgDesigner = array(
|
||||
'user' => $GLOBALS['cfg']['Server']['user'],
|
||||
'db' => $cfgRelation['db'],
|
||||
'table' => $cfgRelation['designer_settings']
|
||||
);
|
||||
if (! empty($cfgDesigner['user'])
|
||||
&& ! empty($cfgDesigner['db'])
|
||||
&& ! empty($cfgDesigner['table'])
|
||||
&& $GLOBALS['cfgRelation']['designersettingswork']
|
||||
) {
|
||||
$orig_data_query = 'SELECT ' . PMA_Util::backquote('settings_data')
|
||||
. ' FROM `' . $cfgDesigner['db'] . '`.`' . $cfgDesigner['table']
|
||||
. '` WHERE ' . PMA_Util::backquote('username') . ' = "'
|
||||
. $cfgDesigner['user'] . '"';
|
||||
|
||||
$orig_data = $GLOBALS['dbi']->fetchSingleRow($orig_data_query);
|
||||
|
||||
$success = false;
|
||||
|
||||
if (isset($orig_data)
|
||||
&& ! empty($orig_data)
|
||||
&& $orig_data
|
||||
) {
|
||||
$orig_data = json_decode($orig_data['settings_data'], true);
|
||||
$orig_data[$_REQUEST['index']] = $_REQUEST['value'];
|
||||
$orig_data = json_encode($orig_data);
|
||||
|
||||
$save_query = 'UPDATE `' . $cfgDesigner['db'] . '`.`'
|
||||
. $cfgDesigner['table'] . '` SET '
|
||||
. PMA_Util::backquote('settings_data') . ' = \''
|
||||
. $orig_data . '\' WHERE ' . PMA_Util::backquote('username')
|
||||
. ' = "' . $cfgDesigner['user'] . '";';
|
||||
|
||||
$success = $GLOBALS['dbi']->query($save_query);
|
||||
} else {
|
||||
$save_data = array($_REQUEST['index'] => $_REQUEST['value']);
|
||||
|
||||
$query = 'INSERT INTO ' . PMA_Util::backquote($cfgDesigner['db'])
|
||||
. '.' . PMA_Util::backquote($cfgDesigner['table'])
|
||||
. ' VALUES("' . PMA_Util::sqlAddSlashes($cfgDesigner['user'])
|
||||
. '", \''
|
||||
. PMA_Util::sqlAddSlashes(json_encode($save_data)) . '\');';
|
||||
|
||||
$success = $GLOBALS['dbi']->query($query);
|
||||
}
|
||||
|
||||
$response->isSuccess($success);
|
||||
}
|
||||
$success = PMA_saveDesignerSetting($_REQUEST['index'], $_REQUEST['value']);
|
||||
$response->isSuccess($success);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@ -22,5 +22,10 @@ $scripts->addFile('import.js');
|
||||
require 'libraries/db_common.inc.php';
|
||||
require 'libraries/db_info.inc.php';
|
||||
|
||||
$import_type = 'database';
|
||||
require 'libraries/display_import.inc.php';
|
||||
require 'libraries/display_import.lib.php';
|
||||
$response = PMA_Response::getInstance();
|
||||
$response->addHTML(
|
||||
PMA_getImportDisplay(
|
||||
'database', $db, $table, $max_upload_size
|
||||
)
|
||||
);
|
||||
|
||||
@ -12,34 +12,26 @@ require_once 'libraries/common.inc.php';
|
||||
require_once 'libraries/db_common.inc.php';
|
||||
require_once 'libraries/db_info.inc.php';
|
||||
require_once 'libraries/di/Container.class.php';
|
||||
require_once 'libraries/controllers/StructureController.class.php';
|
||||
require_once 'libraries/controllers/DatabaseStructureController.class.php';
|
||||
|
||||
$container = DI\Container::getDefaultContainer();
|
||||
$container->factory('PMA\Controllers\StructureController');
|
||||
$container->factory('PMA\Controllers\DatabaseStructureController');
|
||||
$container->alias(
|
||||
'StructureController', 'PMA\Controllers\StructureController'
|
||||
'DatabaseStructureController', 'PMA\Controllers\DatabaseStructureController'
|
||||
);
|
||||
|
||||
global $db, $table, $pos, $db_is_system_schema, $total_num_tables, $tables,
|
||||
$num_tables, $tbl_is_view, $tbl_storage_engine, $table_info_num_rows, $tbl_collation, $showtable;
|
||||
global $db, $pos, $db_is_system_schema, $total_num_tables, $tables, $num_tables;
|
||||
/* Define dependencies for the concerned controller */
|
||||
$dependency_definitions = array(
|
||||
'db' => $db,
|
||||
'table' => $table,
|
||||
'type' => 'db',
|
||||
'url_query' => &$GLOBALS['url_query'],
|
||||
'pos' => $pos,
|
||||
'db_is_system_schema' => $db_is_system_schema,
|
||||
'num_tables' => $num_tables,
|
||||
'total_num_tables' => $total_num_tables,
|
||||
'tables' => $tables,
|
||||
'tbl_is_view' => $tbl_is_view,
|
||||
'tbl_storage_engine' => $tbl_storage_engine,
|
||||
'table_info_num_rows' => $table_info_num_rows,
|
||||
'tbl_collation' => $tbl_collation,
|
||||
'showtable' => $showtable
|
||||
);
|
||||
|
||||
/** @var Controllers\StructureController $controller */
|
||||
$controller = $container->get('StructureController', $dependency_definitions);
|
||||
/** @var Controllers\DatabaseStructureController $controller */
|
||||
$controller = $container->get('DatabaseStructureController', $dependency_definitions);
|
||||
$controller->indexAction();
|
||||
|
||||
229
db_tracking.php
229
db_tracking.php
@ -110,234 +110,19 @@ $all_tables_result = PMA_queryAsControlUser($all_tables_query);
|
||||
|
||||
// If a HEAD version exists
|
||||
if ($GLOBALS['dbi']->numRows($all_tables_result) > 0) {
|
||||
?>
|
||||
<div id="tracked_tables">
|
||||
<h3><?php echo __('Tracked tables');?></h3>
|
||||
|
||||
<form method="post" action="db_tracking.php" name="trackedForm"
|
||||
id="trackedForm" class="ajax">
|
||||
<?php
|
||||
echo PMA_URL_getHiddenInputs($GLOBALS['db'])
|
||||
?>
|
||||
<table id="versions" class="data">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th><?php echo __('Table');?></th>
|
||||
<th><?php echo __('Last version');?></th>
|
||||
<th><?php echo __('Created');?></th>
|
||||
<th><?php echo __('Updated');?></th>
|
||||
<th><?php echo __('Status');?></th>
|
||||
<th><?php echo __('Action');?></th>
|
||||
<th><?php echo __('Show');?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
|
||||
// Print out information about versions
|
||||
|
||||
$delete = PMA_Util::getIcon('b_drop.png', __('Delete tracking'));
|
||||
$versions = PMA_Util::getIcon('b_versions.png', __('Versions'));
|
||||
$report = PMA_Util::getIcon('b_report.png', __('Tracking report'));
|
||||
$structure = PMA_Util::getIcon('b_props.png', __('Structure snapshot'));
|
||||
|
||||
$style = 'odd';
|
||||
while ($one_result = $GLOBALS['dbi']->fetchArray($all_tables_result)) {
|
||||
list($table_name, $version_number) = $one_result;
|
||||
$table_query = ' SELECT * FROM ' .
|
||||
PMA_Util::backquote($cfgRelation['db']) . '.' .
|
||||
PMA_Util::backquote($cfgRelation['tracking']) .
|
||||
' WHERE `db_name` = \'' . PMA_Util::sqlAddSlashes($_REQUEST['db'])
|
||||
. '\' AND `table_name` = \'' . PMA_Util::sqlAddSlashes($table_name)
|
||||
. '\' AND `version` = \'' . $version_number . '\'';
|
||||
|
||||
$table_result = PMA_queryAsControlUser($table_query);
|
||||
$version_data = $GLOBALS['dbi']->fetchArray($table_result);
|
||||
|
||||
$tmp_link = 'tbl_tracking.php' . $url_query . '&table='
|
||||
. htmlspecialchars($version_data['table_name']);
|
||||
$delete_link = 'db_tracking.php' . $url_query . '&table='
|
||||
. htmlspecialchars($version_data['table_name'])
|
||||
. '&delete_tracking=true&';
|
||||
$checkbox_id = "selected_tbl_"
|
||||
. htmlspecialchars($version_data['table_name']);
|
||||
?>
|
||||
<tr class="<?php echo $style;?>">
|
||||
<td class="center">
|
||||
<input type="checkbox" name="selected_tbl[]"
|
||||
class="checkall" id="<?php echo $checkbox_id;?>"
|
||||
value="<?php echo htmlspecialchars($version_data['table_name']);?>"/>
|
||||
</td>
|
||||
<th>
|
||||
<label for="<?php echo $checkbox_id;?>">
|
||||
<?php echo htmlspecialchars($version_data['table_name']);?>
|
||||
</label>
|
||||
</th>
|
||||
<td class="right"><?php echo $version_data['version'];?></td>
|
||||
<td><?php echo $version_data['date_created'];?></td>
|
||||
<td><?php echo $version_data['date_updated'];?></td>
|
||||
<td>
|
||||
<?php
|
||||
$state = PMA_getVersionStatus($version_data);
|
||||
$options = array(
|
||||
0 => array(
|
||||
'label' => __('not active'),
|
||||
'value' => 'deactivate_now',
|
||||
'selected' => ($state != 'active')
|
||||
),
|
||||
1 => array(
|
||||
'label' => __('active'),
|
||||
'value' => 'activate_now',
|
||||
'selected' => ($state == 'active')
|
||||
)
|
||||
);
|
||||
echo PMA_Util::toggleButton(
|
||||
$tmp_link . '&version=' . $version_data['version'],
|
||||
'toggle_activation',
|
||||
$options,
|
||||
null
|
||||
);
|
||||
?>
|
||||
</td>
|
||||
<td>
|
||||
<a class="delete_tracking_anchor ajax"
|
||||
href="<?php echo $delete_link;?>" >
|
||||
<?php echo $delete; ?></a>
|
||||
<?php
|
||||
echo '</td>'
|
||||
. '<td>'
|
||||
. '<a href="' . $tmp_link . '">' . $versions . '</a>'
|
||||
. ' '
|
||||
. '<a href="' . $tmp_link . '&report=true&version='
|
||||
. $version_data['version'] . '">' . $report . '</a>'
|
||||
. ' '
|
||||
. '<a href="' . $tmp_link . '&snapshot=true&version='
|
||||
. $version_data['version'] . '">' . $structure . '</a>'
|
||||
. '</td>'
|
||||
. '</tr>';
|
||||
if ($style == 'even') {
|
||||
$style = 'odd';
|
||||
} else {
|
||||
$style = 'even';
|
||||
}
|
||||
}
|
||||
unset($tmp_link);
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php
|
||||
echo PMA_Util::getWithSelected($pmaThemeImage, $text_dir, "trackedForm");
|
||||
echo PMA_Util::getButtonOrImage(
|
||||
'submit_mult', 'mult_submit', 'submit_mult_delete_tracking',
|
||||
__('Delete tracking'), 'b_drop.png', 'delete_tracking'
|
||||
PMA_displayTrackedTables(
|
||||
$GLOBALS['db'], $all_tables_result, $url_query, $pmaThemeImage,
|
||||
$text_dir, $cfgRelation
|
||||
);
|
||||
?>
|
||||
</form>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
$sep = $GLOBALS['cfg']['NavigationTreeTableSeparator'];
|
||||
|
||||
// Get list of tables
|
||||
$table_list = PMA_Util::getTableList($GLOBALS['db']);
|
||||
|
||||
$my_tables = array();
|
||||
|
||||
// For each table try to get the tracking version
|
||||
foreach ($table_list as $key => $value) {
|
||||
// If $value is a table group.
|
||||
if (array_key_exists(('is' . $sep . 'group'), $value)
|
||||
&& $value['is' . $sep . 'group']
|
||||
) {
|
||||
foreach ($value as $temp_table) {
|
||||
// If $temp_table is a table with the value for 'Name' is set,
|
||||
// rather than a property of the table group.
|
||||
if (is_array($temp_table)
|
||||
&& array_key_exists('Name', $temp_table)
|
||||
) {
|
||||
$tracking_version = PMA_Tracker::getVersion(
|
||||
$GLOBALS['db'],
|
||||
$temp_table['Name']
|
||||
);
|
||||
if ($tracking_version == -1) {
|
||||
$my_tables[] = $temp_table['Name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // If $value is a table.
|
||||
if (PMA_Tracker::getVersion($GLOBALS['db'], $value['Name']) == -1) {
|
||||
$my_tables[] = $value['Name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$untracked_tables = PMA_getUntrackedTables($GLOBALS['db']);
|
||||
|
||||
// If untracked tables exist
|
||||
if (count($my_tables) > 0) {
|
||||
?>
|
||||
<h3><?php echo __('Untracked tables');?></h3>
|
||||
<form method="post" action="db_tracking.php" name="untrackedForm"
|
||||
id="untrackedForm" class="ajax">
|
||||
<?php
|
||||
echo PMA_URL_getHiddenInputs($GLOBALS['db'])
|
||||
?>
|
||||
<table id="noversions" class="data">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th style="width: 300px"><?php echo __('Table');?></th>
|
||||
<th><?php echo __('Action');?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
// Print out list of untracked tables
|
||||
|
||||
$style = 'odd';
|
||||
|
||||
foreach ($my_tables as $key => $tablename) {
|
||||
$checkbox_id = "selected_tbl_"
|
||||
. htmlspecialchars($tablename);
|
||||
if (PMA_Tracker::getVersion($GLOBALS['db'], $tablename) == -1) {
|
||||
$my_link = '<a href="tbl_tracking.php' . $url_query
|
||||
. '&table=' . htmlspecialchars($tablename) . '">';
|
||||
$my_link .= PMA_Util::getIcon('eye.png', __('Track table'));
|
||||
$my_link .= '</a>';
|
||||
?>
|
||||
<tr class="<?php echo $style;?>">
|
||||
<td class="center">
|
||||
<input type="checkbox" name="selected_tbl[]"
|
||||
class="checkall" id="<?php echo $checkbox_id;?>"
|
||||
value="<?php echo htmlspecialchars($tablename);?>"/>
|
||||
</td>
|
||||
<th>
|
||||
<label for="<?php echo $checkbox_id;?>">
|
||||
<?php echo htmlspecialchars($tablename);?>
|
||||
</label>
|
||||
</th>
|
||||
<td><?php echo $my_link;?></td>
|
||||
</tr>
|
||||
<?php
|
||||
if ($style == 'even') {
|
||||
$style = 'odd';
|
||||
} else {
|
||||
$style = 'even';
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php
|
||||
echo PMA_Util::getWithSelected($pmaThemeImage, $text_dir, "untrackedForm");
|
||||
echo PMA_Util::getButtonOrImage(
|
||||
'submit_mult', 'mult_submit', 'submit_mult_track',
|
||||
__('Track table'), 'eye.png', 'track'
|
||||
if (count($untracked_tables) > 0) {
|
||||
PMA_displayUntrackedTables(
|
||||
$GLOBALS['db'], $untracked_tables, $url_query, $pmaThemeImage, $text_dir
|
||||
);
|
||||
?>
|
||||
</form>
|
||||
<?php
|
||||
}
|
||||
// If available print out database log
|
||||
if (count($data['ddlog']) > 0) {
|
||||
|
||||
@ -402,6 +402,18 @@ Credits, in chronological order
|
||||
|
||||
* Export with table/column name changes
|
||||
|
||||
* Dan Ungureanu (Google Summer of Code 2015)
|
||||
|
||||
* New parser and analyzer
|
||||
|
||||
* Nisarg Jhaveri (Google Summer of Code 2015)
|
||||
|
||||
* Page-related settings
|
||||
|
||||
* SQL debugging integration to the Console
|
||||
|
||||
* Other UI improvements
|
||||
|
||||
And also to the following people who have contributed minor changes,
|
||||
enhancements, bugfixes or support for a new language since version
|
||||
2.1.0:
|
||||
|
||||
@ -385,8 +385,7 @@ MMCache but upgrading MMCache to version 2.3.21 solves the problem.
|
||||
|
||||
Yes.
|
||||
|
||||
Since release 4.1 phpMyAdmin supports only PHP 5.3 and newer. For PHP 5.2 you
|
||||
can use 4.0.x releases.
|
||||
Since release 4.5, phpMyAdmin supports only PHP 5.5 and newer. Since release 4.1 phpMyAdmin supports only PHP 5.3 and newer. For PHP 5.2 you can use 4.0.x releases.
|
||||
|
||||
.. _faq1_32:
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ web server (such as Apache, nginx, :term:`IIS`) to install phpMyAdmin's files in
|
||||
PHP
|
||||
---
|
||||
|
||||
* You need PHP 5.3.0 or newer, with ``session`` support, the Standard PHP Library
|
||||
* You need PHP 5.5.0 or newer, with ``session`` support, the Standard PHP Library
|
||||
(SPL) extension, JSON support, and the ``mbstring`` extension.
|
||||
|
||||
* To support uploading of ZIP files, you need the PHP ``zip`` extension.
|
||||
|
||||
@ -253,9 +253,16 @@ Verifying phpMyAdmin releases
|
||||
+++++++++++++++++++++++++++++
|
||||
|
||||
Since July 2015 all phpMyAdmin releases are cryptographically signed by the
|
||||
releasing developer. You should verify that the signature matches the archive
|
||||
you have downloaded. This way you can be sure that you are using the same code
|
||||
that was released.
|
||||
releasing developer, who is currently Marc Delisle. His key id is
|
||||
0x81AF644A, his PGP fingerprint is:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
436F F188 4B1A 0C3F DCBF 0D79 FEFC 65D1 81AF 644A
|
||||
|
||||
and you can get more identification information from `https://keybase.io/lem9 <https://keybase.io/lem9>`_. You should verify that the signature matches
|
||||
the archive you have downloaded. This way you can be sure that you are using
|
||||
the same code that was released.
|
||||
|
||||
Each archive is accompanied with ``.asc`` files which contains the PGP signature
|
||||
for it. Once you have both of them in the same folder, you can verify the signature:
|
||||
|
||||
@ -114,7 +114,6 @@ if (!defined('TESTSUITE')) {
|
||||
'sql_create_database',
|
||||
'sql_drop_table',
|
||||
'sql_procedure_function',
|
||||
'sql_create_table_statements',
|
||||
'sql_create_table',
|
||||
'sql_create_view',
|
||||
'sql_create_trigger',
|
||||
|
||||
BIN
favicon.ico
BIN
favicon.ico
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 22 KiB |
@ -301,7 +301,7 @@ for ($a = 0; $a < $geom_count; $a++) {
|
||||
echo '<label for="y">' . __("Y") . '</label>';
|
||||
echo '<input type="text" name="gis_data[' . $a . '][' . $type . ']['
|
||||
. $i . '][' . $j . '][y]"' . ' value="'
|
||||
. escape($gis_data[$a][$type][$i][$j]['x']) . '" />';
|
||||
. escape($gis_data[$a][$type][$i][$j]['y']) . '" />';
|
||||
}
|
||||
echo '<input type="submit" name="gis_data[' . $a . '][' . $type . ']['
|
||||
. $i . '][add_point]"'
|
||||
|
||||
@ -690,7 +690,7 @@ if (! empty($id_bookmark) && $_REQUEST['action_bookmark'] == 2) {
|
||||
if ($import_notice) {
|
||||
$message->addString($import_notice);
|
||||
}
|
||||
if (isset($local_import_file)) {
|
||||
if (! empty($local_import_file)) {
|
||||
$message->addString('(' . htmlspecialchars($local_import_file) . ')');
|
||||
} else {
|
||||
$message->addString(
|
||||
|
||||
50
index.php
50
index.php
@ -15,6 +15,7 @@ require_once 'libraries/common.inc.php';
|
||||
* display Git revision if requested
|
||||
*/
|
||||
require_once 'libraries/display_git_revision.lib.php';
|
||||
require_once 'libraries/Template.class.php';
|
||||
|
||||
/**
|
||||
* pass variables to child pages
|
||||
@ -187,7 +188,7 @@ if ($server > 0 || count($cfg['Servers']) > 1
|
||||
if ($cfg['ShowChgPassword']) {
|
||||
$conditional_class = 'ajax';
|
||||
PMA_printListItem(
|
||||
PMA_Util::getImage('s_passwd.png') . " " . __('Change password'),
|
||||
PMA_Util::getImage('s_passwd.png') . " " . __('Change password'),
|
||||
'li_change_password',
|
||||
'user_password.php' . $common_url_query,
|
||||
null,
|
||||
@ -202,7 +203,7 @@ if ($server > 0 || count($cfg['Servers']) > 1
|
||||
echo ' <form method="post" action="index.php">' . "\n"
|
||||
. PMA_URL_getHiddenInputs(null, null, 4, 'collation_connection')
|
||||
. ' <label for="select_collation_connection">' . "\n"
|
||||
. ' ' . PMA_Util::getImage('s_asci.png') . " "
|
||||
. ' ' . PMA_Util::getImage('s_asci.png') . " "
|
||||
. __('Server connection collation') . "\n"
|
||||
// put the doc link in the form so that it appears on the same line
|
||||
. PMA_Util::showMySQLDocu('Charset-connection')
|
||||
@ -255,7 +256,7 @@ echo '</ul>';
|
||||
if ($server > 0) {
|
||||
echo '<ul>';
|
||||
PMA_printListItem(
|
||||
PMA_Util::getImage('b_tblops.png') . " " . __('More settings'),
|
||||
PMA_Util::getImage('b_tblops.png') . " " . __('More settings'),
|
||||
'li_user_preferences',
|
||||
'prefs_manage.php' . $common_url_query,
|
||||
null,
|
||||
@ -698,32 +699,19 @@ function PMA_printListItem($name, $listId = null, $url = null,
|
||||
$mysql_help_page = null, $target = null, $a_id = null, $class = null,
|
||||
$a_class = null
|
||||
) {
|
||||
echo '<li id="' . $listId . '"';
|
||||
if (null !== $class) {
|
||||
echo ' class="' . $class . '"';
|
||||
}
|
||||
echo '>';
|
||||
if (null !== $url) {
|
||||
echo '<a href="' . $url . '"';
|
||||
if (null !== $target) {
|
||||
echo ' target="' . $target . '"';
|
||||
}
|
||||
if (null !== $a_id) {
|
||||
echo ' id="' . $a_id . '"';
|
||||
}
|
||||
if (null !== $a_class) {
|
||||
echo ' class="' . $a_class . '"';
|
||||
}
|
||||
echo '>';
|
||||
}
|
||||
|
||||
echo $name;
|
||||
|
||||
if (null !== $url) {
|
||||
echo '</a>' . "\n";
|
||||
}
|
||||
if (null !== $mysql_help_page) {
|
||||
echo PMA_Util::showMySQLDocu($mysql_help_page);
|
||||
}
|
||||
echo '</li>';
|
||||
echo PMA\Template::get('list/item')
|
||||
->render(
|
||||
array(
|
||||
'content' => $name,
|
||||
'id' => $listId,
|
||||
'class' => $class,
|
||||
'url' => array(
|
||||
'href' => $url,
|
||||
'target' => $target,
|
||||
'id' => $a_id,
|
||||
'class' => $a_class,
|
||||
),
|
||||
'mysql_help_page' => $mysql_help_page,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
13
js/export.js
13
js/export.js
@ -539,19 +539,6 @@ function toggle_table_select(row) {
|
||||
}
|
||||
|
||||
AJAX.registerOnload('export.js', function () {
|
||||
/**
|
||||
* For SQL plugin, if "CREATE TABLE options" is checked/unchecked, check/uncheck each of its sub-options
|
||||
*/
|
||||
var $create = $("#checkbox_sql_create_table_statements");
|
||||
var $create_options = $("#ul_create_table_statements input");
|
||||
$create.change(function () {
|
||||
$create_options.prop('checked', $(this).prop("checked"));
|
||||
});
|
||||
$create_options.change(function () {
|
||||
if ($create_options.is(":checked")) {
|
||||
$create.prop('checked', true);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Disables the view output as text option if the output must be saved as a file
|
||||
|
||||
@ -4036,7 +4036,7 @@ function PMA_init_slider()
|
||||
var $wrapper = $('<div>', {'class': 'slide-wrapper'});
|
||||
$wrapper.toggle($this.is(':visible'));
|
||||
$('<a>', {href: '#' + this.id, "class": 'ajax'})
|
||||
.text(this.title)
|
||||
.text($this.attr('title'))
|
||||
.prepend($('<span>'))
|
||||
.insertBefore($this)
|
||||
.click(function () {
|
||||
@ -4053,6 +4053,7 @@ function PMA_init_slider()
|
||||
return false;
|
||||
});
|
||||
$this.wrap($wrapper);
|
||||
$this.removeAttr('title');
|
||||
PMA_set_status_label($this);
|
||||
$this.data('slider_init_done', 1);
|
||||
});
|
||||
|
||||
@ -534,6 +534,7 @@ AJAX.registerOnload('normalization.js', function() {
|
||||
"db": PMA_commonParams.get('db'),
|
||||
"table": PMA_commonParams.get('table'),
|
||||
"dropped_column": selectedCol,
|
||||
"purge" : 1,
|
||||
"sql_query": 'ALTER TABLE `' + PMA_commonParams.get('table') + '` DROP `' + selectedCol + '`;',
|
||||
"is_js_confirmed": 1
|
||||
},
|
||||
|
||||
@ -162,7 +162,7 @@ function verificationsAfterFieldChange(urlField, multi_edit, theType)
|
||||
{
|
||||
var evt = window.event || arguments.callee.caller.arguments[0];
|
||||
var target = evt.target || evt.srcElement;
|
||||
var $this_input = $("input[name='fields[multi_edit][" + multi_edit + "][" +
|
||||
var $this_input = $(":input[name^='fields[multi_edit][" + multi_edit + "][" +
|
||||
urlField + "]']");
|
||||
// the function drop-down that corresponds to this input field
|
||||
var $this_function = $("select[name='funcs[multi_edit][" + multi_edit + "][" +
|
||||
@ -172,12 +172,6 @@ function verificationsAfterFieldChange(urlField, multi_edit, theType)
|
||||
function_selected = true;
|
||||
}
|
||||
|
||||
// check if it is textarea rather than input
|
||||
if ($this_input.length === 0) {
|
||||
$this_input = $("textarea[name='fields[multi_edit][" + multi_edit + "][" +
|
||||
urlField + "]']");
|
||||
}
|
||||
|
||||
//To generate the textbox that can take the salt
|
||||
var new_salt_box = "<br><input type=text name=salt[multi_edit][" + multi_edit + "][" + urlField + "]" +
|
||||
" id=salt_" + target.id + " placeholder='" + PMA_messages.strEncryptionKey + "'>";
|
||||
|
||||
@ -14,8 +14,8 @@ var defaultX = 0;
|
||||
var defaultY = 0;
|
||||
|
||||
// Variables
|
||||
var x;
|
||||
var y;
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
var scale = 1;
|
||||
|
||||
var svg;
|
||||
|
||||
@ -27,7 +27,10 @@ AJAX.registerOnload('tbl_operations.js', function () {
|
||||
$.post($form.attr('action'), $form.serialize() + "&submit_copy=Go", function (data) {
|
||||
if (typeof data !== 'undefined' && data.success === true) {
|
||||
if ($form.find("input[name='switch_to_new']").prop('checked')) {
|
||||
PMA_commonParams.set('db', data.db);
|
||||
PMA_commonParams.set(
|
||||
'db',
|
||||
$form.find("select[name='target_db']").val()
|
||||
);
|
||||
PMA_commonParams.set(
|
||||
'table',
|
||||
$form.find("input[name='new_name']").val()
|
||||
|
||||
@ -92,6 +92,13 @@ AJAX.registerOnload('tbl_select.js', function () {
|
||||
"!= ''"
|
||||
];
|
||||
|
||||
var geomUnaryFunctions = [
|
||||
'IsEmpty',
|
||||
'IsSimple',
|
||||
'IsRing',
|
||||
'IsClosed',
|
||||
];
|
||||
|
||||
// jQuery object to reuse
|
||||
var $search_form = $(this);
|
||||
event.preventDefault();
|
||||
@ -120,6 +127,11 @@ AJAX.registerOnload('tbl_select.js', function () {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (values['geom_func[' + a + ']'] &&
|
||||
$.isArray(values['geom_func[' + a + ']'], geomUnaryFunctions) >= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (values['criteriaValues[' + a + ']'] === '' || values['criteriaValues[' + a + ']'] === null) {
|
||||
delete values['criteriaValues[' + a + ']'];
|
||||
delete values['criteriaColumnOperators[' + a + ']'];
|
||||
|
||||
@ -85,6 +85,7 @@ AJAX.registerTeardown('tbl_structure.js', function () {
|
||||
$(document).off('click', "#printView");
|
||||
$(document).off('submit', ".append_fields_form.ajax");
|
||||
$('body').off('click', '#fieldsForm.ajax button[name="submit_mult"], #fieldsForm.ajax input[name="submit_mult"]');
|
||||
$(document).off('click', 'a[name^=partition_action].ajax');
|
||||
});
|
||||
|
||||
AJAX.registerOnload('tbl_structure.js', function () {
|
||||
@ -432,6 +433,35 @@ AJAX.registerOnload('tbl_structure.js', function () {
|
||||
AJAX.source = $form;
|
||||
$.post($form.attr('action'), submitData, AJAX.responseHandler);
|
||||
});
|
||||
|
||||
/**
|
||||
* Handles clicks on Action links in partition table
|
||||
*/
|
||||
$(document).on('click', 'a[name^=partition_action].ajax', function (e) {
|
||||
e.preventDefault();
|
||||
var $link = $(this);
|
||||
|
||||
function submitPartitionAction(url) {
|
||||
var submitData = '&ajax_request=true&ajax_page_request=true';
|
||||
PMA_ajaxShowMessage();
|
||||
AJAX.source = $link;
|
||||
$.post(url, submitData, AJAX.responseHandler);
|
||||
}
|
||||
|
||||
if ($link.is('#partition_action_DROP')) {
|
||||
var question = PMA_messages.strDropPartitionWarning;
|
||||
$link.PMA_confirm(question, $link.attr('href'), function (url) {
|
||||
submitPartitionAction(url);
|
||||
});
|
||||
} else if ($link.is('#partition_action_TRUNCATE')) {
|
||||
var question = PMA_messages.strTruncatePartitionWarning;
|
||||
$link.PMA_confirm(question, $link.attr('href'), function (url) {
|
||||
submitPartitionAction(url);
|
||||
});
|
||||
} else {
|
||||
submitPartitionAction($link.attr('href'));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/** Handler for "More" dropdown in structure table rows */
|
||||
|
||||
@ -1371,8 +1371,10 @@ class PMA_Config
|
||||
// Add hostname
|
||||
$pma_absolute_uri .= $url['host'];
|
||||
// Add port, if it not the default one
|
||||
// (or 80 for https which is most likely a bug)
|
||||
if (! empty($url['port'])
|
||||
&& (($url['scheme'] == 'http' && $url['port'] != 80)
|
||||
|| ($url['scheme'] == 'https' && $url['port'] != 80)
|
||||
|| ($url['scheme'] == 'https' && $url['port'] != 443))
|
||||
) {
|
||||
$pma_absolute_uri .= ':' . $url['port'];
|
||||
|
||||
@ -3161,7 +3161,9 @@ class PMA_DisplayResults
|
||||
|
||||
$display_params = $this->__get('display_params');
|
||||
|
||||
if ($meta->numeric == 1) {
|
||||
// in some situations (issue 11406), numeric returns 1
|
||||
// even for a string type
|
||||
if ($meta->numeric == 1 && $meta->type != 'string') {
|
||||
// n u m e r i c
|
||||
|
||||
$display_params['data'][$row_no][$i]
|
||||
@ -3728,7 +3730,7 @@ class PMA_DisplayResults
|
||||
/**
|
||||
* Prepare data cell for numeric type fields
|
||||
*
|
||||
* @param string $column the relevant column in data row
|
||||
* @param string $column the column's value
|
||||
* @param string $class the html class for column
|
||||
* @param boolean $condition_field the column should highlighted
|
||||
* or not
|
||||
|
||||
@ -165,8 +165,8 @@ class PMA_Menu
|
||||
private function _getBreadcrumbs()
|
||||
{
|
||||
$retval = '';
|
||||
$table = new PMA_Table($this->_table, $this->_db);
|
||||
$tbl_is_view = $table->isView();
|
||||
$tbl_is_view = $GLOBALS['dbi']->getTable($this->_db, $this->_table)
|
||||
->isView();
|
||||
$server_info = ! empty($GLOBALS['cfg']['Server']['verbose'])
|
||||
? $GLOBALS['cfg']['Server']['verbose']
|
||||
: $GLOBALS['cfg']['Server']['host'];
|
||||
@ -299,8 +299,8 @@ class PMA_Menu
|
||||
private function _getTableTabs()
|
||||
{
|
||||
$db_is_system_schema = $GLOBALS['dbi']->isSystemSchema($this->_db);
|
||||
$table = new PMA_Table($this->_table, $this->_db);
|
||||
$tbl_is_view = $table->isView();
|
||||
$tbl_is_view = $GLOBALS['dbi']->getTable($this->_db, $this->_table)
|
||||
->isView();
|
||||
$is_superuser = $GLOBALS['dbi']->isSuperuser();
|
||||
$isCreateOrGrantUser = $GLOBALS['dbi']->isUserType('grant')
|
||||
|| $GLOBALS['dbi']->isUserType('create');
|
||||
|
||||
@ -9,13 +9,351 @@ if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a sub partition of a table
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
class PMA_SubPartition
|
||||
{
|
||||
/**
|
||||
* @var string the database
|
||||
*/
|
||||
protected $db;
|
||||
/**
|
||||
* @var string the table
|
||||
*/
|
||||
protected $table;
|
||||
/**
|
||||
* @var string partition name
|
||||
*/
|
||||
protected $name;
|
||||
/**
|
||||
* @var integer ordinal
|
||||
*/
|
||||
protected $ordinal;
|
||||
/**
|
||||
* @var string partition method
|
||||
*/
|
||||
protected $method;
|
||||
/**
|
||||
* @var string partition expression
|
||||
*/
|
||||
protected $expression;
|
||||
/**
|
||||
* @var integer no of table rows in the partition
|
||||
*/
|
||||
protected $rows;
|
||||
/**
|
||||
* @var integer data length
|
||||
*/
|
||||
protected $dataLength;
|
||||
/**
|
||||
* @var integer index length
|
||||
*/
|
||||
protected $indexLength;
|
||||
/**
|
||||
* @var string partition comment
|
||||
*/
|
||||
protected $comment;
|
||||
|
||||
/**
|
||||
* Constructs a partition
|
||||
*
|
||||
* @param array $row fetched row from information_schema.PARTITIONS
|
||||
*/
|
||||
public function __construct($row)
|
||||
{
|
||||
$this->db = $row['TABLE_SCHEMA'];
|
||||
$this->table = $row['TABLE_NAME'];
|
||||
$this->loadData($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads data from the fetched row from information_schema.PARTITIONS
|
||||
*
|
||||
* @param array $row fetched row
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function loadData($row)
|
||||
{
|
||||
$this->name = $row['SUBPARTITION_NAME'];
|
||||
$this->ordinal = $row['SUBPARTITION_ORDINAL_POSITION'];
|
||||
$this->method = $row['SUBPARTITION_METHOD'];
|
||||
$this->expression = $row['SUBPARTITION_EXPRESSION'];
|
||||
$this->loadCommonData($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads some data that is common to both partitions and sub partitions
|
||||
*
|
||||
* @param array $row fetched row
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function loadCommonData($row)
|
||||
{
|
||||
$this->rows = $row['TABLE_ROWS'];
|
||||
$this->dataLength = $row['DATA_LENGTH'];
|
||||
$this->indexLength = $row['INDEX_LENGTH'];
|
||||
$this->comment = $row['PARTITION_COMMENT'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the partition name
|
||||
*
|
||||
* @return string partition name
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ordinal of the partition
|
||||
*
|
||||
* @return number the ordinal
|
||||
*/
|
||||
public function getOrdinal()
|
||||
{
|
||||
return $this->ordinal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the partition method
|
||||
*
|
||||
* @return string partition method
|
||||
*/
|
||||
public function getMethod()
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the partition expression
|
||||
*
|
||||
* @return string partition expression
|
||||
*/
|
||||
public function getExpression()
|
||||
{
|
||||
return $this->expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of data rows
|
||||
*
|
||||
* @return integer number of rows
|
||||
*/
|
||||
public function getRows()
|
||||
{
|
||||
return $this->rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data length
|
||||
*
|
||||
* @return integer data length
|
||||
*/
|
||||
public function getDataLength()
|
||||
{
|
||||
return $this->dataLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index length
|
||||
*
|
||||
* @return integer index length
|
||||
*/
|
||||
public function getIndexLength()
|
||||
{
|
||||
return $this->indexLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the partition comment
|
||||
*
|
||||
* @return string partition comment
|
||||
*/
|
||||
public function getComment()
|
||||
{
|
||||
return $this->comment;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* base Partition Class
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
class PMA_Partition
|
||||
class PMA_Partition extends PMA_SubPartition
|
||||
{
|
||||
/**
|
||||
* @var string partition description
|
||||
*/
|
||||
protected $description;
|
||||
/**
|
||||
* @var PMA_SubPartition[] sub partitions
|
||||
*/
|
||||
protected $subPartitions = array();
|
||||
|
||||
/**
|
||||
* Loads data from the fetched row from information_schema.PARTITIONS
|
||||
*
|
||||
* @param array $row fetched row
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function loadData($row)
|
||||
{
|
||||
$this->name = $row['PARTITION_NAME'];
|
||||
$this->ordinal = $row['PARTITION_ORDINAL_POSITION'];
|
||||
$this->method = $row['PARTITION_METHOD'];
|
||||
$this->expression = $row['PARTITION_EXPRESSION'];
|
||||
$this->description = $row['PARTITION_DESCRIPTION'];
|
||||
// no sub partitions, load all data to this object
|
||||
if (empty($row['SUBPARTITION_NAME'])) {
|
||||
$this->loadCommonData($row);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the partiotion description
|
||||
*
|
||||
* @return string partition description
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a sub partition
|
||||
*
|
||||
* @param PMA_SubPartition $partition
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addSubPartition(PMA_SubPartition $partition)
|
||||
{
|
||||
$this->subPartitions[] = $partition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether there are sub partitions
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasSubPartitions()
|
||||
{
|
||||
return ! empty($this->subPartitions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of data rows
|
||||
*
|
||||
* @return integer number of rows
|
||||
*/
|
||||
public function getRows()
|
||||
{
|
||||
if (empty($this->subPartitions)) {
|
||||
return $this->rows;
|
||||
} else {
|
||||
$rows = 0;
|
||||
foreach ($this->subPartitions as $subPartition) {
|
||||
$rows += $subPartition->rows;
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total data length
|
||||
*
|
||||
* @return integer data length
|
||||
*/
|
||||
public function getDataLength()
|
||||
{
|
||||
if (empty($this->subPartitions)) {
|
||||
return $this->dataLength;
|
||||
} else {
|
||||
$dataLength = 0;
|
||||
foreach ($this->subPartitions as $subPartition) {
|
||||
$dataLength += $subPartition->dataLength;
|
||||
}
|
||||
return $dataLength;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tatal index length
|
||||
*
|
||||
* @return integer index length
|
||||
*/
|
||||
public function getIndexLength()
|
||||
{
|
||||
if (empty($this->subPartitions)) {
|
||||
return $this->indexLength;
|
||||
} else {
|
||||
$indexLength = 0;
|
||||
foreach ($this->subPartitions as $subPartition) {
|
||||
$indexLength += $subPartition->indexLength;
|
||||
}
|
||||
return $indexLength;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of sub partitions
|
||||
*
|
||||
* @return PMA_SubPartition[]
|
||||
*/
|
||||
public function getSubPartitions()
|
||||
{
|
||||
return $this->subPartitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of partitions for a specific db/table
|
||||
*
|
||||
* @param string $db database name
|
||||
* @param string $table table name
|
||||
*
|
||||
* @access public
|
||||
* @return PMA_Partition[]
|
||||
*/
|
||||
static public function getPartitions($db, $table)
|
||||
{
|
||||
if (PMA_Partition::havePartitioning()) {
|
||||
$result = $GLOBALS['dbi']->fetchResult(
|
||||
"SELECT * FROM `information_schema`.`PARTITIONS`"
|
||||
. " WHERE `TABLE_SCHEMA` = '" . PMA_Util::sqlAddSlashes($db)
|
||||
. "' AND `TABLE_NAME` = '" . PMA_Util::sqlAddSlashes($table) . "'"
|
||||
);
|
||||
if ($result) {
|
||||
$partitionMap = array();
|
||||
foreach ($result as $row) {
|
||||
if (isset($partitionMap[$row['PARTITION_NAME']])) {
|
||||
$partition = $partitionMap[$row['PARTITION_NAME']];
|
||||
} else {
|
||||
$partition = new PMA_Partition($row);
|
||||
$partitionMap[$row['PARTITION_NAME']] = $partition;
|
||||
}
|
||||
|
||||
if (! empty($row['SUBPARTITION_NAME'])) {
|
||||
$parentPartition = $partition;
|
||||
$partition = new PMA_SubPartition($row);
|
||||
$parentPartition->addSubPartition($partition);
|
||||
}
|
||||
}
|
||||
return array_values($partitionMap);
|
||||
}
|
||||
return array();
|
||||
} else {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns array of partition names for a specific db/table
|
||||
*
|
||||
|
||||
@ -2363,7 +2363,7 @@ class PMA_Table
|
||||
'SELECT COUNT(*) AS %s FROM %s.%s',
|
||||
PMA_Util::backquote('row_count'),
|
||||
PMA_Util::backquote($this->_db_name),
|
||||
PMA_Util::backquote($$this->_name)
|
||||
PMA_Util::backquote($this->_name)
|
||||
)
|
||||
);
|
||||
return $result['row_count'];
|
||||
|
||||
@ -1757,21 +1757,27 @@ class PMA_Util
|
||||
}
|
||||
|
||||
//Set the id for the tab, if set in the params
|
||||
$id_string = ( empty($tab['id']) ? '' : ' id="' . $tab['id'] . '" ' );
|
||||
$out = '<li' . ($tab['class'] == 'active' ? ' class="active"' : '') . '>';
|
||||
$tabId = (empty($tab['id']) ? null : $tab['id']);
|
||||
|
||||
if (! empty($tab['link'])) {
|
||||
$out .= '<a class="tab' . htmlentities($tab['class']) . '"'
|
||||
. $id_string
|
||||
. ' href="' . $tab['link'] . '" ' . $tab['attr'] . '>'
|
||||
. $tab['text'] . '</a>';
|
||||
$item = array();
|
||||
if (!empty($tab['link'])) {
|
||||
$item = array(
|
||||
'content' => $tab['text'],
|
||||
'url' => array(
|
||||
'href' => empty($tab['link']) ? null : $tab['link'],
|
||||
'id' => $tabId,
|
||||
'class' => 'tab' . htmlentities($tab['class']),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
$out .= '<span class="tab' . htmlentities($tab['class']) . '"'
|
||||
. $id_string . '>' . $tab['text'] . '</span>';
|
||||
$item['content'] = '<span class="tab' . htmlentities($tab['class']) . '"'
|
||||
. $tabId . '>' . $tab['text'] . '</span>';
|
||||
}
|
||||
|
||||
$out .= '</li>';
|
||||
return $out;
|
||||
$item['class'] = $tab['class'] == 'active' ? 'active' : '';
|
||||
|
||||
return Template::get('list/item')
|
||||
->render($item);
|
||||
} // end of the 'getHtmlTab()' function
|
||||
|
||||
/**
|
||||
|
||||
@ -42,8 +42,8 @@ if (getcwd() == dirname(__FILE__)) {
|
||||
* Minimum PHP version; can't call PMA_fatalError() which uses a
|
||||
* PHP 5 function, so cannot easily localize this message.
|
||||
*/
|
||||
if (version_compare(PHP_VERSION, '5.3.0', 'lt')) {
|
||||
die('PHP 5.3+ is required');
|
||||
if (version_compare(PHP_VERSION, '5.5.0', 'lt')) {
|
||||
die('PHP 5.5+ is required');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1965,7 +1965,7 @@ $cfg['Export']['sql_drop_table'] = false;
|
||||
* of VIEWs and the stand-in table
|
||||
* @global boolean $cfg['Export']['sql_if_not_exists']
|
||||
*/
|
||||
$cfg['Export']['sql_if_not_exists'] = true;
|
||||
$cfg['Export']['sql_if_not_exists'] = false;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -2086,13 +2086,6 @@ $cfg['Export']['sql_mime'] = false;
|
||||
*/
|
||||
$cfg['Export']['sql_header_comment'] = '';
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @global boolean $cfg['Export']['sql_create_table_statements']
|
||||
*/
|
||||
$cfg['Export']['sql_create_table_statements'] = true;
|
||||
|
||||
/**
|
||||
* Whether to use complete inserts, extended inserts, both, or neither
|
||||
*
|
||||
@ -3149,5 +3142,3 @@ $cfg['MysqlMinVersion'] = array(
|
||||
'internal' => 50500,
|
||||
'human' => '5.5.0'
|
||||
);
|
||||
|
||||
|
||||
|
||||
@ -50,12 +50,23 @@ function PMA_displayFormTop($action = null, $method = 'post', $hidden_fields = n
|
||||
*/
|
||||
function PMA_displayTabsTop($tabs)
|
||||
{
|
||||
$htmlOutput = '<ul class="tabs">';
|
||||
$items = array();
|
||||
foreach ($tabs as $tab_id => $tab_name) {
|
||||
$htmlOutput .= '<li><a href="#' . $tab_id . '">'
|
||||
. htmlspecialchars($tab_name) . '</a></li>';
|
||||
$items[] = array(
|
||||
'content' => htmlspecialchars($tab_name),
|
||||
'url' => array(
|
||||
'href' => '#' . $tab_id,
|
||||
),
|
||||
);
|
||||
}
|
||||
$htmlOutput .= '</ul>';
|
||||
|
||||
include_once './libraries/Template.class.php';
|
||||
$htmlOutput = PMA\Template::get('list/unordered')->render(
|
||||
array(
|
||||
'class' => 'tabs',
|
||||
'items' => $items,
|
||||
)
|
||||
);
|
||||
$htmlOutput .= '<br clear="right" />';
|
||||
$htmlOutput .= '<div class="tabs_contents">';
|
||||
return $htmlOutput;
|
||||
|
||||
@ -187,8 +187,6 @@ $strConfigExport_sql_auto_increment_name = __('Add AUTO_INCREMENT value');
|
||||
$strConfigExport_sql_backquotes_name
|
||||
= __('Enclose table and column names with backquotes');
|
||||
$strConfigExport_sql_compatibility_name = __('SQL compatibility mode');
|
||||
$strConfigExport_sql_create_table_statements_name
|
||||
= __('<code>CREATE TABLE</code> options:');
|
||||
$strConfigExport_sql_dates_name = __('Creation/Update/Check dates');
|
||||
$strConfigExport_sql_delayed_name = __('Use delayed inserts');
|
||||
$strConfigExport_sql_disable_fk_name = __('Disable foreign key checks');
|
||||
@ -205,7 +203,10 @@ $strConfigExport_sql_create_view_name = sprintf(__('Add %s'), 'CREATE VIEW');
|
||||
$strConfigExport_sql_create_trigger_name
|
||||
= sprintf(__('Add %s'), 'CREATE TRIGGER');
|
||||
$strConfigExport_sql_hex_for_binary_name = __('Use hexadecimal for BINARY & BLOB');
|
||||
$strConfigExport_sql_if_not_exists_name = sprintf(__('Add %s'), 'IF NOT EXISTS');
|
||||
$strConfigExport_sql_if_not_exists_name = __(
|
||||
'Add IF NOT EXISTS (less efficient as indexes will be generated during'
|
||||
. ' table creation)'
|
||||
);
|
||||
$strConfigExport_sql_ignore_name = __('Use ignore inserts');
|
||||
$strConfigExport_sql_include_comments_name = __('Comments');
|
||||
$strConfigExport_sql_insert_syntax_name = __('Syntax to use when inserting data');
|
||||
@ -1000,4 +1001,3 @@ $strConfigZeroConf_desc = __(
|
||||
. 'configuration storage tables automatically.'
|
||||
);
|
||||
$strConfigZeroConf_name = __('Enable Zero Configuration mode');
|
||||
|
||||
|
||||
@ -323,13 +323,12 @@ $forms['Export']['Sql'] = array('Export' => array(
|
||||
':group:' . __('Structure'),
|
||||
'sql_drop_table',
|
||||
'sql_procedure_function',
|
||||
'sql_create_table',
|
||||
'sql_create_view',
|
||||
'sql_create_trigger',
|
||||
'sql_create_table_statements' => ':group',
|
||||
'sql_create_table' => ':group',
|
||||
'sql_if_not_exists',
|
||||
'sql_auto_increment',
|
||||
':group:end',
|
||||
'sql_create_view',
|
||||
'sql_create_trigger',
|
||||
'sql_backquotes',
|
||||
':group:end',
|
||||
':group:' . __('Data'),
|
||||
|
||||
@ -220,14 +220,13 @@ $forms['Export']['Sql'] = array(
|
||||
':group:end',
|
||||
':group:' . __('Structure'),
|
||||
'Export/sql_drop_table',
|
||||
'Export/sql_create_table',
|
||||
'Export/sql_create_view',
|
||||
'Export/sql_procedure_function',
|
||||
'Export/sql_create_trigger',
|
||||
'Export/sql_create_table_statements' => ':group',
|
||||
'Export/sql_create_table' => ':group',
|
||||
'Export/sql_if_not_exists',
|
||||
'Export/sql_auto_increment',
|
||||
':group:end',
|
||||
'Export/sql_create_view',
|
||||
'Export/sql_procedure_function',
|
||||
'Export/sql_create_trigger',
|
||||
'Export/sql_backquotes',
|
||||
':group:end',
|
||||
':group:' . __('Data'),
|
||||
|
||||
39
libraries/controllers/DatabaseController.class.php
Normal file
39
libraries/controllers/DatabaseController.class.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Holds the PMA\DatabaseController
|
||||
*
|
||||
* @package PMA
|
||||
*/
|
||||
|
||||
namespace PMA\Controllers;
|
||||
|
||||
use PMA\DI\Container;
|
||||
|
||||
if (!defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once 'libraries/controllers/Controller.class.php';
|
||||
|
||||
/**
|
||||
* Handles database related logic
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
abstract class DatabaseController extends Controller
|
||||
{
|
||||
/**
|
||||
* @var string $db
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->db = $this->container->get('db');
|
||||
}
|
||||
}
|
||||
1052
libraries/controllers/DatabaseStructureController.class.php
Normal file
1052
libraries/controllers/DatabaseStructureController.class.php
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -166,7 +166,7 @@ class TableChartController extends TableController
|
||||
* Displays the page
|
||||
*/
|
||||
$this->response->addHTML(
|
||||
Template::get('tbl_chart')->render(
|
||||
Template::get('table/chart/tbl_chart')->render(
|
||||
array(
|
||||
'url_query' => $this->url_query,
|
||||
'url_params' => $url_params,
|
||||
|
||||
@ -124,7 +124,9 @@ class TableGisVisualizationController extends TableController
|
||||
$this->visualizationSettings = $_REQUEST['visualizationSettings'];
|
||||
}
|
||||
|
||||
if (! isset($this->visualizationSettings['labelColumn']) && isset($labelCandidates[0])) {
|
||||
if (!isset($this->visualizationSettings['labelColumn'])
|
||||
&& isset($labelCandidates[0])
|
||||
) {
|
||||
$this->visualizationSettings['labelColumn'] = '';
|
||||
}
|
||||
|
||||
@ -134,7 +136,8 @@ class TableGisVisualizationController extends TableController
|
||||
}
|
||||
|
||||
// Convert geometric columns from bytes to text.
|
||||
$pos = isset($_REQUEST['pos']) ? $_REQUEST['pos'] : $_SESSION['tmpval']['pos'];
|
||||
$pos = isset($_REQUEST['pos']) ? $_REQUEST['pos']
|
||||
: $_SESSION['tmpval']['pos'];
|
||||
if (isset($_REQUEST['session_max_rows'])) {
|
||||
$rows = $_REQUEST['session_max_rows'];
|
||||
} else {
|
||||
@ -186,11 +189,12 @@ class TableGisVisualizationController extends TableController
|
||||
* Displays the page
|
||||
*/
|
||||
$this->url_params['sql_query'] = $this->sql_query;
|
||||
$downloadUrl = 'tbl_gis_visualization.php' . PMA_URL_getCommon($this->url_params)
|
||||
. '&saveToFile=true';
|
||||
$downloadUrl = 'tbl_gis_visualization.php' . PMA_URL_getCommon(
|
||||
$this->url_params
|
||||
) . '&saveToFile=true';
|
||||
$svgSupport = (PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER <= 8)
|
||||
? false : true;
|
||||
$html = Template::get('gis_visualization/gis_visualization')->render(
|
||||
$html = Template::get('table/gis_visualization/gis_visualization')->render(
|
||||
array(
|
||||
'url_params' => $this->url_params,
|
||||
'downloadUrl' => $downloadUrl,
|
||||
@ -198,7 +202,9 @@ class TableGisVisualizationController extends TableController
|
||||
'spatialCandidates' => $spatialCandidates,
|
||||
'visualizationSettings' => $this->visualizationSettings,
|
||||
'sql_query' => $this->sql_query,
|
||||
'visualization' => $this->visualization->toImage($svgSupport ? 'svg' : 'png'),
|
||||
'visualization' => $this->visualization->toImage(
|
||||
$svgSupport ? 'svg' : 'png'
|
||||
),
|
||||
'svgSupport' => $svgSupport,
|
||||
'drawOl' => $this->visualization->asOl()
|
||||
)
|
||||
|
||||
@ -116,7 +116,7 @@ class TableIndexesController extends TableController
|
||||
$this->response->getHeader()->getScripts()->addFile('indexes.js');
|
||||
|
||||
$this->response->addHTML(
|
||||
Template::get('index_form')->render(
|
||||
Template::get('table/index_form')->render(
|
||||
array(
|
||||
'fields' => $fields,
|
||||
'index' => $this->index,
|
||||
|
||||
@ -156,9 +156,10 @@ class TableRelationController extends TableController
|
||||
}
|
||||
|
||||
// display secondary level tabs if necessary
|
||||
$engine = $this->dbi->getTable($this->db, $this->table)->sGetStatusInfo('ENGINE');
|
||||
$engine = $this->dbi->getTable($this->db, $this->table)
|
||||
->sGetStatusInfo('ENGINE');
|
||||
$this->response->addHTML(
|
||||
Template::get('structure/secondary_tabs')->render(
|
||||
Template::get('table/secondary_tabs')->render(
|
||||
array(
|
||||
'url_params' => array(
|
||||
'db' => $GLOBALS['db'],
|
||||
@ -180,7 +181,7 @@ class TableRelationController extends TableController
|
||||
|
||||
// common form
|
||||
$this->response->addHTML(
|
||||
Template::get('tbl_relation/common_form')->render(
|
||||
Template::get('table/relation/common_form')->render(
|
||||
array(
|
||||
'db' => $this->db,
|
||||
'table' => $this->table,
|
||||
@ -274,8 +275,12 @@ class TableRelationController extends TableController
|
||||
: null;
|
||||
|
||||
if ($this->upd_query->updateInternalRelations(
|
||||
$multi_edit_columns_name, $_POST['destination_db'], $_POST['destination_table'],
|
||||
$_POST['destination_column'], $this->cfgRelation, isset($this->existrel) ? $this->existrel : null
|
||||
$multi_edit_columns_name,
|
||||
$_POST['destination_db'],
|
||||
$_POST['destination_table'],
|
||||
$_POST['destination_column'],
|
||||
$this->cfgRelation,
|
||||
isset($this->existrel) ? $this->existrel : null
|
||||
)
|
||||
) {
|
||||
$this->response->addHTML(
|
||||
@ -297,8 +302,9 @@ class TableRelationController extends TableController
|
||||
{
|
||||
$foreignTable = $_REQUEST['foreignTable'];
|
||||
$table_obj = new PMA_Table($foreignTable, $_REQUEST['foreignDb']);
|
||||
// Since views do not have keys defined on them provide the full list of columns
|
||||
if ($GLOBALS['dbi']->getTable($_REQUEST['foreignDb'], $foreignTable)->isView()) {
|
||||
// Since views do not have keys defined on them provide the full list of
|
||||
// columns
|
||||
if ($table_obj->isView()) {
|
||||
$columnList = $table_obj->getColumns(false, false);
|
||||
} else {
|
||||
$columnList = $table_obj->getIndexedColumns(false, false);
|
||||
|
||||
@ -187,7 +187,7 @@ class TableSearchController extends TableController
|
||||
|
||||
// Show secondary level of tabs
|
||||
$this->response->addHTML(
|
||||
Template::get('table/secondary_tabs')
|
||||
Template::get('secondary_tabs')
|
||||
->render(
|
||||
array(
|
||||
'url_params' => array(
|
||||
@ -214,7 +214,7 @@ class TableSearchController extends TableController
|
||||
$err_url = $goto . '?' . PMA_URL_getCommon($params);
|
||||
// Displays the find and replace form
|
||||
$this->response->addHTML(
|
||||
Template::get('table/selection_form')
|
||||
Template::get('table/search/selection_form')
|
||||
->render(
|
||||
array(
|
||||
'searchType' => $this->_searchType,
|
||||
@ -336,7 +336,7 @@ class TableSearchController extends TableController
|
||||
|
||||
// Displays the zoom search form
|
||||
$this->response->addHTML(
|
||||
Template::get('table/secondary_tabs')
|
||||
Template::get('secondary_tabs')
|
||||
->render(
|
||||
array(
|
||||
'url_params' => array(
|
||||
@ -348,7 +348,7 @@ class TableSearchController extends TableController
|
||||
)
|
||||
);
|
||||
$this->response->addHTML(
|
||||
Template::get('table/selection_form')
|
||||
Template::get('table/search/selection_form')
|
||||
->render(
|
||||
array(
|
||||
'searchType' => $this->_searchType,
|
||||
@ -440,7 +440,7 @@ class TableSearchController extends TableController
|
||||
)
|
||||
);
|
||||
$this->response->addHTML(
|
||||
Template::get('table/zoom_result_form')
|
||||
Template::get('table/search/zoom_result_form')
|
||||
->render(
|
||||
array(
|
||||
'_db' => $this->db,
|
||||
@ -578,7 +578,7 @@ class TableSearchController extends TableController
|
||||
);
|
||||
// Displays the table search form
|
||||
$this->response->addHTML(
|
||||
Template::get('table/secondary_tabs')
|
||||
Template::get('secondary_tabs')
|
||||
->render(
|
||||
array(
|
||||
'url_params' => array(
|
||||
@ -590,7 +590,7 @@ class TableSearchController extends TableController
|
||||
)
|
||||
);
|
||||
$this->response->addHTML(
|
||||
Template::get('table/selection_form')
|
||||
Template::get('table/search/selection_form')
|
||||
->render(
|
||||
array(
|
||||
'searchType' => $this->_searchType,
|
||||
@ -698,7 +698,7 @@ class TableSearchController extends TableController
|
||||
$result = $this->dbi->fetchResult($sql_query, 0);
|
||||
}
|
||||
|
||||
return Template::get('table/replace_preview')->render(
|
||||
return Template::get('table/search/replace_preview')->render(
|
||||
array(
|
||||
'db' => $this->db,
|
||||
'table' => $this->table,
|
||||
@ -920,7 +920,7 @@ class TableSearchController extends TableController
|
||||
$type = $this->_columnTypes[$column_index];
|
||||
$collation = $this->_columnCollations[$column_index];
|
||||
//Gets column's comparison operators depending on column type
|
||||
$func = Template::get('table/column_comparison_operators')->render(
|
||||
$func = Template::get('table/search/column_comparison_operators')->render(
|
||||
array(
|
||||
'search_index' => $search_index,
|
||||
'columnTypes' => $this->_columnTypes,
|
||||
@ -933,7 +933,7 @@ class TableSearchController extends TableController
|
||||
$foreignData = PMA_getForeignData(
|
||||
$this->_foreigners, $this->_columnNames[$column_index], false, '', ''
|
||||
);
|
||||
$value = Template::get('table/input_box')->render(
|
||||
$value = Template::get('table/search/input_box')->render(
|
||||
array(
|
||||
'str' => '',
|
||||
'column_type' => (string) $type,
|
||||
@ -948,7 +948,7 @@ class TableSearchController extends TableController
|
||||
'criteriaValues' => $entered_value,
|
||||
'db' => $this->db,
|
||||
'titles' => $titles,
|
||||
'in_fbs' => false
|
||||
'in_fbs' => true
|
||||
)
|
||||
);
|
||||
return array(
|
||||
@ -976,6 +976,7 @@ class TableSearchController extends TableController
|
||||
// return
|
||||
if (! isset($_POST['criteriaValues'])
|
||||
&& ! isset($_POST['criteriaColumnOperators'])
|
||||
&& ! isset($_POST['geom_func'])
|
||||
) {
|
||||
return '';
|
||||
}
|
||||
@ -988,8 +989,8 @@ class TableSearchController extends TableController
|
||||
)) {
|
||||
|
||||
$unaryFlag = $GLOBALS['PMA_Types']->isUnaryOperator($operator);
|
||||
$tmp_geom_func = isset($geom_func[$column_index])
|
||||
? $geom_func[$column_index] : null;
|
||||
$tmp_geom_func = isset($_POST['geom_func'][$column_index])
|
||||
? $_POST['geom_func'][$column_index] : null;
|
||||
|
||||
$whereClause = $this->_getWhereClause(
|
||||
$_POST['criteriaValues'][$column_index],
|
||||
@ -1074,33 +1075,37 @@ class TableSearchController extends TableController
|
||||
|
||||
// Get details about the geometry functions
|
||||
$geom_funcs = PMA_Util::getGISFunctions($types, true, false);
|
||||
// New output type is the output type of the function being applied
|
||||
$types = $geom_funcs[$geom_func]['type'];
|
||||
|
||||
// If the function takes a single parameter
|
||||
if ($geom_funcs[$geom_func]['params'] == 1) {
|
||||
$backquoted_name = $geom_func . '(' . PMA_Util::backquote($names) . ')';
|
||||
} else {
|
||||
// If the function takes two parameters
|
||||
// If the function takes multiple parameters
|
||||
if ($geom_funcs[$geom_func]['params'] > 1) {
|
||||
// create gis data from the criteria input
|
||||
$gis_data = PMA_Util::createGISData($criteriaValues);
|
||||
$where = $geom_func . '(' . PMA_Util::backquote($names)
|
||||
. ',' . $gis_data . ')';
|
||||
. ', ' . $gis_data . ')';
|
||||
return $where;
|
||||
}
|
||||
|
||||
// New output type is the output type of the function being applied
|
||||
$type = $geom_funcs[$geom_func]['type'];
|
||||
$geom_function_applied = $geom_func
|
||||
. '(' . PMA_Util::backquote($names) . ')';
|
||||
|
||||
// If the where clause is something like 'IsEmpty(`spatial_col_name`)'
|
||||
if (isset($geom_unary_functions[$geom_func])
|
||||
&& trim($criteriaValues) == ''
|
||||
) {
|
||||
$where = $backquoted_name;
|
||||
$where = $geom_function_applied;
|
||||
|
||||
} elseif (in_array($types, PMA_Util::getGISDatatypes())
|
||||
} elseif (in_array($type, PMA_Util::getGISDatatypes())
|
||||
&& ! empty($criteriaValues)
|
||||
) {
|
||||
// create gis data from the criteria input
|
||||
$gis_data = PMA_Util::createGISData($criteriaValues);
|
||||
$where = $backquoted_name . ' ' . $func_type . ' ' . $gis_data;
|
||||
$where = $geom_function_applied . " " . $func_type . " " . $gis_data;
|
||||
|
||||
} elseif (/*overload*/mb_strlen($criteriaValues) > 0) {
|
||||
$where = $geom_function_applied . " "
|
||||
. $func_type . " '" . $criteriaValues . "'";
|
||||
}
|
||||
return $where;
|
||||
}
|
||||
@ -1121,7 +1126,7 @@ class TableSearchController extends TableController
|
||||
$func_type, $unaryFlag, $geom_func = null
|
||||
) {
|
||||
// If geometry function is set
|
||||
if ($geom_func != null && trim($geom_func) != '') {
|
||||
if (! empty($geom_func)) {
|
||||
return $this->_getGeomWhereClause(
|
||||
$criteriaValues, $names, $func_type, $types, $geom_func
|
||||
);
|
||||
|
||||
1253
libraries/controllers/TableStructureController.class.php
Normal file
1253
libraries/controllers/TableStructureController.class.php
Normal file
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,7 @@ require_once './libraries/bookmark.lib.php';
|
||||
PMA_Util::checkParameters(array('db'));
|
||||
|
||||
global $cfg;
|
||||
global $db;
|
||||
|
||||
$is_show_stats = $cfg['ShowStats'];
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ require_once 'libraries/Template.class.php';
|
||||
*/
|
||||
function PMA_getHtmlForPageSelector($cfgRelation, $db)
|
||||
{
|
||||
return PMA\Template::get('designer/page_selector')
|
||||
return PMA\Template::get('database/designer/page_selector')
|
||||
->render(
|
||||
array(
|
||||
'db' => $db,
|
||||
@ -41,7 +41,7 @@ function PMA_getHtmlForPageSelector($cfgRelation, $db)
|
||||
*/
|
||||
function PMA_getHtmlForEditOrDeletePages($db, $operation)
|
||||
{
|
||||
return PMA\Template::get('designer/edit_delete_pages')
|
||||
return PMA\Template::get('database/designer/edit_delete_pages')
|
||||
->render(
|
||||
array(
|
||||
'db' => $db,
|
||||
@ -59,7 +59,7 @@ function PMA_getHtmlForEditOrDeletePages($db, $operation)
|
||||
*/
|
||||
function PMA_getHtmlForPageSaveAs($db)
|
||||
{
|
||||
return PMA\Template::get('designer/page_save_as')
|
||||
return PMA\Template::get('database/designer/page_save_as')
|
||||
->render(
|
||||
array(
|
||||
'db' => $db
|
||||
@ -118,7 +118,7 @@ function PMA_getHtmlForSchemaExport($db, $page)
|
||||
)->getDisplay();
|
||||
}
|
||||
|
||||
return PMA\Template::get('designer/schema_export')
|
||||
return PMA\Template::get('database/designer/schema_export')
|
||||
->render(
|
||||
array(
|
||||
'db' => $db,
|
||||
@ -141,7 +141,7 @@ function PMA_getHtmlForSchemaExport($db, $page)
|
||||
function PMA_getHtmlForJSFields(
|
||||
$script_tables, $script_contr, $script_display_field, $display_page
|
||||
) {
|
||||
return PMA\Template::get('designer/js_fields')
|
||||
return PMA\Template::get('database/designer/js_fields')
|
||||
->render(
|
||||
array(
|
||||
'script_tables' => $script_tables,
|
||||
@ -163,7 +163,7 @@ function PMA_getHtmlForJSFields(
|
||||
*/
|
||||
function PMA_getDesignerPageMenu($visualBuilder, $selected_page, $params_array)
|
||||
{
|
||||
return PMA\Template::get('designer/side_menu')
|
||||
return PMA\Template::get('database/designer/side_menu')
|
||||
->render(
|
||||
array(
|
||||
'visualBuilder' => $visualBuilder,
|
||||
@ -267,7 +267,7 @@ function PMA_returnClassNamesFromMenuButtons()
|
||||
*/
|
||||
function PMA_getHTMLCanvas()
|
||||
{
|
||||
return PMA\Template::get('designer/canvas')->render();
|
||||
return PMA\Template::get('database/designer/canvas')->render();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -280,7 +280,7 @@ function PMA_getHTMLCanvas()
|
||||
*/
|
||||
function PMA_getHTMLTableList($tab_pos, $display_page)
|
||||
{
|
||||
return PMA\Template::get('designer/table_list')
|
||||
return PMA\Template::get('database/designer/table_list')
|
||||
->render(
|
||||
array(
|
||||
'tab_pos' => $tab_pos,
|
||||
@ -303,7 +303,7 @@ function PMA_getHTMLTableList($tab_pos, $display_page)
|
||||
function PMA_getDatabaseTables(
|
||||
$tab_pos, $display_page, $tab_column, $tables_all_keys, $tables_pk_or_unique_keys
|
||||
) {
|
||||
return PMA\Template::get('designer/database_tables')
|
||||
return PMA\Template::get('database/designer/database_tables')
|
||||
->render(
|
||||
array(
|
||||
'tab_pos' => $tab_pos,
|
||||
@ -322,7 +322,7 @@ function PMA_getDatabaseTables(
|
||||
*/
|
||||
function PMA_getNewRelationPanel()
|
||||
{
|
||||
return PMA\Template::get('designer/new_relation_panel')->render();
|
||||
return PMA\Template::get('database/designer/new_relation_panel')->render();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -332,7 +332,7 @@ function PMA_getNewRelationPanel()
|
||||
*/
|
||||
function PMA_getDeleteRelationPanel()
|
||||
{
|
||||
return PMA\Template::get('designer/delete_relation_panel')->render();
|
||||
return PMA\Template::get('database/designer/delete_relation_panel')->render();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -342,7 +342,7 @@ function PMA_getDeleteRelationPanel()
|
||||
*/
|
||||
function PMA_getOptionsPanel()
|
||||
{
|
||||
return PMA\Template::get('designer/options_panel')->render();
|
||||
return PMA\Template::get('database/designer/options_panel')->render();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -352,7 +352,7 @@ function PMA_getOptionsPanel()
|
||||
*/
|
||||
function PMA_getRenameToPanel()
|
||||
{
|
||||
return PMA\Template::get('designer/rename_to_panel')->render();
|
||||
return PMA\Template::get('database/designer/rename_to_panel')->render();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -362,7 +362,7 @@ function PMA_getRenameToPanel()
|
||||
*/
|
||||
function PMA_getHavingQueryPanel()
|
||||
{
|
||||
return PMA\Template::get('designer/having_query_panel')->render();
|
||||
return PMA\Template::get('database/designer/having_query_panel')->render();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -372,7 +372,7 @@ function PMA_getHavingQueryPanel()
|
||||
*/
|
||||
function PMA_getAggregateQueryPanel()
|
||||
{
|
||||
return PMA\Template::get('designer/aggregate_query_panel')->render();
|
||||
return PMA\Template::get('database/designer/aggregate_query_panel')->render();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -382,7 +382,7 @@ function PMA_getAggregateQueryPanel()
|
||||
*/
|
||||
function PMA_getWhereQueryPanel()
|
||||
{
|
||||
return PMA\Template::get('designer/where_query_panel')->render();
|
||||
return PMA\Template::get('database/designer/where_query_panel')->render();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -392,5 +392,5 @@ function PMA_getWhereQueryPanel()
|
||||
*/
|
||||
function PMA_getQueryDetails()
|
||||
{
|
||||
return PMA\Template::get('designer/query_details')->render();
|
||||
return PMA\Template::get('database/designer/query_details')->render();
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ if (! defined('PHPMYADMIN')) {
|
||||
}
|
||||
|
||||
global $cfg;
|
||||
global $db;
|
||||
|
||||
/**
|
||||
* limits for table list
|
||||
|
||||
@ -639,6 +639,10 @@ $GLOBALS['dummy_queries'] = array(
|
||||
array(
|
||||
'query' => "SHOW TABLE STATUS FROM `db` WHERE `Name` LIKE 'table%'",
|
||||
'result' => array()
|
||||
),
|
||||
array(
|
||||
'query' => "SHOW VARIABLES LIKE 'have_partitioning'",
|
||||
'result' => array()
|
||||
)
|
||||
);
|
||||
/**
|
||||
|
||||
@ -43,7 +43,7 @@ require_once 'libraries/Template.class.php';
|
||||
*/
|
||||
function PMA_getHtmlForCreateTable($db)
|
||||
{
|
||||
return PMA\Template::get('table/create_table')->render(
|
||||
return PMA\Template::get('database/create_table')->render(
|
||||
array('db' => $db)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,64 +0,0 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
|
||||
/**
|
||||
* include file for display import : server, database, table
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
require_once './libraries/file_listing.lib.php';
|
||||
require_once './libraries/plugin_interface.lib.php';
|
||||
require_once './libraries/display_import.lib.php';
|
||||
require_once './libraries/display_import_ajax.lib.php';
|
||||
|
||||
/* Scan for plugins */
|
||||
/* @var $import_list ImportPlugin[] */
|
||||
$import_list = PMA_getPlugins(
|
||||
"import",
|
||||
'libraries/plugins/import/',
|
||||
$import_type
|
||||
);
|
||||
|
||||
/* Fail if we didn't find any plugin */
|
||||
if (empty($import_list)) {
|
||||
PMA_Message::error(
|
||||
__(
|
||||
'Could not load import plugins, please check your installation!'
|
||||
)
|
||||
)->display();
|
||||
exit;
|
||||
}
|
||||
|
||||
if (PMA_isValid($_REQUEST['offset'], 'numeric')) {
|
||||
$offset = $_REQUEST['offset'];
|
||||
}
|
||||
if (isset($_REQUEST['timeout_passed'])) {
|
||||
$timeout_passed = $_REQUEST['timeout_passed'];
|
||||
}
|
||||
if (isset($_REQUEST['local_import_file'])) {
|
||||
$local_import_file = $_REQUEST['local_import_file'];
|
||||
}
|
||||
|
||||
$timeout_passed_str = isset($timeout_passed)? $timeout_passed : null;
|
||||
$offset_str = isset($offset)? $offset : null;
|
||||
$html = PMA_getHtmlForImport(
|
||||
$upload_id,
|
||||
$import_type,
|
||||
$db,
|
||||
$table,
|
||||
$max_upload_size,
|
||||
$import_list,
|
||||
$timeout_passed_str,
|
||||
$offset_str
|
||||
);
|
||||
|
||||
$response = PMA_Response::getInstance();
|
||||
$response->addHTML($html);
|
||||
|
||||
@ -210,13 +210,15 @@ function PMA_getHtmlForImportCharset()
|
||||
/**
|
||||
* Prints Html For Display Import options : file property
|
||||
*
|
||||
* @param int $max_upload_size Max upload size
|
||||
* @param ImportPlugin[] $import_list import list
|
||||
* @param int $max_upload_size Max upload size
|
||||
* @param ImportPlugin[] $import_list import list
|
||||
* @param String $local_import_file from upload directory
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function PMA_getHtmlForImportOptionsFile($max_upload_size, $import_list)
|
||||
{
|
||||
function PMA_getHtmlForImportOptionsFile(
|
||||
$max_upload_size, $import_list, $local_import_file
|
||||
) {
|
||||
global $cfg;
|
||||
$html = ' <div class="importoptions">';
|
||||
$html .= ' <h3>' . __('File to Import:') . '</h3>';
|
||||
@ -235,7 +237,7 @@ function PMA_getHtmlForImportOptionsFile($max_upload_size, $import_list)
|
||||
$html .= ' <input type="radio" name="file_location" '
|
||||
. 'id="radio_local_import_file"';
|
||||
if (! empty($GLOBALS['timeout_passed'])
|
||||
&& ! empty($GLOBALS['local_import_file'])
|
||||
&& ! empty($local_import_file)
|
||||
) {
|
||||
$html .= ' checked="checked"';
|
||||
}
|
||||
@ -398,20 +400,21 @@ function PMA_getHtmlForImportOptionsSubmit()
|
||||
/**
|
||||
* Prints Html For Display Import
|
||||
*
|
||||
* @param int $upload_id The selected upload id
|
||||
* @param String $import_type Import type: server, database, table
|
||||
* @param String $db Selected DB
|
||||
* @param String $table Selected Table
|
||||
* @param int $max_upload_size Max upload size
|
||||
* @param ImportPlugin[] $import_list Import list
|
||||
* @param String $timeout_passed Timeout passed
|
||||
* @param String $offset Timeout offset
|
||||
* @param int $upload_id The selected upload id
|
||||
* @param String $import_type Import type: server, database, table
|
||||
* @param String $db Selected DB
|
||||
* @param String $table Selected Table
|
||||
* @param int $max_upload_size Max upload size
|
||||
* @param ImportPlugin[] $import_list Import list
|
||||
* @param String $timeout_passed Timeout passed
|
||||
* @param String $offset Timeout offset
|
||||
* @param String $local_import_file from upload directory
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function PMA_getHtmlForImport(
|
||||
$upload_id, $import_type, $db, $table,
|
||||
$max_upload_size, $import_list, $timeout_passed, $offset
|
||||
$max_upload_size, $import_list, $timeout_passed, $offset, $local_import_file
|
||||
) {
|
||||
global $SESSION_KEY;
|
||||
$html = '';
|
||||
@ -440,7 +443,9 @@ function PMA_getHtmlForImport(
|
||||
|
||||
$html .= PMA_getHtmlForImportOptions($import_type, $db, $table);
|
||||
|
||||
$html .= PMA_getHtmlForImportOptionsFile($max_upload_size, $import_list);
|
||||
$html .= PMA_getHtmlForImportOptionsFile(
|
||||
$max_upload_size, $import_list, $local_import_file
|
||||
);
|
||||
|
||||
$html .= PMA_getHtmlForImportOptionsPartialImport($timeout_passed, $offset);
|
||||
|
||||
@ -618,3 +623,65 @@ function PMA_getHtmlForImportWithPlugin($upload_id)
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets HTML to display import dialogs
|
||||
*
|
||||
* @param String $import_type Import type: server|database|table
|
||||
* @param String $db Selected DB
|
||||
* @param String $table Selected Table
|
||||
* @param int $max_upload_size Max upload size
|
||||
*
|
||||
* @return string $html
|
||||
*/
|
||||
function PMA_getImportDisplay($import_type, $db, $table, $max_upload_size)
|
||||
{
|
||||
global $SESSION_KEY;
|
||||
include_once './libraries/file_listing.lib.php';
|
||||
include_once './libraries/plugin_interface.lib.php';
|
||||
// this one generates also some globals
|
||||
include_once './libraries/display_import_ajax.lib.php';
|
||||
|
||||
/* Scan for plugins */
|
||||
/* @var $import_list ImportPlugin[] */
|
||||
$import_list = PMA_getPlugins(
|
||||
"import",
|
||||
'libraries/plugins/import/',
|
||||
$import_type
|
||||
);
|
||||
|
||||
/* Fail if we didn't find any plugin */
|
||||
if (empty($import_list)) {
|
||||
PMA_Message::error(
|
||||
__(
|
||||
'Could not load import plugins, please check your installation!'
|
||||
)
|
||||
)->display();
|
||||
exit;
|
||||
}
|
||||
|
||||
if (PMA_isValid($_REQUEST['offset'], 'numeric')) {
|
||||
$offset = $_REQUEST['offset'];
|
||||
}
|
||||
if (isset($_REQUEST['timeout_passed'])) {
|
||||
$timeout_passed = $_REQUEST['timeout_passed'];
|
||||
}
|
||||
|
||||
$local_import_file = '';
|
||||
if (isset($_REQUEST['local_import_file'])) {
|
||||
$local_import_file = $_REQUEST['local_import_file'];
|
||||
}
|
||||
|
||||
$timeout_passed_str = isset($timeout_passed)? $timeout_passed : null;
|
||||
$offset_str = isset($offset)? $offset : null;
|
||||
return PMA_getHtmlForImport(
|
||||
$upload_id,
|
||||
$import_type,
|
||||
$db,
|
||||
$table,
|
||||
$max_upload_size,
|
||||
$import_list,
|
||||
$timeout_passed_str,
|
||||
$offset_str,
|
||||
$local_import_file
|
||||
);
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ if (is_readable('js/line_counts.php')) {
|
||||
/**
|
||||
* the url where to submit reports to
|
||||
*/
|
||||
define('SUBMISSION_URL', "http://reports.phpmyadmin.net/incidents/create");
|
||||
define('SUBMISSION_URL', "https://reports.phpmyadmin.net/incidents/create");
|
||||
|
||||
/**
|
||||
* returns the pretty printed error report data collected from the
|
||||
|
||||
@ -740,6 +740,10 @@ function PMA_exportDatabase(
|
||||
|
||||
}
|
||||
|
||||
if (! $export_plugin->exportDBFooter($db)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// export metadata related to this db
|
||||
if (isset($GLOBALS['sql_metadata'])) {
|
||||
// Types of metadata to export.
|
||||
@ -752,9 +756,6 @@ function PMA_exportDatabase(
|
||||
}
|
||||
}
|
||||
|
||||
if (! $export_plugin->exportDBFooter($db)) {
|
||||
return;
|
||||
}
|
||||
if ($separate_files == 'database') {
|
||||
PMA_saveObjectInBuffer('extra');
|
||||
}
|
||||
@ -849,10 +850,9 @@ function PMA_exportTable(
|
||||
// If this is an export of a single view, we have to export data;
|
||||
// for example, a PDF report
|
||||
// if it is a merge table, no data is exported
|
||||
$table = new PMA_Table($table, $db);
|
||||
if (($whatStrucOrData == 'data'
|
||||
|| $whatStrucOrData == 'structure_and_data')
|
||||
&& ! $table->isMerge()
|
||||
&& ! $GLOBALS['dbi']->getTable($db, $table)->isMerge()
|
||||
) {
|
||||
if (! empty($sql_query)) {
|
||||
// only preg_replace if needed
|
||||
|
||||
@ -104,9 +104,7 @@ function PMA_importRunQuery($sql = '', $full = '', $controluser = false,
|
||||
// USE query changes the database, son need to track
|
||||
// while running multiple queries
|
||||
$is_use_query
|
||||
= (/*overload*/mb_stripos($import_run_buffer['sql'], "use ") !== false)
|
||||
? true
|
||||
: false;
|
||||
= /*overload*/mb_stripos($import_run_buffer['sql'], "use ") !== false;
|
||||
|
||||
$max_sql_len = max(
|
||||
$max_sql_len,
|
||||
|
||||
@ -814,8 +814,6 @@ function PMA_getPmaTypeEnum($column, $backup_field, $column_name_appendix,
|
||||
$column_enum_values = $column['values'];
|
||||
$html_output .= '<input type="hidden" name="fields_type'
|
||||
. $column_name_appendix . '" value="enum" />';
|
||||
$html_output .= '<input type="hidden" name="fields'
|
||||
. $column_name_appendix . '" value="" />';
|
||||
$html_output .= "\n" . ' ' . $backup_field . "\n";
|
||||
if (/*overload*/mb_strlen($column['Type']) > 20) {
|
||||
$html_output .= PMA_getDropDownDependingOnLength(
|
||||
|
||||
@ -87,7 +87,7 @@ if (! empty($submit_mult)
|
||||
exit;
|
||||
break;
|
||||
case 'show_create':
|
||||
$show_create = PMA\Template::get('structure/show_create')->render(
|
||||
$show_create = PMA\Template::get('database/structure/show_create')->render(
|
||||
array(
|
||||
'db' => $GLOBALS['db'],
|
||||
'db_objects' => $selected
|
||||
|
||||
@ -78,7 +78,7 @@ class PMA_NavigationHeader
|
||||
{
|
||||
// display Logo, depending on $GLOBALS['cfg']['NavigationDisplayLogo']
|
||||
if (!$GLOBALS['cfg']['NavigationDisplayLogo']) {
|
||||
return Template::get('logo')
|
||||
return Template::get('navigation/logo')
|
||||
->render(array('displayLogo' => false));
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ class PMA_NavigationHeader
|
||||
}
|
||||
|
||||
if (!$GLOBALS['cfg']['NavigationLogoLink']) {
|
||||
return Template::get('logo')
|
||||
return Template::get('navigation/logo')
|
||||
->render(
|
||||
array(
|
||||
'displayLogo' => true,
|
||||
@ -130,7 +130,7 @@ class PMA_NavigationHeader
|
||||
}
|
||||
}
|
||||
|
||||
return Template::get('logo')
|
||||
return Template::get('navigation/logo')
|
||||
->render(
|
||||
array(
|
||||
'displayLogo' => true,
|
||||
|
||||
@ -382,6 +382,9 @@ class Node_Database extends Node
|
||||
{
|
||||
$db = $this->real_name;
|
||||
$cfgRelation = PMA_getRelationsParam();
|
||||
if (empty($cfgRelation['navigationhiding'])) {
|
||||
return array();
|
||||
}
|
||||
$navTable = PMA_Util::backquote($cfgRelation['db'])
|
||||
. "." . PMA_Util::backquote($cfgRelation['navigationhiding']);
|
||||
$sqlQuery = "SELECT `item_name` FROM " . $navTable
|
||||
|
||||
@ -467,8 +467,7 @@ function PMA_copyTables($tables_full, $move, $db)
|
||||
|
||||
// do not copy the data from a Merge table
|
||||
// note: on the calling FORM, 'data' means 'structure and data'
|
||||
$table = new PMA_Table($each_table, $db);
|
||||
if ($table->isMerge()) {
|
||||
if ($GLOBALS['dbi']->getTable($db, $each_table)->isMerge()) {
|
||||
if ($this_what == 'data') {
|
||||
$this_what = 'structure';
|
||||
}
|
||||
|
||||
@ -5,23 +5,27 @@
|
||||
*
|
||||
* Uses mcrypt, if available/possible, and an internal implementation, otherwise.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
* PHP version 5
|
||||
*
|
||||
* If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
|
||||
* {@link Crypt_AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
|
||||
* it'll be null-padded to 192-bits and 192 bits will be the key length until {@link Crypt_AES::setKey() setKey()}
|
||||
* NOTE: Since AES.php is (for compatibility and phpseclib-historical reasons) virtually
|
||||
* just a wrapper to Rijndael.php you may consider using Rijndael.php instead of
|
||||
* to save one include_once().
|
||||
*
|
||||
* If {@link \phpseclib\Crypt\AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
|
||||
* {@link \phpseclib\Crypt\AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
|
||||
* it'll be null-padded to 192-bits and 192 bits will be the key length until {@link \phpseclib\Crypt\AES::setKey() setKey()}
|
||||
* is called, again, at which point, it'll be recalculated.
|
||||
*
|
||||
* Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
|
||||
* make a whole lot of sense. {@link Crypt_AES::setBlockLength() setBlockLength()}, for instance. Calling that function,
|
||||
* Since \phpseclib\Crypt\AES extends \phpseclib\Crypt\Rijndael, some functions are available to be called that, in the context of AES, don't
|
||||
* make a whole lot of sense. {@link \phpseclib\Crypt\AES::setBlockLength() setBlockLength()}, for instance. Calling that function,
|
||||
* however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
|
||||
*
|
||||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include 'Crypt/AES.php';
|
||||
* include 'vendor/autoload.php';
|
||||
*
|
||||
* $aes = new Crypt_AES();
|
||||
* $aes = new \phpseclib\Crypt\AES();
|
||||
*
|
||||
* $aes->setKey('abcdefghijklmnop');
|
||||
*
|
||||
@ -35,145 +39,33 @@
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @category Crypt
|
||||
* @package Crypt_AES
|
||||
* @package AES
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVIII Jim Wigginton
|
||||
* @copyright 2008 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
/**
|
||||
* Include Crypt_Rijndael
|
||||
*/
|
||||
if (!class_exists('Crypt_Rijndael')) {
|
||||
include_once 'Rijndael.php';
|
||||
}
|
||||
namespace phpseclib\Crypt;
|
||||
|
||||
/**#@+
|
||||
* @access public
|
||||
* @see Crypt_AES::encrypt()
|
||||
* @see Crypt_AES::decrypt()
|
||||
*/
|
||||
/**
|
||||
* Encrypt / decrypt using the Counter mode.
|
||||
*
|
||||
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
|
||||
*/
|
||||
define('CRYPT_AES_MODE_CTR', CRYPT_MODE_CTR);
|
||||
/**
|
||||
* Encrypt / decrypt using the Electronic Code Book mode.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
|
||||
*/
|
||||
define('CRYPT_AES_MODE_ECB', CRYPT_MODE_ECB);
|
||||
/**
|
||||
* Encrypt / decrypt using the Code Book Chaining mode.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
|
||||
*/
|
||||
define('CRYPT_AES_MODE_CBC', CRYPT_MODE_CBC);
|
||||
/**
|
||||
* Encrypt / decrypt using the Cipher Feedback mode.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
|
||||
*/
|
||||
define('CRYPT_AES_MODE_CFB', CRYPT_MODE_CFB);
|
||||
/**
|
||||
* Encrypt / decrypt using the Cipher Feedback mode.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
|
||||
*/
|
||||
define('CRYPT_AES_MODE_OFB', CRYPT_MODE_OFB);
|
||||
/**#@-*/
|
||||
|
||||
/**#@+
|
||||
* @access private
|
||||
* @see Crypt_AES::Crypt_AES()
|
||||
*/
|
||||
/**
|
||||
* Toggles the internal implementation
|
||||
*/
|
||||
define('CRYPT_AES_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
|
||||
/**
|
||||
* Toggles the mcrypt implementation
|
||||
*/
|
||||
define('CRYPT_AES_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
|
||||
/**#@-*/
|
||||
use phpseclib\Crypt\Rijndael;
|
||||
|
||||
/**
|
||||
* Pure-PHP implementation of AES.
|
||||
*
|
||||
* @package Crypt_AES
|
||||
* @package AES
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @access public
|
||||
*/
|
||||
class Crypt_AES extends Crypt_Rijndael
|
||||
class AES extends Rijndael
|
||||
{
|
||||
/**
|
||||
* The namespace used by the cipher for its constants.
|
||||
*
|
||||
* @see Crypt_Base::const_namespace
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $const_namespace = 'AES';
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* Determines whether or not the mcrypt extension should be used.
|
||||
*
|
||||
* $mode could be:
|
||||
*
|
||||
* - CRYPT_AES_MODE_ECB
|
||||
*
|
||||
* - CRYPT_AES_MODE_CBC
|
||||
*
|
||||
* - CRYPT_AES_MODE_CTR
|
||||
*
|
||||
* - CRYPT_AES_MODE_CFB
|
||||
*
|
||||
* - CRYPT_AES_MODE_OFB
|
||||
*
|
||||
* If not explicitly set, CRYPT_AES_MODE_CBC will be used.
|
||||
*
|
||||
* @see Crypt_Rijndael::Crypt_Rijndael()
|
||||
* @see Crypt_Base::Crypt_Base()
|
||||
* @param optional Integer $mode
|
||||
* @access public
|
||||
*/
|
||||
function Crypt_AES($mode = CRYPT_AES_MODE_CBC)
|
||||
{
|
||||
parent::Crypt_Rijndael($mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy function
|
||||
*
|
||||
* Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything.
|
||||
* Since \phpseclib\Crypt\AES extends \phpseclib\Crypt\Rijndael, this function is, technically, available, but it doesn't do anything.
|
||||
*
|
||||
* @see Crypt_Rijndael::setBlockLength()
|
||||
* @see \phpseclib\Crypt\Rijndael::setBlockLength()
|
||||
* @access public
|
||||
* @param Integer $length
|
||||
*/
|
||||
@ -181,4 +73,56 @@ class Crypt_AES extends Crypt_Rijndael
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key length
|
||||
*
|
||||
* Valid key lengths are 128, 192, and 256. If the length is less than 128, it will be rounded up to
|
||||
* 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
|
||||
*
|
||||
* @see \phpseclib\Crypt\Rijndael:setKeyLength()
|
||||
* @access public
|
||||
* @param Integer $length
|
||||
*/
|
||||
function setKeyLength($length)
|
||||
{
|
||||
switch ($length) {
|
||||
case 160:
|
||||
$length = 192;
|
||||
break;
|
||||
case 224:
|
||||
$length = 256;
|
||||
}
|
||||
parent::setKeyLength($length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key.
|
||||
*
|
||||
* Rijndael supports five different key lengths, AES only supports three.
|
||||
*
|
||||
* @see \phpseclib\Crypt\Rijndael:setKey()
|
||||
* @see setKeyLength()
|
||||
* @access public
|
||||
* @param String $key
|
||||
*/
|
||||
function setKey($key)
|
||||
{
|
||||
parent::setKey($key);
|
||||
|
||||
if (!$this->explicit_key_length) {
|
||||
$length = strlen($key);
|
||||
switch (true) {
|
||||
case $length <= 16:
|
||||
$this->key_size = 16;
|
||||
break;
|
||||
case $length <= 24:
|
||||
$this->key_size = 24;
|
||||
break;
|
||||
default:
|
||||
$this->key_size = 32;
|
||||
}
|
||||
$this->_setEngine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,54 +3,44 @@
|
||||
/**
|
||||
* Random Number Generator
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
* PHP version 5
|
||||
*
|
||||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include 'Crypt/Random.php';
|
||||
* include 'vendor/autoload.php';
|
||||
*
|
||||
* echo bin2hex(crypt_random_string(8));
|
||||
* echo bin2hex(\phpseclib\Crypt\Random::string(8));
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @category Crypt
|
||||
* @package Crypt_Random
|
||||
* @package Random
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright MMVII Jim Wigginton
|
||||
* @copyright 2007 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
// laravel is a PHP framework that utilizes phpseclib. laravel workbenches may, independently,
|
||||
// have phpseclib as a requirement as well. if you're developing such a program you may encounter
|
||||
// a "Cannot redeclare crypt_random_string()" error.
|
||||
if (!function_exists('crypt_random_string')) {
|
||||
/**
|
||||
* "Is Windows" test
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
|
||||
namespace phpseclib\Crypt;
|
||||
|
||||
use phpseclib\Crypt\AES;
|
||||
use phpseclib\Crypt\Base;
|
||||
use phpseclib\Crypt\Blowfish;
|
||||
use phpseclib\Crypt\DES;
|
||||
use phpseclib\Crypt\RC4;
|
||||
use phpseclib\Crypt\TripleDES;
|
||||
use phpseclib\Crypt\Twofish;
|
||||
|
||||
/**
|
||||
* Pure-PHP Random Number Generator
|
||||
*
|
||||
* @package Random
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @access public
|
||||
*/
|
||||
class Random
|
||||
{
|
||||
/**
|
||||
* Generate a random string.
|
||||
*
|
||||
@ -60,11 +50,10 @@ if (!function_exists('crypt_random_string')) {
|
||||
*
|
||||
* @param Integer $length
|
||||
* @return String
|
||||
* @access public
|
||||
*/
|
||||
function crypt_random_string($length)
|
||||
public static function string($length)
|
||||
{
|
||||
if (CRYPT_RANDOM_IS_WINDOWS) {
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
|
||||
// method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call.
|
||||
// ie. class_alias is a function that was introduced in PHP 5.3
|
||||
if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) {
|
||||
@ -120,7 +109,7 @@ if (!function_exists('crypt_random_string')) {
|
||||
// easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but
|
||||
// PHP isn't low level to be able to use those as sources and on a web server there's not likely
|
||||
// going to be a ton of keyboard or mouse action. web servers do have one thing that we can use
|
||||
// however. a ton of people visiting the website. obviously you don't want to base your seeding
|
||||
// however, a ton of people visiting the website. obviously you don't want to base your seeding
|
||||
// soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled
|
||||
// by the user and (2) this isn't just looking at the data sent by the current user - it's based
|
||||
// on the data sent by all users. one user requests the page and a hash of their info is saved.
|
||||
@ -168,9 +157,9 @@ if (!function_exists('crypt_random_string')) {
|
||||
ini_set('session.use_cookies', $old_use_cookies);
|
||||
session_cache_limiter($old_session_cache_limiter);
|
||||
} else {
|
||||
if ($_OLD_SESSION !== false) {
|
||||
$_SESSION = $_OLD_SESSION;
|
||||
unset($_OLD_SESSION);
|
||||
if ($_OLD_SESSION !== false) {
|
||||
$_SESSION = $_OLD_SESSION;
|
||||
unset($_OLD_SESSION);
|
||||
} else {
|
||||
unset($_SESSION);
|
||||
}
|
||||
@ -191,21 +180,27 @@ if (!function_exists('crypt_random_string')) {
|
||||
//
|
||||
// http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
|
||||
switch (true) {
|
||||
case class_exists('Crypt_AES'):
|
||||
$crypto = new Crypt_AES(CRYPT_AES_MODE_CTR);
|
||||
case class_exists('\phpseclib\Crypt\AES'):
|
||||
$crypto = new AES(Base::MODE_CTR);
|
||||
break;
|
||||
case class_exists('Crypt_TripleDES'):
|
||||
$crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
|
||||
case class_exists('\phpseclib\Crypt\Twofish'):
|
||||
$crypto = new Twofish(Base::MODE_CTR);
|
||||
break;
|
||||
case class_exists('Crypt_DES'):
|
||||
$crypto = new Crypt_DES(CRYPT_DES_MODE_CTR);
|
||||
case class_exists('\phpseclib\Crypt\Blowfish'):
|
||||
$crypto = new Blowfish(Base::MODE_CTR);
|
||||
break;
|
||||
case class_exists('Crypt_RC4'):
|
||||
$crypto = new Crypt_RC4();
|
||||
case class_exists('\phpseclib\Crypt\TripleDES'):
|
||||
$crypto = new TripleDES(Base::MODE_CTR);
|
||||
break;
|
||||
case class_exists('\phpseclib\Crypt\DES'):
|
||||
$crypto = new DES(Base::MODE_CTR);
|
||||
break;
|
||||
case class_exists('\phpseclib\Crypt\RC4'):
|
||||
$crypto = new RC4();
|
||||
break;
|
||||
default:
|
||||
$crypto = $seed;
|
||||
return crypt_random_string($length);
|
||||
user_error(__CLASS__ . ' requires at least one symmetric cipher be loaded');
|
||||
return false;
|
||||
}
|
||||
|
||||
$crypto->setKey($key);
|
||||
@ -213,37 +208,21 @@ if (!function_exists('crypt_random_string')) {
|
||||
$crypto->enableContinuousBuffer();
|
||||
}
|
||||
|
||||
if (is_string($crypto)) {
|
||||
// the following is based off of ANSI X9.31:
|
||||
//
|
||||
// http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
|
||||
//
|
||||
// OpenSSL uses that same standard for it's random numbers:
|
||||
//
|
||||
// http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
|
||||
// (do a search for "ANS X9.31 A.2.4")
|
||||
//
|
||||
// ANSI X9.31 recommends ciphers be used and phpseclib does use them if they're available (see
|
||||
// later on in the code) but if they're not we'll use sha1
|
||||
$result = '';
|
||||
while (strlen($result) < $length) { // each loop adds 20 bytes
|
||||
// microtime() isn't packed as "densely" as it could be but then neither is that the idea.
|
||||
// the idea is simply to ensure that each "block" has a unique element to it.
|
||||
$i = pack('H*', sha1(microtime()));
|
||||
$r = pack('H*', sha1($i ^ $v));
|
||||
$v = pack('H*', sha1($r ^ $i));
|
||||
$result.= $r;
|
||||
}
|
||||
return substr($result, 0, $length);
|
||||
}
|
||||
|
||||
//return $crypto->encrypt(str_repeat("\0", $length));
|
||||
|
||||
// the following is based off of ANSI X9.31:
|
||||
//
|
||||
// http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
|
||||
//
|
||||
// OpenSSL uses that same standard for it's random numbers:
|
||||
//
|
||||
// http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
|
||||
// (do a search for "ANS X9.31 A.2.4")
|
||||
$result = '';
|
||||
while (strlen($result) < $length) {
|
||||
$i = $crypto->encrypt(microtime());
|
||||
$r = $crypto->encrypt($i ^ $v);
|
||||
$v = $crypto->encrypt($r ^ $i);
|
||||
$i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21
|
||||
$r = $crypto->encrypt($i ^ $v); // strlen($v) == 20
|
||||
$v = $crypto->encrypt($r ^ $i); // strlen($r) == 20
|
||||
$result.= $r;
|
||||
}
|
||||
return substr($result, 0, $length);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
21
libraries/phpseclib/LICENSE
Normal file
21
libraries/phpseclib/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
Copyright 2007-2013 TerraFrost and other contributors
|
||||
http://phpseclib.sourceforge.net/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -10,6 +10,8 @@ if (! defined('PHPMYADMIN')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
use phpseclib\Crypt;
|
||||
|
||||
/* Get the authentication interface */
|
||||
require_once 'libraries/plugins/AuthenticationPlugin.class.php';
|
||||
|
||||
@ -36,8 +38,10 @@ if (! function_exists('openssl_encrypt')
|
||||
|| ! function_exists('openssl_random_pseudo_bytes')
|
||||
|| PHP_VERSION_ID < 50304
|
||||
) {
|
||||
include PHPSECLIB_INC_DIR . '/Crypt/AES.php';
|
||||
include PHPSECLIB_INC_DIR . '/Crypt/Random.php';
|
||||
require PHPSECLIB_INC_DIR . '/Crypt/Base.php';
|
||||
require PHPSECLIB_INC_DIR . '/Crypt/Rijndael.php';
|
||||
require PHPSECLIB_INC_DIR . '/Crypt/AES.php';
|
||||
require PHPSECLIB_INC_DIR . '/Crypt/Random.php';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -370,19 +374,19 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
) {
|
||||
if (! empty($_POST["g-recaptcha-response"])) {
|
||||
|
||||
include_once 'libraries/plugins/auth/recaptcha/recaptchalib.php';
|
||||
$reCaptcha = new ReCaptcha(
|
||||
include_once 'libraries/plugins/auth/recaptcha/autoload.php';
|
||||
$reCaptcha = new \ReCaptcha\ReCaptcha(
|
||||
$GLOBALS['cfg']['CaptchaLoginPrivateKey']
|
||||
);
|
||||
|
||||
// verify captcha status.
|
||||
$resp = $reCaptcha->verifyResponse(
|
||||
$_SERVER["REMOTE_ADDR"],
|
||||
$_POST["g-recaptcha-response"]
|
||||
$resp = $reCaptcha->verify(
|
||||
$_POST["g-recaptcha-response"],
|
||||
$_SERVER["REMOTE_ADDR"]
|
||||
);
|
||||
|
||||
// Check if the captcha entered is valid, if not stop the login.
|
||||
if ($resp == null || ! $resp->success) {
|
||||
if ($resp == null || ! $resp->isSuccess()) {
|
||||
$conn_error = __('Entered captcha is wrong, try again!');
|
||||
$_SESSION['last_valid_captcha'] = false;
|
||||
return false;
|
||||
@ -721,10 +725,10 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
private function _getSessionEncryptionSecret()
|
||||
{
|
||||
if (empty($_SESSION['encryption_key'])) {
|
||||
if ($this->_useOpenSSL()) {
|
||||
if (self::useOpenSSL()) {
|
||||
$_SESSION['encryption_key'] = openssl_random_pseudo_bytes(256);
|
||||
} else {
|
||||
$_SESSION['encryption_key'] = crypt_random_string(256);
|
||||
$_SESSION['encryption_key'] = Crypt\Random::string(256);
|
||||
}
|
||||
}
|
||||
return $_SESSION['encryption_key'];
|
||||
@ -735,7 +739,7 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function _useOpenSSL()
|
||||
public static function useOpenSSL()
|
||||
{
|
||||
return (
|
||||
function_exists('openssl_encrypt')
|
||||
@ -756,7 +760,7 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
*/
|
||||
public function cookieEncrypt($data, $secret)
|
||||
{
|
||||
if ($this->_useOpenSSL()) {
|
||||
if (self::useOpenSSL()) {
|
||||
return openssl_encrypt(
|
||||
$data,
|
||||
'AES-128-CBC',
|
||||
@ -765,7 +769,7 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
$this->_cookie_iv
|
||||
);
|
||||
} else {
|
||||
$cipher = new Crypt_AES(CRYPT_AES_MODE_CBC);
|
||||
$cipher = new Crypt\AES(Crypt\Base::MODE_CBC);
|
||||
$cipher->setIV($this->_cookie_iv);
|
||||
$cipher->setKey($secret);
|
||||
return base64_encode($cipher->encrypt($data));
|
||||
@ -790,7 +794,7 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
$this->createIV();
|
||||
}
|
||||
|
||||
if ($this->_useOpenSSL()) {
|
||||
if (self::useOpenSSL()) {
|
||||
return openssl_decrypt(
|
||||
$encdata,
|
||||
'AES-128-CBC',
|
||||
@ -799,7 +803,7 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
$this->_cookie_iv
|
||||
);
|
||||
} else {
|
||||
$cipher = new Crypt_AES(CRYPT_AES_MODE_CBC);
|
||||
$cipher = new Crypt\AES(Crypt\Base::MODE_CBC);
|
||||
$cipher->setIV($this->_cookie_iv);
|
||||
$cipher->setKey($secret);
|
||||
return $cipher->decrypt(base64_decode($encdata));
|
||||
@ -813,10 +817,10 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
*/
|
||||
public function getIVSize()
|
||||
{
|
||||
if ($this->_useOpenSSL()) {
|
||||
if (self::useOpenSSL()) {
|
||||
return openssl_cipher_iv_length('AES-128-CBC');
|
||||
}
|
||||
$cipher = new Crypt_AES(CRYPT_AES_MODE_CBC);
|
||||
$cipher = new Crypt\AES(Crypt\Base::MODE_CBC);
|
||||
return $cipher->block_size;
|
||||
}
|
||||
|
||||
@ -830,12 +834,12 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
*/
|
||||
public function createIV()
|
||||
{
|
||||
if ($this->_useOpenSSL()) {
|
||||
if (self::useOpenSSL()) {
|
||||
$this->_cookie_iv = openssl_random_pseudo_bytes(
|
||||
$this->getIVSize()
|
||||
);
|
||||
} else {
|
||||
$this->_cookie_iv = crypt_random_string(
|
||||
$this->_cookie_iv = Crypt\Random::string(
|
||||
$this->getIVSize()
|
||||
);
|
||||
}
|
||||
@ -869,3 +873,11 @@ class AuthenticationCookie extends AuthenticationPlugin
|
||||
$this->storePasswordCookie($password);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* phpseclib
|
||||
*/
|
||||
if (! AuthenticationCookie::useOpenSSL()) {
|
||||
include PHPSECLIB_INC_DIR . '/Crypt/AES.php';
|
||||
include PHPSECLIB_INC_DIR . '/Crypt/Random.php';
|
||||
}
|
||||
|
||||
97
libraries/plugins/auth/recaptcha/ReCaptcha/ReCaptcha.php
Normal file
97
libraries/plugins/auth/recaptcha/ReCaptcha/ReCaptcha.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/**
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
*
|
||||
* @copyright Copyright (c) 2015, Google Inc.
|
||||
* @link http://www.google.com/recaptcha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace ReCaptcha;
|
||||
|
||||
/**
|
||||
* reCAPTCHA client.
|
||||
*/
|
||||
class ReCaptcha
|
||||
{
|
||||
/**
|
||||
* Version of this client library.
|
||||
* @const string
|
||||
*/
|
||||
const VERSION = 'php_1.1.0';
|
||||
|
||||
/**
|
||||
* Shared secret for the site.
|
||||
* @var type string
|
||||
*/
|
||||
private $secret;
|
||||
|
||||
/**
|
||||
* Method used to communicate with service. Defaults to POST request.
|
||||
* @var RequestMethod
|
||||
*/
|
||||
private $requestMethod;
|
||||
|
||||
/**
|
||||
* Create a configured instance to use the reCAPTCHA service.
|
||||
*
|
||||
* @param string $secret shared secret between site and reCAPTCHA server.
|
||||
* @param RequestMethod $requestMethod method used to send the request. Defaults to POST.
|
||||
*/
|
||||
public function __construct($secret, RequestMethod $requestMethod = null)
|
||||
{
|
||||
if (empty($secret)) {
|
||||
throw new \RuntimeException('No secret provided');
|
||||
}
|
||||
|
||||
if (!is_string($secret)) {
|
||||
throw new \RuntimeException('The provided secret must be a string');
|
||||
}
|
||||
|
||||
$this->secret = $secret;
|
||||
|
||||
if (!is_null($requestMethod)) {
|
||||
$this->requestMethod = $requestMethod;
|
||||
} else {
|
||||
$this->requestMethod = new RequestMethod\Post();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the reCAPTCHA siteverify API to verify whether the user passes
|
||||
* CAPTCHA test.
|
||||
*
|
||||
* @param string $response The value of 'g-recaptcha-response' in the submitted form.
|
||||
* @param string $remoteIp The end user's IP address.
|
||||
* @return Response Response from the service.
|
||||
*/
|
||||
public function verify($response, $remoteIp = null)
|
||||
{
|
||||
// Discard empty solution submissions
|
||||
if (empty($response)) {
|
||||
$recaptchaResponse = new Response(false, array('missing-input-response'));
|
||||
return $recaptchaResponse;
|
||||
}
|
||||
|
||||
$params = new RequestParameters($this->secret, $response, $remoteIp, self::VERSION);
|
||||
$rawResponse = $this->requestMethod->submit($params);
|
||||
return Response::fromJson($rawResponse);
|
||||
}
|
||||
}
|
||||
42
libraries/plugins/auth/recaptcha/ReCaptcha/RequestMethod.php
Normal file
42
libraries/plugins/auth/recaptcha/ReCaptcha/RequestMethod.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
*
|
||||
* @copyright Copyright (c) 2015, Google Inc.
|
||||
* @link http://www.google.com/recaptcha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace ReCaptcha;
|
||||
|
||||
/**
|
||||
* Method used to send the request to the service.
|
||||
*/
|
||||
interface RequestMethod
|
||||
{
|
||||
|
||||
/**
|
||||
* Submit the request with the specified parameters.
|
||||
*
|
||||
* @param RequestParameters $params Request parameters
|
||||
* @return string Body of the reCAPTCHA response
|
||||
*/
|
||||
public function submit(RequestParameters $params);
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/**
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
*
|
||||
* @copyright Copyright (c) 2015, Google Inc.
|
||||
* @link http://www.google.com/recaptcha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace ReCaptcha\RequestMethod;
|
||||
|
||||
use ReCaptcha\RequestMethod;
|
||||
use ReCaptcha\RequestParameters;
|
||||
|
||||
/**
|
||||
* Sends POST requests to the reCAPTCHA service.
|
||||
*/
|
||||
class Post implements RequestMethod
|
||||
{
|
||||
/**
|
||||
* URL to which requests are POSTed.
|
||||
* @const string
|
||||
*/
|
||||
const SITE_VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify';
|
||||
|
||||
/**
|
||||
* Submit the POST request with the specified parameters.
|
||||
*
|
||||
* @param RequestParameters $params Request parameters
|
||||
* @return string Body of the reCAPTCHA response
|
||||
*/
|
||||
public function submit(RequestParameters $params)
|
||||
{
|
||||
/**
|
||||
* PHP 5.6.0 changed the way you specify the peer name for SSL context options.
|
||||
* Using "CN_name" will still work, but it will raise deprecated errors.
|
||||
*/
|
||||
$peer_key = version_compare(PHP_VERSION, '5.6.0', '<') ? 'CN_name' : 'peer_name';
|
||||
$options = array(
|
||||
'http' => array(
|
||||
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
|
||||
'method' => 'POST',
|
||||
'content' => $params->toQueryString(),
|
||||
// Force the peer to validate (not needed in 5.6.0+, but still works
|
||||
'verify_peer' => true,
|
||||
// Force the peer validation to use www.google.com
|
||||
$peer_key => 'www.google.com',
|
||||
),
|
||||
);
|
||||
$context = stream_context_create($options);
|
||||
return file_get_contents(self::SITE_VERIFY_URL, false, $context);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
/**
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
*
|
||||
* @copyright Copyright (c) 2015, Google Inc.
|
||||
* @link http://www.google.com/recaptcha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace ReCaptcha\RequestMethod;
|
||||
|
||||
/**
|
||||
* Convenience wrapper around native socket and file functions to allow for
|
||||
* mocking.
|
||||
*/
|
||||
class Socket
|
||||
{
|
||||
private $handle = null;
|
||||
|
||||
/**
|
||||
* fsockopen
|
||||
*
|
||||
* @see http://php.net/fsockopen
|
||||
* @param string $hostname
|
||||
* @param int $port
|
||||
* @param int $errno
|
||||
* @param string $errstr
|
||||
* @param float $timeout
|
||||
* @return resource
|
||||
*/
|
||||
public function fsockopen($hostname, $port = -1, &$errno = 0, &$errstr = '', $timeout = null)
|
||||
{
|
||||
$this->handle = fsockopen($hostname, $port, $errno, $errstr, (is_null($timeout) ? ini_get("default_socket_timeout") : $timeout));
|
||||
|
||||
if ($this->handle != false && $errno === 0 && $errstr === '') {
|
||||
return $this->handle;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fwrite
|
||||
*
|
||||
* @see http://php.net/fwrite
|
||||
* @param string $string
|
||||
* @param int $length
|
||||
* @return int | bool
|
||||
*/
|
||||
public function fwrite($string, $length = null)
|
||||
{
|
||||
return fwrite($this->handle, $string, (is_null($length) ? strlen($string) : $length));
|
||||
}
|
||||
|
||||
/**
|
||||
* fgets
|
||||
*
|
||||
* @see http://php.net/fgets
|
||||
* @param int $length
|
||||
*/
|
||||
public function fgets($length = null)
|
||||
{
|
||||
return fgets($this->handle, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* feof
|
||||
*
|
||||
* @see http://php.net/feof
|
||||
* @return bool
|
||||
*/
|
||||
public function feof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* fclose
|
||||
*
|
||||
* @see http://php.net/fclose
|
||||
* @return bool
|
||||
*/
|
||||
public function fclose()
|
||||
{
|
||||
return fclose($this->handle);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/**
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
*
|
||||
* @copyright Copyright (c) 2015, Google Inc.
|
||||
* @link http://www.google.com/recaptcha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace ReCaptcha\RequestMethod;
|
||||
|
||||
use ReCaptcha\RequestMethod;
|
||||
use ReCaptcha\RequestParameters;
|
||||
|
||||
/**
|
||||
* Sends a POST request to the reCAPTCHA service, but makes use of fsockopen()
|
||||
* instead of get_file_contents(). This is to account for people who may be on
|
||||
* servers where allow_furl_open is disabled.
|
||||
*/
|
||||
class SocketPost implements RequestMethod
|
||||
{
|
||||
/**
|
||||
* reCAPTCHA service host.
|
||||
* @const string
|
||||
*/
|
||||
const RECAPTCHA_HOST = 'www.google.com';
|
||||
|
||||
/**
|
||||
* @const string reCAPTCHA service path
|
||||
*/
|
||||
const SITE_VERIFY_PATH = '/recaptcha/api/siteverify';
|
||||
|
||||
/**
|
||||
* @const string Bad request error
|
||||
*/
|
||||
const BAD_REQUEST = '{"success": false, "error-codes": ["invalid-request"]}';
|
||||
|
||||
/**
|
||||
* @const string Bad response error
|
||||
*/
|
||||
const BAD_RESPONSE = '{"success": false, "error-codes": ["invalid-response"]}';
|
||||
|
||||
/**
|
||||
* Socket to the reCAPTCHA service
|
||||
* @var Socket
|
||||
*/
|
||||
private $socket;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \ReCaptcha\RequestMethod\Socket $socket optional socket, injectable for testing
|
||||
*/
|
||||
public function __construct(Socket $socket = null)
|
||||
{
|
||||
if (!is_null($socket)) {
|
||||
$this->socket = $socket;
|
||||
} else {
|
||||
$this->socket = new Socket();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit the POST request with the specified parameters.
|
||||
*
|
||||
* @param RequestParameters $params Request parameters
|
||||
* @return string Body of the reCAPTCHA response
|
||||
*/
|
||||
public function submit(RequestParameters $params)
|
||||
{
|
||||
$errno = 0;
|
||||
$errstr = '';
|
||||
|
||||
if ($this->socket->fsockopen('ssl://' . self::RECAPTCHA_HOST, 443, $errno, $errstr, 30) !== false) {
|
||||
$content = $params->toQueryString();
|
||||
|
||||
$request = "POST " . self::SITE_VERIFY_PATH . " HTTP/1.1\r\n";
|
||||
$request .= "Host: " . self::RECAPTCHA_HOST . "\r\n";
|
||||
$request .= "Content-Type: application/x-www-form-urlencoded\r\n";
|
||||
$request .= "Content-length: " . strlen($content) . "\r\n";
|
||||
$request .= "Connection: close\r\n\r\n";
|
||||
$request .= $content . "\r\n\r\n";
|
||||
|
||||
$this->socket->fwrite($request);
|
||||
$response = '';
|
||||
|
||||
while (!$this->socket->feof()) {
|
||||
$response .= $this->socket->fgets(4096);
|
||||
}
|
||||
|
||||
$this->socket->fclose();
|
||||
|
||||
if (0 === strpos($response, 'HTTP/1.1 200 OK')) {
|
||||
$parts = preg_split("#\n\s*\n#Uis", $response);
|
||||
return $parts[1];
|
||||
}
|
||||
|
||||
return self::BAD_RESPONSE;
|
||||
}
|
||||
|
||||
return self::BAD_REQUEST;
|
||||
}
|
||||
}
|
||||
103
libraries/plugins/auth/recaptcha/ReCaptcha/RequestParameters.php
Normal file
103
libraries/plugins/auth/recaptcha/ReCaptcha/RequestParameters.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
/**
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
*
|
||||
* @copyright Copyright (c) 2015, Google Inc.
|
||||
* @link http://www.google.com/recaptcha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace ReCaptcha;
|
||||
|
||||
/**
|
||||
* Stores and formats the parameters for the request to the reCAPTCHA service.
|
||||
*/
|
||||
class RequestParameters
|
||||
{
|
||||
/**
|
||||
* Site secret.
|
||||
* @var string
|
||||
*/
|
||||
private $secret;
|
||||
|
||||
/**
|
||||
* Form response.
|
||||
* @var string
|
||||
*/
|
||||
private $response;
|
||||
|
||||
/**
|
||||
* Remote user's IP address.
|
||||
* @var string
|
||||
*/
|
||||
private $remoteIp;
|
||||
|
||||
/**
|
||||
* Client version.
|
||||
* @var string
|
||||
*/
|
||||
private $version;
|
||||
|
||||
/**
|
||||
* Initialise parameters.
|
||||
*
|
||||
* @param string $secret Site secret.
|
||||
* @param string $response Value from g-captcha-response form field.
|
||||
* @param string $remoteIp User's IP address.
|
||||
* @param string $version Version of this client library.
|
||||
*/
|
||||
public function __construct($secret, $response, $remoteIp = null, $version = null)
|
||||
{
|
||||
$this->secret = $secret;
|
||||
$this->response = $response;
|
||||
$this->remoteIp = $remoteIp;
|
||||
$this->version = $version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Array representation.
|
||||
*
|
||||
* @return array Array formatted parameters.
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
$params = array('secret' => $this->secret, 'response' => $this->response);
|
||||
|
||||
if (!is_null($this->remoteIp)) {
|
||||
$params['remoteip'] = $this->remoteIp;
|
||||
}
|
||||
|
||||
if (!is_null($this->version)) {
|
||||
$params['version'] = $this->version;
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query string representation for HTTP request.
|
||||
*
|
||||
* @return string Query string formatted parameters.
|
||||
*/
|
||||
public function toQueryString()
|
||||
{
|
||||
return http_build_query($this->toArray());
|
||||
}
|
||||
}
|
||||
102
libraries/plugins/auth/recaptcha/ReCaptcha/Response.php
Normal file
102
libraries/plugins/auth/recaptcha/ReCaptcha/Response.php
Normal file
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
*
|
||||
* @copyright Copyright (c) 2015, Google Inc.
|
||||
* @link http://www.google.com/recaptcha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace ReCaptcha;
|
||||
|
||||
/**
|
||||
* The response returned from the service.
|
||||
*/
|
||||
class Response
|
||||
{
|
||||
/**
|
||||
* Succes or failure.
|
||||
* @var boolean
|
||||
*/
|
||||
private $success = false;
|
||||
|
||||
/**
|
||||
* Error code strings.
|
||||
* @var array
|
||||
*/
|
||||
private $errorCodes = array();
|
||||
|
||||
/**
|
||||
* Build the response from the expected JSON returned by the service.
|
||||
*
|
||||
* @param string $json
|
||||
* @return \ReCaptcha\Response
|
||||
*/
|
||||
public static function fromJson($json)
|
||||
{
|
||||
$responseData = json_decode($json, true);
|
||||
|
||||
if (!$responseData) {
|
||||
return new Response(false, array('invalid-json'));
|
||||
}
|
||||
|
||||
if (isset($responseData['success']) && $responseData['success'] == true) {
|
||||
return new Response(true);
|
||||
}
|
||||
|
||||
if (isset($responseData['error-codes']) && is_array($responseData['error-codes'])) {
|
||||
return new Response(false, $responseData['error-codes']);
|
||||
}
|
||||
|
||||
return new Response(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param boolean $success
|
||||
* @param array $errorCodes
|
||||
*/
|
||||
public function __construct($success, array $errorCodes = array())
|
||||
{
|
||||
$this->success = $success;
|
||||
$this->errorCodes = $errorCodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is success?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isSuccess()
|
||||
{
|
||||
return $this->success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get error codes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getErrorCodes()
|
||||
{
|
||||
return $this->errorCodes;
|
||||
}
|
||||
}
|
||||
38
libraries/plugins/auth/recaptcha/autoload.php
Normal file
38
libraries/plugins/auth/recaptcha/autoload.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/* An autoloader for ReCaptcha\Foo classes. This should be require()d
|
||||
* by the user before attempting to instantiate any of the ReCaptcha
|
||||
* classes.
|
||||
*/
|
||||
|
||||
spl_autoload_register(function ($class) {
|
||||
if (substr($class, 0, 10) !== 'ReCaptcha\\') {
|
||||
/* If the class does not lie under the "ReCaptcha" namespace,
|
||||
* then we can exit immediately.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
/* All of the classes have names like "ReCaptcha\Foo", so we need
|
||||
* to replace the backslashes with frontslashes if we want the
|
||||
* name to map directly to a location in the filesystem.
|
||||
*/
|
||||
$class = str_replace('\\', '/', $class);
|
||||
|
||||
/* First, check under the current directory. It is important that
|
||||
* we look here first, so that we don't waste time searching for
|
||||
* test classes in the common case.
|
||||
*/
|
||||
$path = dirname(__FILE__).'/'.$class.'.php';
|
||||
if (is_readable($path)) {
|
||||
require_once $path;
|
||||
}
|
||||
|
||||
/* If we didn't find what we're looking for already, maybe it's
|
||||
* a test class?
|
||||
*/
|
||||
$path = dirname(__FILE__).'/../tests/'.$class.'.php';
|
||||
if (is_readable($path)) {
|
||||
require_once $path;
|
||||
}
|
||||
});
|
||||
@ -1,139 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
* - Documentation and latest version
|
||||
* https://developers.google.com/recaptcha/docs/php
|
||||
* - Get a reCAPTCHA API Key
|
||||
* https://www.google.com/recaptcha/admin/create
|
||||
* - Discussion group
|
||||
* http://groups.google.com/group/recaptcha
|
||||
*
|
||||
* @copyright Copyright (c) 2014, Google Inc.
|
||||
* @link http://www.google.com/recaptcha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A ReCaptchaResponse is returned from checkAnswer().
|
||||
*/
|
||||
class ReCaptchaResponse
|
||||
{
|
||||
public $success;
|
||||
public $errorCodes;
|
||||
}
|
||||
|
||||
class ReCaptcha
|
||||
{
|
||||
private static $_signupUrl = "https://www.google.com/recaptcha/admin";
|
||||
private static $_siteVerifyUrl =
|
||||
"https://www.google.com/recaptcha/api/siteverify?";
|
||||
private $_secret;
|
||||
private static $_version = "php_1.0";
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $secret shared secret between site and ReCAPTCHA server.
|
||||
*/
|
||||
public function ReCaptcha($secret)
|
||||
{
|
||||
if ($secret == null || $secret == "") {
|
||||
die("To use reCAPTCHA you must get an API key from <a href='"
|
||||
. self::$_signupUrl . "'>" . self::$_signupUrl . "</a>");
|
||||
}
|
||||
$this->_secret=$secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the given data into a query string format.
|
||||
*
|
||||
* @param array $data array of string elements to be encoded.
|
||||
*
|
||||
* @return string - encoded request.
|
||||
*/
|
||||
private function _encodeQS($data)
|
||||
{
|
||||
$req = "";
|
||||
foreach ($data as $key => $value) {
|
||||
$req .= $key . '=' . urlencode(stripslashes($value)) . '&';
|
||||
}
|
||||
|
||||
// Cut the last '&'
|
||||
$req=substr($req, 0, strlen($req)-1);
|
||||
return $req;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits an HTTP GET to a reCAPTCHA server.
|
||||
*
|
||||
* @param string $path url path to recaptcha server.
|
||||
* @param array $data array of parameters to be sent.
|
||||
*
|
||||
* @return array response
|
||||
*/
|
||||
private function _submitHTTPGet($path, $data)
|
||||
{
|
||||
$req = $this->_encodeQS($data);
|
||||
$response = file_get_contents($path . $req);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the reCAPTCHA siteverify API to verify whether the user passes
|
||||
* CAPTCHA test.
|
||||
*
|
||||
* @param string $remoteIp IP address of end user.
|
||||
* @param string $response response string from recaptcha verification.
|
||||
*
|
||||
* @return ReCaptchaResponse
|
||||
*/
|
||||
public function verifyResponse($remoteIp, $response)
|
||||
{
|
||||
// Discard empty solution submissions
|
||||
if ($response == null || strlen($response) == 0) {
|
||||
$recaptchaResponse = new ReCaptchaResponse();
|
||||
$recaptchaResponse->success = false;
|
||||
$recaptchaResponse->errorCodes = 'missing-input';
|
||||
return $recaptchaResponse;
|
||||
}
|
||||
|
||||
$getResponse = $this->_submitHttpGet(
|
||||
self::$_siteVerifyUrl,
|
||||
array (
|
||||
'secret' => $this->_secret,
|
||||
'remoteip' => $remoteIp,
|
||||
'v' => self::$_version,
|
||||
'response' => $response
|
||||
)
|
||||
);
|
||||
$answers = json_decode($getResponse, true);
|
||||
$recaptchaResponse = new ReCaptchaResponse();
|
||||
|
||||
if (trim($answers ['success']) == true) {
|
||||
$recaptchaResponse->success = true;
|
||||
} else {
|
||||
$recaptchaResponse->success = false;
|
||||
$recaptchaResponse->errorCodes = $answers ['error-codes'];
|
||||
}
|
||||
|
||||
return $recaptchaResponse;
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,13 +262,27 @@ class ExportSql extends ExportPlugin
|
||||
$leaf->setText(sprintf(__('Add %s statement'), $drop_clause));
|
||||
$subgroup->addProperty($leaf);
|
||||
|
||||
$subgroup_create_table = new OptionsPropertySubgroup();
|
||||
|
||||
// Add table structure option
|
||||
$leaf = new BoolPropertyItem();
|
||||
$leaf->setName('create_table');
|
||||
$leaf->setText(
|
||||
sprintf(__('Add %s statement'), '<code>CREATE TABLE</code>')
|
||||
);
|
||||
$subgroup->addProperty($leaf);
|
||||
$subgroup_create_table->setSubgroupHeader($leaf);
|
||||
|
||||
$leaf = new BoolPropertyItem();
|
||||
$leaf->setName('if_not_exists');
|
||||
$leaf->setText('<code>IF NOT EXISTS</code> ' . __('(less efficient as indexes will be generated during table creation)'));
|
||||
$subgroup_create_table->addProperty($leaf);
|
||||
|
||||
$leaf = new BoolPropertyItem();
|
||||
$leaf->setName('auto_increment');
|
||||
$leaf->setText(sprintf(__('%s value'), '<code>AUTO_INCREMENT</code>'));
|
||||
$subgroup_create_table->addProperty($leaf);
|
||||
|
||||
$subgroup->addProperty($subgroup_create_table);
|
||||
|
||||
// Add view option
|
||||
$leaf = new BoolPropertyItem();
|
||||
@ -299,21 +313,6 @@ class ExportSql extends ExportPlugin
|
||||
);
|
||||
$subgroup->addProperty($leaf);
|
||||
|
||||
// begin CREATE TABLE statements
|
||||
$subgroup_create_table = new OptionsPropertySubgroup();
|
||||
$leaf = new BoolPropertyItem();
|
||||
$leaf->setName('create_table_statements');
|
||||
$leaf->setText(__('<code>CREATE TABLE</code> options:'));
|
||||
$subgroup_create_table->setSubgroupHeader($leaf);
|
||||
$leaf = new BoolPropertyItem();
|
||||
$leaf->setName('if_not_exists');
|
||||
$leaf->setText('<code>IF NOT EXISTS</code>');
|
||||
$subgroup_create_table->addProperty($leaf);
|
||||
$leaf = new BoolPropertyItem();
|
||||
$leaf->setName('auto_increment');
|
||||
$leaf->setText('<code>AUTO_INCREMENT</code>');
|
||||
$subgroup_create_table->addProperty($leaf);
|
||||
$subgroup->addProperty($subgroup_create_table);
|
||||
$structureOptions->addProperty($subgroup);
|
||||
|
||||
$leaf = new BoolPropertyItem();
|
||||
@ -1036,8 +1035,7 @@ class ExportSql extends ExportPlugin
|
||||
$types = array(
|
||||
'bookmark' => 'dbase',
|
||||
'relation' => 'master_db',
|
||||
//'pdf_pages' => 'db_name',
|
||||
//'table_coords' => 'db_name',
|
||||
'pdf_pages' => 'db_name',
|
||||
'savedsearches' => 'db_name',
|
||||
'central_columns' => 'db_name',
|
||||
);
|
||||
@ -1071,6 +1069,69 @@ class ExportSql extends ExportPlugin
|
||||
foreach ($types as $type => $dbNameColumn) {
|
||||
if (in_array($type, $metadataTypes) && isset($cfgRelation[$type])) {
|
||||
|
||||
// special case, designer pages and their coordinates
|
||||
if ($type == 'pdf_pages') {
|
||||
|
||||
$sql_query = "SELECT `page_nr`, `page_descr` FROM "
|
||||
. PMA_Util::backquote($cfgRelation['db'])
|
||||
. "." . PMA_Util::backquote($cfgRelation[$type])
|
||||
. " WHERE " . PMA_Util::backquote($dbNameColumn)
|
||||
. " = '" . PMA_Util::sqlAddSlashes($db) . "'";
|
||||
|
||||
$result = $GLOBALS['dbi']->fetchResult(
|
||||
$sql_query, 'page_nr', 'page_descr'
|
||||
);
|
||||
|
||||
foreach ($result as $page => $name) {
|
||||
// insert row for pdf_page
|
||||
$sql_query_row = "SELECT `db_name`, `page_descr` FROM "
|
||||
. PMA_Util::backquote($cfgRelation['db'])
|
||||
. "." . PMA_Util::backquote($cfgRelation[$type])
|
||||
. " WHERE " . PMA_Util::backquote($dbNameColumn)
|
||||
. " = '" . PMA_Util::sqlAddSlashes($db) . "'"
|
||||
. " AND `page_nr` = '" . $page . "'";
|
||||
|
||||
if (! $this->exportData(
|
||||
$cfgRelation['db'],
|
||||
$cfgRelation[$type],
|
||||
$GLOBALS['crlf'],
|
||||
'',
|
||||
$sql_query_row,
|
||||
$aliases
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$lastPage = $GLOBALS['crlf']
|
||||
. "SET @LAST_PAGE = LAST_INSERT_ID();"
|
||||
. $GLOBALS['crlf'] ;
|
||||
if (! PMA_exportOutputHandler($lastPage)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sql_query_coords = "SELECT `db_name`, `table_name`, "
|
||||
. "'@LAST_PAGE' AS `pdf_page_number`, `x`, `y` FROM "
|
||||
. PMA_Util::backquote($cfgRelation['db'])
|
||||
. "." . PMA_Util::backquote($cfgRelation['table_coords'])
|
||||
. " WHERE `pdf_page_number` = '" . $page . "'";
|
||||
|
||||
$GLOBALS['exporting_metadata'] = true;
|
||||
if (! $this->exportData(
|
||||
$cfgRelation['db'],
|
||||
$cfgRelation['table_coords'],
|
||||
$GLOBALS['crlf'],
|
||||
'',
|
||||
$sql_query_coords,
|
||||
$aliases
|
||||
)) {
|
||||
$GLOBALS['exporting_metadata'] = false;
|
||||
return false;
|
||||
}
|
||||
$GLOBALS['exporting_metadata'] = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// remove auto_incrementing id field for some tables
|
||||
if ($type == 'bookmark') {
|
||||
$sql_query = "SELECT `dbase`, `user`, `label`, `query` FROM ";
|
||||
@ -1546,23 +1607,27 @@ class ExportSql extends ExportPlugin
|
||||
// constraints).
|
||||
if ($field->key->type === 'FULLTEXT KEY') {
|
||||
$indexes_fulltext[] = $field->build($field);
|
||||
} else {
|
||||
unset($statement->fields[$key]);
|
||||
} else if (empty($GLOBALS['sql_if_not_exists'])) {
|
||||
$indexes[] = $field->build($field);
|
||||
unset($statement->fields[$key]);
|
||||
}
|
||||
unset($statement->fields[$key]);
|
||||
}
|
||||
|
||||
// Creating the parts that drop foreign keys.
|
||||
if (!empty($field->key)) {
|
||||
if ($field->key->type === 'FOREIGN KEY') {
|
||||
$dropped[] = 'FOREIGN KEY ' . SqlParser\Context::escape($field->name);
|
||||
unset($statement->fields[$key]);
|
||||
}
|
||||
unset($statement->fields[$key]);
|
||||
}
|
||||
|
||||
// Dropping AUTO_INCREMENT.
|
||||
if (!empty($field->options)) {
|
||||
if ($field->options->has('AUTO_INCREMENT')) {
|
||||
if ($field->options->has('AUTO_INCREMENT')
|
||||
&& empty($GLOBALS['sql_if_not_exists'])
|
||||
) {
|
||||
|
||||
$auto_increment[] = $field::build($field);
|
||||
$field->options->remove('AUTO_INCREMENT');
|
||||
}
|
||||
@ -1630,14 +1695,17 @@ class ExportSql extends ExportPlugin
|
||||
}
|
||||
|
||||
// Generating auto-increment-related query.
|
||||
if ((!empty($auto_increment))
|
||||
if ((! empty($auto_increment))
|
||||
&& ($update_indexes_increments)
|
||||
&& ($statement->entityOptions->has('AUTO_INCREMENT') !== false)
|
||||
) {
|
||||
$sql_auto_increments_query = $alter_header .
|
||||
$crlf . ' MODIFY ' . implode(',' . $crlf . ' MODIFY ', $auto_increment) .
|
||||
', AUTO_INCREMENT=' . $statement->entityOptions->has('AUTO_INCREMENT')
|
||||
. $alter_footer;
|
||||
$crlf . ' MODIFY ' . implode(',' . $crlf . ' MODIFY ', $auto_increment);
|
||||
if (isset($GLOBALS['sql_auto_increment'])) {
|
||||
$sql_auto_increments_query .= ', AUTO_INCREMENT='
|
||||
. $statement->entityOptions->has('AUTO_INCREMENT');
|
||||
}
|
||||
$sql_auto_increments_query .= ';';
|
||||
|
||||
$sql_auto_increments = $this->generateComment(
|
||||
$crlf, $sql_auto_increments,
|
||||
@ -1648,7 +1716,9 @@ class ExportSql extends ExportPlugin
|
||||
|
||||
// Removing the `AUTO_INCREMENT` attribute from the `CREATE TABLE`
|
||||
// too.
|
||||
if (!empty($statement->entityOptions)) {
|
||||
if (!empty($statement->entityOptions)
|
||||
&& empty($GLOBALS['sql_if_not_exists'])
|
||||
) {
|
||||
$statement->entityOptions->remove('AUTO_INCREMENT');
|
||||
}
|
||||
|
||||
@ -2224,6 +2294,10 @@ class ExportSql extends ExportPlugin
|
||||
)
|
||||
)
|
||||
. "'";
|
||||
} elseif (! empty($GLOBALS['exporting_metadata'])
|
||||
&& $row[$j] == '@LAST_PAGE'
|
||||
) {
|
||||
$values[] = '@LAST_PAGE';
|
||||
} else {
|
||||
// something else -> treat as a string
|
||||
$values[] = '\''
|
||||
|
||||
@ -21,103 +21,6 @@ require_once 'libraries/plugins/ImportPlugin.class.php';
|
||||
*/
|
||||
class ImportSql extends ImportPlugin
|
||||
{
|
||||
const BIG_VALUE = 2147483647;
|
||||
const READ_MB_FALSE = 0;
|
||||
const READ_MB_TRUE = 1;
|
||||
|
||||
/**
|
||||
* @var string SQL delimiter
|
||||
*/
|
||||
private $_delimiter;
|
||||
|
||||
/**
|
||||
* @var int SQL delimiter length
|
||||
*/
|
||||
private $_delimiterLength;
|
||||
|
||||
/**
|
||||
* @var bool|int SQL delimiter position or false if not found
|
||||
*/
|
||||
private $_delimiterPosition = false;
|
||||
|
||||
/**
|
||||
* @var int Query start position
|
||||
*/
|
||||
private $_queryBeginPosition = 0;
|
||||
|
||||
/**
|
||||
* @var int|false First special chars position or false if not found
|
||||
*/
|
||||
private $_firstSearchChar = null;
|
||||
|
||||
/**
|
||||
* @var bool Current position is in string
|
||||
*/
|
||||
private $_isInString = false;
|
||||
|
||||
/**
|
||||
* @var string Quote of current string or null if out of string
|
||||
*/
|
||||
private $_quote = null;
|
||||
|
||||
/**
|
||||
* @var bool Current position is in comment
|
||||
*/
|
||||
private $_isInComment = false;
|
||||
|
||||
/**
|
||||
* @var string Current comment opener
|
||||
*/
|
||||
private $_openingComment = null;
|
||||
|
||||
/**
|
||||
* @var bool Current position is in delimiter definition
|
||||
*/
|
||||
private $_isInDelimiter = false;
|
||||
|
||||
/**
|
||||
* @var string Delimiter keyword
|
||||
*/
|
||||
private $_delimiterKeyword = 'DELIMITER ';
|
||||
|
||||
/**
|
||||
* @var int Import should be done using multibytes
|
||||
*/
|
||||
private $_readMb = self::READ_MB_FALSE;
|
||||
|
||||
/**
|
||||
* @var string Data to parse
|
||||
*/
|
||||
private $_data = null;
|
||||
|
||||
/**
|
||||
* @var int Length of data to parse
|
||||
*/
|
||||
private $_dataLength = 0;
|
||||
|
||||
/**
|
||||
* @var array List of string functions
|
||||
* @todo Move this part in string functions definition file.
|
||||
*/
|
||||
private $_stringFunctions = array(
|
||||
self::READ_MB_FALSE => array(
|
||||
'substr' => 'substr',
|
||||
'strlen' => 'strlen',
|
||||
'strpos' => 'strpos',
|
||||
'strtoupper' => 'strtoupper',
|
||||
),
|
||||
self::READ_MB_TRUE => array(
|
||||
'substr' => 'mb_substr',
|
||||
'strlen' => 'mb_strlen',
|
||||
'strpos' => 'mb_strpos',
|
||||
'strtoupper' => 'mb_strtoupper',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* @var bool|int List of string functions to use
|
||||
*/
|
||||
private $_stringFctToUse = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -189,13 +92,6 @@ class ImportSql extends ImportPlugin
|
||||
);
|
||||
$generalOptions->addProperty($leaf);
|
||||
|
||||
$leaf = new BoolPropertyItem();
|
||||
$leaf->setName("read_as_multibytes");
|
||||
$leaf->setText(
|
||||
__('Read as multibytes')
|
||||
);
|
||||
$generalOptions->addProperty($leaf);
|
||||
|
||||
// add the main group to the root group
|
||||
$importSpecificOptions->addProperty($generalOptions);
|
||||
// set the options for the import plugin property item
|
||||
@ -205,182 +101,7 @@ class ImportSql extends ImportPlugin
|
||||
$this->properties = $importPluginProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for end of string
|
||||
*
|
||||
* @return bool End of string found
|
||||
*/
|
||||
private function _searchStringEnd()
|
||||
{
|
||||
//Search for closing quote
|
||||
$posClosingString = $this->_stringFctToUse['strpos'](
|
||||
$this->_data, $this->_quote, $this->_delimiterPosition
|
||||
);
|
||||
|
||||
if (false === $posClosingString) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Quotes escaped by quote will be considered as 2 consecutive strings
|
||||
//and won't pass in this loop.
|
||||
$posEscape = $posClosingString-1;
|
||||
while ($this->_stringFctToUse['substr']($this->_data, $posEscape, 1) == '\\'
|
||||
) {
|
||||
$posEscape--;
|
||||
}
|
||||
|
||||
// Odd count means it was escaped
|
||||
$quoteEscaped = (((($posClosingString - 1) - $posEscape) % 2) === 1);
|
||||
|
||||
//Move after the escaped quote.
|
||||
$this->_delimiterPosition = $posClosingString + 1;
|
||||
|
||||
if ($quoteEscaped) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->_isInString = false;
|
||||
$this->_quote = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the position of first SQL delimiter or false if no SQL delimiter found.
|
||||
*
|
||||
* @return int|bool Delimiter position or false if no delimiter found
|
||||
*/
|
||||
private function _findDelimiterPosition()
|
||||
{
|
||||
$this->_firstSearchChar = null;
|
||||
$firstSqlDelimiter = null;
|
||||
$matches = null;
|
||||
|
||||
/* while not at end of line */
|
||||
while ($this->_delimiterPosition < $this->_dataLength) {
|
||||
if ($this->_isInString) {
|
||||
if (false === $this->_searchStringEnd()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->_isInComment) {
|
||||
if (in_array($this->_openingComment, array('#', '-- '))) {
|
||||
$posClosingComment = $this->_stringFctToUse['strpos'](
|
||||
$this->_data,
|
||||
"\n",
|
||||
$this->_delimiterPosition
|
||||
);
|
||||
if (false === $posClosingComment) {
|
||||
return false;
|
||||
}
|
||||
//Move after the end of the line.
|
||||
$this->_delimiterPosition = $posClosingComment + 1;
|
||||
$this->_isInComment = false;
|
||||
$this->_openingComment = null;
|
||||
} elseif ('/*' === $this->_openingComment) {
|
||||
//Search for closing comment
|
||||
$posClosingComment = $this->_stringFctToUse['strpos'](
|
||||
$this->_data,
|
||||
'*/',
|
||||
$this->_delimiterPosition
|
||||
);
|
||||
if (false === $posClosingComment) {
|
||||
return false;
|
||||
}
|
||||
//Move after closing comment.
|
||||
$this->_delimiterPosition = $posClosingComment + 2;
|
||||
$this->_isInComment = false;
|
||||
$this->_openingComment = null;
|
||||
} else {
|
||||
//We shouldn't be able to come here.
|
||||
//throw new Exception('Unknown case.');
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->_isInDelimiter) {
|
||||
//Search for new line.
|
||||
if (!preg_match(
|
||||
"/^(.*)\n/",
|
||||
$this->_stringFctToUse['substr'](
|
||||
$this->_data,
|
||||
$this->_delimiterPosition
|
||||
),
|
||||
$matches,
|
||||
PREG_OFFSET_CAPTURE
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->_setDelimiter($matches[1][0]);
|
||||
//Start after delimiter and new line.
|
||||
$this->_queryBeginPosition = $this->_delimiterPosition
|
||||
+ $matches[1][1] + $this->_delimiterLength + 1;
|
||||
$this->_delimiterPosition = $this->_queryBeginPosition;
|
||||
$this->_isInDelimiter = false;
|
||||
$firstSqlDelimiter = null;
|
||||
$this->_firstSearchChar = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
$matches = $this->_searchSpecialChars($matches);
|
||||
|
||||
$firstSqlDelimiter = $this->_searchSqlDelimiter($firstSqlDelimiter);
|
||||
|
||||
if (false === $firstSqlDelimiter && false === $this->_firstSearchChar) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//If first char is delimiter.
|
||||
if (false === $this->_firstSearchChar
|
||||
|| (false !== $firstSqlDelimiter
|
||||
&& $firstSqlDelimiter < $this->_firstSearchChar)
|
||||
) {
|
||||
$this->_delimiterPosition = $firstSqlDelimiter;
|
||||
return true;
|
||||
}
|
||||
|
||||
//Else first char is result of preg_match.
|
||||
|
||||
$specialChars = $matches[1][0];
|
||||
|
||||
//If string is opened.
|
||||
if (in_array($specialChars, array('\'', '"', '`'))) {
|
||||
$this->_isInString = true;
|
||||
$this->_quote = $specialChars;
|
||||
//Move before quote.
|
||||
$this->_delimiterPosition = $this->_firstSearchChar + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
//If comment is opened.
|
||||
if (in_array($specialChars, array('#', '-- ', '/*'))) {
|
||||
$this->_isInComment = true;
|
||||
$this->_openingComment = $specialChars;
|
||||
//Move before comment opening.
|
||||
$this->_delimiterPosition = $this->_firstSearchChar
|
||||
+ $this->_stringFctToUse['strlen']($specialChars);
|
||||
continue;
|
||||
}
|
||||
|
||||
//If DELIMITER is found.
|
||||
$specialCharsUpper = $this->_stringFctToUse['strtoupper']($specialChars);
|
||||
if ($specialCharsUpper === $this->_delimiterKeyword) {
|
||||
$this->_isInDelimiter = true;
|
||||
$this->_delimiterPosition = $this->_firstSearchChar
|
||||
+ $this->_stringFctToUse['strlen']($specialChars);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Handles the whole import logic
|
||||
*
|
||||
* @param array &$sql_data 2-element array with sql data
|
||||
@ -391,95 +112,63 @@ class ImportSql extends ImportPlugin
|
||||
{
|
||||
global $error, $timeout_passed;
|
||||
|
||||
//Manage multibytes or not
|
||||
if (isset($_REQUEST['sql_read_as_multibytes'])) {
|
||||
$this->_readMb = self::READ_MB_TRUE;
|
||||
}
|
||||
$this->_stringFctToUse = $this->_stringFunctions[$this->_readMb];
|
||||
|
||||
if (isset($_POST['sql_delimiter'])) {
|
||||
$this->_setDelimiter($_POST['sql_delimiter']);
|
||||
} else {
|
||||
$this->_setDelimiter(';');
|
||||
}
|
||||
|
||||
// Handle compatibility options
|
||||
// Handle compatibility options.
|
||||
$this->_setSQLMode($GLOBALS['dbi'], $_REQUEST);
|
||||
|
||||
//Initialise data.
|
||||
$this->_setData(null);
|
||||
$bq = new SqlParser\Utils\BufferedQuery();
|
||||
if (isset($_POST['sql_delimiter'])) {
|
||||
$bq->setDelimiter($_POST['sql_delimiter']);
|
||||
}
|
||||
|
||||
/**
|
||||
* will be set in PMA_importGetNextChunk()
|
||||
*
|
||||
* @global boolean $GLOBALS['finished']
|
||||
* Will be set in PMA_importGetNextChunk().
|
||||
* @global bool $GLOBALS['finished']
|
||||
*/
|
||||
$GLOBALS['finished'] = false;
|
||||
$delimiterFound = false;
|
||||
|
||||
while (!$error && !$timeout_passed) {
|
||||
if (false === $delimiterFound) {
|
||||
$newData = PMA_importGetNextChunk(200);
|
||||
while ((!$error) && (!$timeout_passed)) {
|
||||
|
||||
// Getting the first statement, the remaining data and the last
|
||||
// delimiter.
|
||||
$statement = $bq->extract();
|
||||
|
||||
// If there is no full statement, we are looking for more data.
|
||||
if (empty($statement)) {
|
||||
|
||||
// Importing new data.
|
||||
$newData = PMA_importGetNextChunk();
|
||||
|
||||
// Subtract data we didn't handle yet and stop processing.
|
||||
if ($newData === false) {
|
||||
// subtract data we didn't handle yet and stop processing
|
||||
$GLOBALS['offset'] -= $this->_dataLength;
|
||||
$GLOBALS['offset'] -= mb_strlen($bq->query);
|
||||
break;
|
||||
}
|
||||
|
||||
// Checking if the input buffer has finished.
|
||||
if ($newData === true) {
|
||||
$GLOBALS['finished'] = true;
|
||||
break;
|
||||
}
|
||||
|
||||
//Convert CR (but not CRLF) to LF otherwise all queries
|
||||
//may not get executed on some platforms
|
||||
$this->_addData(preg_replace("/\r($|[^\n])/", "\n$1", $newData));
|
||||
unset($newData);
|
||||
}
|
||||
// Convert CR (but not CRLF) to LF otherwise all queries may
|
||||
// not get executed on some platforms.
|
||||
$bq->query .= preg_replace("/\r($|[^\n])/", "\n$1", $newData);
|
||||
|
||||
//Find quotes, comments, delimiter definition or delimiter itself.
|
||||
$delimiterFound = $this->_findDelimiterPosition();
|
||||
|
||||
//If no delimiter found, restart and get more data.
|
||||
if (false === $delimiterFound) {
|
||||
continue;
|
||||
}
|
||||
|
||||
PMA_importRunQuery(
|
||||
$this->_stringFctToUse['substr'](
|
||||
$this->_data,
|
||||
$this->_queryBeginPosition,
|
||||
$this->_delimiterPosition - $this->_queryBeginPosition
|
||||
), //Query to execute
|
||||
$this->_stringFctToUse['substr'](
|
||||
$this->_data,
|
||||
0,
|
||||
$this->_delimiterPosition + $this->_delimiterLength
|
||||
), //Query to display
|
||||
false,
|
||||
$sql_data
|
||||
);
|
||||
|
||||
$this->_setData(
|
||||
$this->_stringFctToUse['substr'](
|
||||
$this->_data,
|
||||
$this->_delimiterPosition + $this->_delimiterLength
|
||||
)
|
||||
);
|
||||
// Executing the query.
|
||||
PMA_importRunQuery($statement, $statement, false, $sql_data);
|
||||
}
|
||||
|
||||
if (! $timeout_passed) {
|
||||
//Commit any possible data in buffers
|
||||
PMA_importRunQuery(
|
||||
$this->_stringFctToUse['substr'](
|
||||
$this->_data,
|
||||
$this->_queryBeginPosition
|
||||
), //Query to execute
|
||||
$this->_data,
|
||||
false,
|
||||
$sql_data
|
||||
);
|
||||
// Extracting remaining statements.
|
||||
while ((!$error) && (!$timeout_passed)
|
||||
&& ($statement = $bq->extract(true))
|
||||
) {
|
||||
PMA_importRunQuery($statement, $statement, false, $sql_data);
|
||||
}
|
||||
|
||||
// Finishing.
|
||||
PMA_importRunQuery('', '', false, $sql_data);
|
||||
}
|
||||
|
||||
@ -508,113 +197,4 @@ class ImportSql extends ImportPlugin
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for special chars: comment, string or DELIMITER
|
||||
*
|
||||
* @param array $matches Special chars found in data
|
||||
*
|
||||
* @return array matches
|
||||
*/
|
||||
private function _searchSpecialChars(
|
||||
$matches
|
||||
) {
|
||||
//Don't look for a string/comment/"DELIMITER" if not found previously
|
||||
//or if it's still after current position.
|
||||
if (null === $this->_firstSearchChar
|
||||
|| (false !== $this->_firstSearchChar
|
||||
&& $this->_firstSearchChar < $this->_delimiterPosition)
|
||||
) {
|
||||
$bFind = preg_match(
|
||||
'/(\'|"|#|-- |\/\*|`|(?i)(?<![A-Z0-9_])'
|
||||
. $this->_delimiterKeyword . ')/',
|
||||
$this->_stringFctToUse['substr'](
|
||||
$this->_data,
|
||||
$this->_delimiterPosition
|
||||
),
|
||||
$matches,
|
||||
PREG_OFFSET_CAPTURE
|
||||
);
|
||||
|
||||
if (1 === $bFind) {
|
||||
$this->_firstSearchChar = $matches[1][1] + $this->_delimiterPosition;
|
||||
} else {
|
||||
$this->_firstSearchChar = false;
|
||||
}
|
||||
}
|
||||
return $matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for SQL delimiter
|
||||
*
|
||||
* @param int $firstSqlDelimiter First found char position
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function _searchSqlDelimiter($firstSqlDelimiter)
|
||||
{
|
||||
//Don't look for the SQL delimiter if not found previously
|
||||
//or if it's still after current position.
|
||||
if (null === $firstSqlDelimiter
|
||||
|| (false !== $firstSqlDelimiter
|
||||
&& $firstSqlDelimiter < $this->_delimiterPosition)
|
||||
) {
|
||||
// the cost of doing this one with preg_match() would be too high
|
||||
$firstSqlDelimiter = $this->_stringFctToUse['strpos'](
|
||||
$this->_data,
|
||||
$this->_delimiter,
|
||||
$this->_delimiterPosition
|
||||
);
|
||||
}
|
||||
|
||||
return $firstSqlDelimiter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new delimiter
|
||||
*
|
||||
* @param string $delimiter New delimiter
|
||||
*
|
||||
* @return int delimiter length
|
||||
*/
|
||||
private function _setDelimiter($delimiter)
|
||||
{
|
||||
$this->_delimiter = $delimiter;
|
||||
$this->_delimiterLength = $this->_stringFctToUse['strlen']($delimiter);
|
||||
|
||||
return $this->_delimiterLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set data to parse
|
||||
*
|
||||
* @param string $data Data to parse
|
||||
*
|
||||
* @return int Data length
|
||||
*/
|
||||
private function _setData($data)
|
||||
{
|
||||
$this->_data = ltrim($data);
|
||||
$this->_dataLength = $this->_stringFctToUse['strlen']($this->_data);
|
||||
$this->_queryBeginPosition = 0;
|
||||
$this->_delimiterPosition = 0;
|
||||
|
||||
return $this->_dataLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add data to parse
|
||||
*
|
||||
* @param string $data Data to add to data to parse
|
||||
*
|
||||
* @return int Data length
|
||||
*/
|
||||
private function _addData($data)
|
||||
{
|
||||
$this->_data .= $data;
|
||||
$this->_dataLength += $this->_stringFctToUse['strlen']($data);
|
||||
|
||||
return $this->_dataLength;
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,59 +57,59 @@ class Relation_Stats_Svg extends RelationStats
|
||||
{
|
||||
if ($showColor) {
|
||||
$listOfColors = array(
|
||||
'red',
|
||||
'grey',
|
||||
'black',
|
||||
'yellow',
|
||||
'green',
|
||||
'cyan',
|
||||
' orange'
|
||||
'#c00',
|
||||
'#bbb',
|
||||
'#333',
|
||||
'#cb0',
|
||||
'#0b0',
|
||||
'#0bf',
|
||||
'#b0b'
|
||||
);
|
||||
shuffle($listOfColors);
|
||||
$color = $listOfColors[0];
|
||||
} else {
|
||||
$color = 'black';
|
||||
$color = '#333';
|
||||
}
|
||||
|
||||
$this->diagram->printElementLine(
|
||||
'line', $this->xSrc, $this->ySrc,
|
||||
$this->xSrc + $this->srcDir * $this->wTick, $this->ySrc,
|
||||
'fill:' . $color . ';stroke:black;stroke-width:2;'
|
||||
'stroke:' . $color . ';stroke-width:1;'
|
||||
);
|
||||
$this->diagram->printElementLine(
|
||||
'line', $this->xDest + $this->destDir * $this->wTick,
|
||||
$this->yDest, $this->xDest, $this->yDest,
|
||||
'fill:' . $color . ';stroke:black;stroke-width:2;'
|
||||
'stroke:' . $color . ';stroke-width:1;'
|
||||
);
|
||||
$this->diagram->printElementLine(
|
||||
'line', $this->xSrc + $this->srcDir * $this->wTick, $this->ySrc,
|
||||
$this->xDest + $this->destDir * $this->wTick, $this->yDest,
|
||||
'fill:' . $color . ';stroke:' . $color . ';stroke-width:1;'
|
||||
'stroke:' . $color . ';stroke-width:1;'
|
||||
);
|
||||
$root2 = 2 * sqrt(2);
|
||||
$this->diagram->printElementLine(
|
||||
'line', $this->xSrc + $this->srcDir * $this->wTick * 0.75, $this->ySrc,
|
||||
$this->xSrc + $this->srcDir * (0.75 - 1 / $root2) * $this->wTick,
|
||||
$this->ySrc + $this->wTick / $root2,
|
||||
'fill:' . $color . ';stroke:black;stroke-width:2;'
|
||||
'stroke:' . $color . ';stroke-width:2;'
|
||||
);
|
||||
$this->diagram->printElementLine(
|
||||
'line', $this->xSrc + $this->srcDir * $this->wTick * 0.75, $this->ySrc,
|
||||
$this->xSrc + $this->srcDir * (0.75 - 1 / $root2) * $this->wTick,
|
||||
$this->ySrc - $this->wTick / $root2,
|
||||
'fill:' . $color . ';stroke:black;stroke-width:2;'
|
||||
'stroke:' . $color . ';stroke-width:2;'
|
||||
);
|
||||
$this->diagram->printElementLine(
|
||||
'line', $this->xDest + $this->destDir * $this->wTick / 2, $this->yDest,
|
||||
$this->xDest + $this->destDir * (0.5 + 1 / $root2) * $this->wTick,
|
||||
$this->yDest + $this->wTick / $root2,
|
||||
'fill:' . $color . ';stroke:black;stroke-width:2;'
|
||||
'stroke:' . $color . ';stroke-width:2;'
|
||||
);
|
||||
$this->diagram->printElementLine(
|
||||
'line', $this->xDest + $this->destDir * $this->wTick / 2, $this->yDest,
|
||||
$this->xDest + $this->destDir * (0.5 + 1 / $root2) * $this->wTick,
|
||||
$this->yDest - $this->wTick / $root2,
|
||||
'fill:' . $color . ';stroke:black;stroke-width:2;'
|
||||
'stroke:' . $color . ';stroke-width:2;'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,16 +135,30 @@ class PMA_SVG extends XMLWriter
|
||||
*
|
||||
* @param integer $width total width of the Svg document
|
||||
* @param integer $height total height of the Svg document
|
||||
* @param integer $x min-x of the view box
|
||||
* @param integer $y min-y of the view box
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @see XMLWriter::startElement(),XMLWriter::writeAttribute()
|
||||
*/
|
||||
public function startSvgDoc($width,$height)
|
||||
public function startSvgDoc($width, $height, $x = 0, $y = 0)
|
||||
{
|
||||
$this->startElement('svg');
|
||||
$this->writeAttribute('width', $width);
|
||||
$this->writeAttribute('height', $height);
|
||||
|
||||
if (!is_int($width)) {
|
||||
$width = intval($width);
|
||||
}
|
||||
|
||||
if (!is_int($height)) {
|
||||
$height = intval($height);
|
||||
}
|
||||
|
||||
if ($x != 0 || $y != 0) {
|
||||
$this->writeAttribute('viewBox', "$x $y $width $height");
|
||||
}
|
||||
$this->writeAttribute('width', ($width - $x) . 'px');
|
||||
$this->writeAttribute('height', ($height - $y) . 'px');
|
||||
$this->writeAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
||||
$this->writeAttribute('version', '1.1');
|
||||
}
|
||||
@ -314,7 +328,6 @@ class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
|
||||
$this->diagram->SetAuthor('phpMyAdmin ' . PMA_VERSION);
|
||||
$this->diagram->setFont('Arial');
|
||||
$this->diagram->setFontSize('16px');
|
||||
$this->diagram->startSvgDoc('1000px', '1000px');
|
||||
|
||||
$alltables = $this->getTablesFromRequest();
|
||||
|
||||
@ -330,10 +343,19 @@ class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
|
||||
}
|
||||
|
||||
if ($this->sameWide) {
|
||||
$this->_tables[$table]->width = $this->_tablewidth;
|
||||
$this->_tables[$table]->width = &$this->_tablewidth;
|
||||
}
|
||||
$this->_setMinMax($this->_tables[$table]);
|
||||
}
|
||||
|
||||
$border = 15;
|
||||
$this->diagram->startSvgDoc(
|
||||
$this->_xMax + $border,
|
||||
$this->_yMax + $border,
|
||||
$this->_xMin - $border,
|
||||
$this->_yMin - $border
|
||||
);
|
||||
|
||||
$seen_a_relation = false;
|
||||
foreach ($alltables as $one_table) {
|
||||
$exist_rel = PMA_getForeigners($this->db, $one_table, '', 'both');
|
||||
@ -351,9 +373,13 @@ class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
|
||||
if ($master_field != 'foreign_keys_data') {
|
||||
if (in_array($rel['foreign_table'], $alltables)) {
|
||||
$this->_addRelation(
|
||||
$one_table, $this->diagram->getFont(), $this->diagram->getFontSize(),
|
||||
$master_field, $rel['foreign_table'],
|
||||
$rel['foreign_field'], $this->tableDimension
|
||||
$one_table,
|
||||
$this->diagram->getFont(),
|
||||
$this->diagram->getFontSize(),
|
||||
$master_field,
|
||||
$rel['foreign_table'],
|
||||
$rel['foreign_field'],
|
||||
$this->tableDimension
|
||||
);
|
||||
}
|
||||
continue;
|
||||
|
||||
@ -139,18 +139,18 @@ class Table_Stats_Svg extends TableStats
|
||||
{
|
||||
$this->diagram->printElement(
|
||||
'rect', $this->x, $this->y, $this->width,
|
||||
$this->heightCell, null, 'fill:red;stroke:black;'
|
||||
$this->heightCell, null, 'fill:#007;stroke:black;'
|
||||
);
|
||||
$this->diagram->printElement(
|
||||
'text', $this->x + 5, $this->y+ 14, $this->width, $this->heightCell,
|
||||
$this->getTitle(), 'fill:none;stroke:black;'
|
||||
$this->getTitle(), 'fill:#fff;'
|
||||
);
|
||||
foreach ($this->fields as $field) {
|
||||
$this->currentCell += $this->heightCell;
|
||||
$fillColor = 'none';
|
||||
if ($showColor) {
|
||||
if (in_array($field, $this->primary)) {
|
||||
$fillColor = '#0c0';
|
||||
$fillColor = '#aea';
|
||||
}
|
||||
if ($field == $this->displayfield) {
|
||||
$fillColor = 'none';
|
||||
@ -162,7 +162,7 @@ class Table_Stats_Svg extends TableStats
|
||||
);
|
||||
$this->diagram->printElement(
|
||||
'text', $this->x + 5, $this->y + 14 + $this->currentCell,
|
||||
$this->width, $this->heightCell, $field, 'fill:none;stroke:black;'
|
||||
$this->width, $this->heightCell, $field, 'fill:black;'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -442,21 +442,21 @@ function PMA_saveTablePositions($pg)
|
||||
{
|
||||
$cfgRelation = PMA_getRelationsParam();
|
||||
if (! $cfgRelation['pdfwork']) {
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
$queury = "DELETE FROM " . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
|
||||
$query = "DELETE FROM " . PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
|
||||
. "." . PMA_Util::backquote($GLOBALS['cfgRelation']['table_coords'])
|
||||
. " WHERE `db_name` = '" . PMA_Util::sqlAddSlashes($_REQUEST['db']) . "'"
|
||||
. " AND `pdf_page_number` = '" . PMA_Util::sqlAddSlashes($pg) . "'";
|
||||
|
||||
$res = PMA_queryAsControlUser($queury, true, PMA_DatabaseInterface::QUERY_STORE);
|
||||
$res = PMA_queryAsControlUser($query, true, PMA_DatabaseInterface::QUERY_STORE);
|
||||
|
||||
if ($res) {
|
||||
foreach ($_REQUEST['t_h'] as $key => $value) {
|
||||
list($DB, $TAB) = explode(".", $key);
|
||||
if ($value) {
|
||||
$queury = "INSERT INTO "
|
||||
$query = "INSERT INTO "
|
||||
. PMA_Util::backquote($GLOBALS['cfgRelation']['db']) . "."
|
||||
. PMA_Util::backquote($GLOBALS['cfgRelation']['table_coords'])
|
||||
. " (`db_name`, `table_name`, `pdf_page_number`, `x`, `y`)"
|
||||
@ -468,13 +468,13 @@ function PMA_saveTablePositions($pg)
|
||||
. "'" . PMA_Util::sqlAddSlashes($_REQUEST['t_y'][$key]) . "')";
|
||||
|
||||
$res = PMA_queryAsControlUser(
|
||||
$queury, true, PMA_DatabaseInterface::QUERY_STORE
|
||||
$query, true, PMA_DatabaseInterface::QUERY_STORE
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
return (boolean) $res;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -700,3 +700,61 @@ function PMA_removeRelation($T1, $F1, $T2, $F2)
|
||||
|
||||
return array(true, __('Internal relation has been removed.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save value for a designer setting
|
||||
*
|
||||
* @param string $index setting
|
||||
* @param string $value value
|
||||
*
|
||||
* @return bool whether the operation succeeded
|
||||
*/
|
||||
function PMA_saveDesignerSetting($index, $value)
|
||||
{
|
||||
$cfgRelation = PMA_getRelationsParam();
|
||||
$cfgDesigner = array(
|
||||
'user' => $GLOBALS['cfg']['Server']['user'],
|
||||
'db' => $cfgRelation['db'],
|
||||
'table' => $cfgRelation['designer_settings']
|
||||
);
|
||||
|
||||
$success = true;
|
||||
if ($GLOBALS['cfgRelation']['designersettingswork']) {
|
||||
|
||||
$orig_data_query = "SELECT settings_data"
|
||||
. " FROM " . PMA_Util::backquote($cfgDesigner['db'])
|
||||
. "." . PMA_Util::backquote($cfgDesigner['table'])
|
||||
. " WHERE username = '"
|
||||
. PMA_Util::sqlAddSlashes($cfgDesigner['user']) . "';";
|
||||
|
||||
$orig_data = $GLOBALS['dbi']->fetchSingleRow(
|
||||
$orig_data_query, $GLOBALS['controllink']
|
||||
);
|
||||
|
||||
if (! empty($orig_data)) {
|
||||
$orig_data = json_decode($orig_data['settings_data'], true);
|
||||
$orig_data[$index] = $value;
|
||||
$orig_data = json_encode($orig_data);
|
||||
|
||||
$save_query = "UPDATE " . PMA_Util::backquote($cfgDesigner['db'])
|
||||
. "." . PMA_Util::backquote($cfgDesigner['table'])
|
||||
. " SET settings_data = '" . $orig_data . "'"
|
||||
. " WHERE username = '"
|
||||
. PMA_Util::sqlAddSlashes($cfgDesigner['user']) . "';";
|
||||
|
||||
$success = PMA_queryAsControlUser($save_query);
|
||||
} else {
|
||||
$save_data = array($index => $value);
|
||||
|
||||
$query = "INSERT INTO " . PMA_Util::backquote($cfgDesigner['db'])
|
||||
. "." . PMA_Util::backquote($cfgDesigner['table'])
|
||||
. " (username, settings_data)"
|
||||
. " VALUES('" . $cfgDesigner['user'] . "',"
|
||||
. " '" . json_encode($save_data) . "');";
|
||||
|
||||
$success = PMA_queryAsControlUser($query);
|
||||
}
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
@ -345,35 +345,30 @@ function PMA_getRelationsParamDiagnostic($cfgRelation)
|
||||
|
||||
$retval .= '<p>' . __('Quick steps to setup advanced features:')
|
||||
. '</p>';
|
||||
$retval .= '<ul>';
|
||||
$retval .= '<li>';
|
||||
$retval .= sprintf(
|
||||
|
||||
$items = array();
|
||||
$items[] = sprintf(
|
||||
__(
|
||||
'Create the needed tables with the '
|
||||
. '<code>%screate_tables.sql</code>.'
|
||||
),
|
||||
htmlspecialchars(SQL_DIR)
|
||||
);
|
||||
$retval .= ' ' . PMA_Util::showDocu('setup', 'linked-tables');
|
||||
$retval .= '</li>';
|
||||
$retval .= '<li>';
|
||||
$retval .= __('Create a pma user and give access to these tables.');
|
||||
$retval .= ' ' . PMA_Util::showDocu('config', 'cfg_Servers_controluser');
|
||||
$retval .= '</li>';
|
||||
$retval .= '<li>';
|
||||
$retval .= __(
|
||||
) . ' ' . PMA_Util::showDocu('setup', 'linked-tables');
|
||||
$items[] = __('Create a pma user and give access to these tables.') . ' '
|
||||
. PMA_Util::showDocu('config', 'cfg_Servers_controluser');
|
||||
$items[] = __(
|
||||
'Enable advanced features in configuration file '
|
||||
. '(<code>config.inc.php</code>), for example by '
|
||||
. 'starting from <code>config.sample.inc.php</code>.'
|
||||
);
|
||||
$retval .= ' ' . PMA_Util::showDocu('setup', 'quick-install');
|
||||
$retval .= '</li>';
|
||||
$retval .= '<li>';
|
||||
$retval .= __(
|
||||
) . ' ' . PMA_Util::showDocu('setup', 'quick-install');
|
||||
$items[] = __(
|
||||
'Re-login to phpMyAdmin to load the updated configuration file.'
|
||||
);
|
||||
$retval .= '</li>';
|
||||
$retval .= '</ul>';
|
||||
|
||||
include_once './libraries/Template.class.php';
|
||||
$retval .= PMA\Template::get('list/unordered')->render(
|
||||
array('items' => $items,)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -90,199 +90,7 @@ function PMA_RTN_handleEditor()
|
||||
{
|
||||
global $_GET, $_POST, $_REQUEST, $GLOBALS, $db, $errors;
|
||||
|
||||
if (! empty($_REQUEST['editor_process_add'])
|
||||
|| ! empty($_REQUEST['editor_process_edit'])
|
||||
) {
|
||||
/**
|
||||
* Handle a request to create/edit a routine
|
||||
*/
|
||||
$sql_query = '';
|
||||
$routine_query = PMA_RTN_getQueryFromRequest();
|
||||
if (! count($errors)) { // set by PMA_RTN_getQueryFromRequest()
|
||||
// Execute the created query
|
||||
if (! empty($_REQUEST['editor_process_edit'])) {
|
||||
$isProcOrFunc = in_array(
|
||||
$_REQUEST['item_original_type'],
|
||||
array('PROCEDURE', 'FUNCTION')
|
||||
);
|
||||
if (!$isProcOrFunc) {
|
||||
$errors[] = sprintf(
|
||||
__('Invalid routine type: "%s"'),
|
||||
htmlspecialchars($_REQUEST['item_original_type'])
|
||||
);
|
||||
} else {
|
||||
// Backup the old routine, in case something goes wrong
|
||||
$create_routine = $GLOBALS['dbi']->getDefinition(
|
||||
$db, $_REQUEST['item_original_type'],
|
||||
$_REQUEST['item_original_name']
|
||||
);
|
||||
|
||||
if (! defined('PMA_DRIZZLE') || ! PMA_DRIZZLE) {
|
||||
if (isset($GLOBALS['proc_priv']) && $GLOBALS['proc_priv']
|
||||
&& isset($GLOBALS['flush_priv']) && $GLOBALS['flush_priv']
|
||||
) {
|
||||
// Backup the Old Privileges before dropping
|
||||
// if $_REQUEST['item_adjust_privileges'] set
|
||||
$privilegesBackup = array();
|
||||
if (isset($_REQUEST['item_adjust_privileges'])
|
||||
&& ! empty($_REQUEST['item_adjust_privileges'])
|
||||
) {
|
||||
$privilegesBackupQuery = 'SELECT * FROM ' . PMA_Util::backquote('mysql')
|
||||
. '.' . PMA_Util::backquote('procs_priv')
|
||||
. ' where Routine_name = "' . $_REQUEST['item_original_name']
|
||||
. '" AND Routine_type = "' . $_REQUEST['item_original_type']
|
||||
. '";';
|
||||
|
||||
$privilegesBackup = $GLOBALS['dbi']->fetchResult(
|
||||
$privilegesBackupQuery, 0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$drop_routine = "DROP {$_REQUEST['item_original_type']} "
|
||||
. PMA_Util::backquote($_REQUEST['item_original_name'])
|
||||
. ";\n";
|
||||
$result = $GLOBALS['dbi']->tryQuery($drop_routine);
|
||||
if (! $result) {
|
||||
$errors[] = sprintf(
|
||||
__('The following query has failed: "%s"'),
|
||||
htmlspecialchars($drop_routine)
|
||||
)
|
||||
. '<br />'
|
||||
. __('MySQL said: ') . $GLOBALS['dbi']->getError(null);
|
||||
} else {
|
||||
$result = $GLOBALS['dbi']->tryQuery($routine_query);
|
||||
if (! $result) {
|
||||
$errors[] = sprintf(
|
||||
__('The following query has failed: "%s"'),
|
||||
htmlspecialchars($routine_query)
|
||||
)
|
||||
. '<br />'
|
||||
. __('MySQL said: ') . $GLOBALS['dbi']->getError(null);
|
||||
// We dropped the old routine,
|
||||
// but were unable to create the new one
|
||||
// Try to restore the backup query
|
||||
$result = $GLOBALS['dbi']->tryQuery($create_routine);
|
||||
$errors = checkResult(
|
||||
$result,
|
||||
__(
|
||||
'Sorry, we failed to restore'
|
||||
. ' the dropped routine.'
|
||||
),
|
||||
$create_routine,
|
||||
$errors
|
||||
);
|
||||
} else {
|
||||
// Default value
|
||||
$resultAdjust = false;
|
||||
|
||||
if (! defined('PMA_DRIZZLE') || ! PMA_DRIZZLE) {
|
||||
if (isset($GLOBALS['proc_priv']) && $GLOBALS['proc_priv']
|
||||
&& isset($GLOBALS['flush_priv']) && $GLOBALS['flush_priv']
|
||||
) {
|
||||
// Insert all the previous privileges
|
||||
// but with the new name and the new type
|
||||
foreach ($privilegesBackup as $priv) {
|
||||
$adjustProcPrivilege = 'INSERT INTO '
|
||||
. PMA_Util::backquote('mysql') . '.'
|
||||
. PMA_Util::backquote('procs_priv')
|
||||
. ' VALUES("' . $priv[0] . '", "'
|
||||
. $priv[1] . '", "' . $priv[2] . '", "'
|
||||
. $_REQUEST['item_name'] . '", "'
|
||||
. $_REQUEST['item_type'] . '", "'
|
||||
. $priv[5] . '", "'
|
||||
. $priv[6] . '", "'
|
||||
. $priv[7] . '");';
|
||||
$resultAdjust = $GLOBALS['dbi']->query(
|
||||
$adjustProcPrivilege
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($resultAdjust) {
|
||||
// Flush the Privileges
|
||||
$flushPrivQuery = 'FLUSH PRIVILEGES;';
|
||||
$GLOBALS['dbi']->query($flushPrivQuery);
|
||||
|
||||
$message = PMA_Message::success(
|
||||
__(
|
||||
'Routine %1$s has been modified. Privileges have been adjusted.'
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$message = PMA_Message::success(
|
||||
__('Routine %1$s has been modified.')
|
||||
);
|
||||
}
|
||||
$message->addParam(
|
||||
PMA_Util::backquote($_REQUEST['item_name'])
|
||||
);
|
||||
$sql_query = $drop_routine . $routine_query;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 'Add a new routine' mode
|
||||
$result = $GLOBALS['dbi']->tryQuery($routine_query);
|
||||
if (! $result) {
|
||||
$errors[] = sprintf(
|
||||
__('The following query has failed: "%s"'),
|
||||
htmlspecialchars($routine_query)
|
||||
)
|
||||
. '<br /><br />'
|
||||
. __('MySQL said: ') . $GLOBALS['dbi']->getError(null);
|
||||
} else {
|
||||
$message = PMA_Message::success(
|
||||
__('Routine %1$s has been created.')
|
||||
);
|
||||
$message->addParam(
|
||||
PMA_Util::backquote($_REQUEST['item_name'])
|
||||
);
|
||||
$sql_query = $routine_query;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($errors)) {
|
||||
$message = PMA_Message::error(
|
||||
__(
|
||||
'One or more errors have occurred while'
|
||||
. ' processing your request:'
|
||||
)
|
||||
);
|
||||
$message->addString('<ul>');
|
||||
foreach ($errors as $string) {
|
||||
$message->addString('<li>' . $string . '</li>');
|
||||
}
|
||||
$message->addString('</ul>');
|
||||
}
|
||||
|
||||
$output = PMA_Util::getMessage($message, $sql_query);
|
||||
if ($GLOBALS['is_ajax_request']) {
|
||||
$response = PMA_Response::getInstance();
|
||||
if ($message->isSuccess()) {
|
||||
$routines = $GLOBALS['dbi']->getRoutines(
|
||||
$db, $_REQUEST['item_type'], $_REQUEST['item_name']
|
||||
);
|
||||
$routine = $routines[0];
|
||||
$response->addJSON(
|
||||
'name',
|
||||
htmlspecialchars(
|
||||
/*overload*/mb_strtoupper($_REQUEST['item_name'])
|
||||
)
|
||||
);
|
||||
$response->addJSON('new_row', PMA_RTN_getRowForList($routine));
|
||||
$response->addJSON('insert', ! empty($routine));
|
||||
$response->addJSON('message', $output);
|
||||
} else {
|
||||
$response->isSuccess(false);
|
||||
$response->addJSON('message', $output);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
}
|
||||
$errors = PMA_RTN_handleRequestCreateOrEdit($errors, $db);
|
||||
|
||||
/**
|
||||
* Display a form used to add/edit a routine, if necessary
|
||||
@ -359,6 +167,288 @@ function PMA_RTN_handleEditor()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to create or edit a routine
|
||||
*
|
||||
* @param array $errors Errors
|
||||
* @param string $db DB name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function PMA_RTN_handleRequestCreateOrEdit($errors, $db)
|
||||
{
|
||||
if (empty($_REQUEST['editor_process_add'])
|
||||
&& empty($_REQUEST['editor_process_edit'])
|
||||
) {
|
||||
return $errors;
|
||||
}
|
||||
|
||||
$sql_query = '';
|
||||
$routine_query = PMA_RTN_getQueryFromRequest();
|
||||
if (!count($errors)) { // set by PMA_RTN_getQueryFromRequest()
|
||||
// Execute the created query
|
||||
if (!empty($_REQUEST['editor_process_edit'])) {
|
||||
$isProcOrFunc = in_array(
|
||||
$_REQUEST['item_original_type'],
|
||||
array('PROCEDURE', 'FUNCTION')
|
||||
);
|
||||
|
||||
if (!$isProcOrFunc) {
|
||||
$errors[] = sprintf(
|
||||
__('Invalid routine type: "%s"'),
|
||||
htmlspecialchars($_REQUEST['item_original_type'])
|
||||
);
|
||||
} else {
|
||||
// Backup the old routine, in case something goes wrong
|
||||
$create_routine = $GLOBALS['dbi']->getDefinition(
|
||||
$db,
|
||||
$_REQUEST['item_original_type'],
|
||||
$_REQUEST['item_original_name']
|
||||
);
|
||||
|
||||
$privilegesBackup = PMA_RTN_backupPrivileges();
|
||||
|
||||
$drop_routine = "DROP {$_REQUEST['item_original_type']} "
|
||||
. PMA_Util::backquote($_REQUEST['item_original_name'])
|
||||
. ";\n";
|
||||
$result = $GLOBALS['dbi']->tryQuery($drop_routine);
|
||||
if (!$result) {
|
||||
$errors[] = sprintf(
|
||||
__('The following query has failed: "%s"'),
|
||||
htmlspecialchars($drop_routine)
|
||||
)
|
||||
. '<br />'
|
||||
. __('MySQL said: ') . $GLOBALS['dbi']->getError(null);
|
||||
} else {
|
||||
list($newErrors, $message) = PMA_RTN_createRoutine(
|
||||
$routine_query,
|
||||
$create_routine,
|
||||
$privilegesBackup
|
||||
);
|
||||
if (empty($newErrors)) {
|
||||
$sql_query = $drop_routine . $sql_query;
|
||||
} else {
|
||||
$errors = array_merge($errors, $newErrors);
|
||||
}
|
||||
unset($newErrors);
|
||||
if (null === $message) {
|
||||
unset($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 'Add a new routine' mode
|
||||
$result = $GLOBALS['dbi']->tryQuery($routine_query);
|
||||
if (!$result) {
|
||||
$errors[] = sprintf(
|
||||
__('The following query has failed: "%s"'),
|
||||
htmlspecialchars($routine_query)
|
||||
)
|
||||
. '<br /><br />'
|
||||
. __('MySQL said: ') . $GLOBALS['dbi']->getError(null);
|
||||
} else {
|
||||
$message = PMA_Message::success(
|
||||
__('Routine %1$s has been created.')
|
||||
);
|
||||
$message->addParam(
|
||||
PMA_Util::backquote($_REQUEST['item_name'])
|
||||
);
|
||||
$sql_query = $routine_query;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($errors)) {
|
||||
$message = PMA_Message::error(
|
||||
__(
|
||||
'One or more errors have occurred while'
|
||||
. ' processing your request:'
|
||||
)
|
||||
);
|
||||
$message->addString('<ul>');
|
||||
foreach ($errors as $string) {
|
||||
$message->addString('<li>' . $string . '</li>');
|
||||
}
|
||||
$message->addString('</ul>');
|
||||
}
|
||||
|
||||
$output = PMA_Util::getMessage($message, $sql_query);
|
||||
if (!$GLOBALS['is_ajax_request']) {
|
||||
return $errors;
|
||||
}
|
||||
|
||||
$response = PMA_Response::getInstance();
|
||||
if (!$message->isSuccess()) {
|
||||
$response->isSuccess(false);
|
||||
$response->addJSON('message', $output);
|
||||
exit;
|
||||
}
|
||||
|
||||
$routines = $GLOBALS['dbi']->getRoutines(
|
||||
$db,
|
||||
$_REQUEST['item_type'],
|
||||
$_REQUEST['item_name']
|
||||
);
|
||||
$routine = $routines[0];
|
||||
$response->addJSON(
|
||||
'name',
|
||||
htmlspecialchars(
|
||||
/*overload*/
|
||||
mb_strtoupper($_REQUEST['item_name'])
|
||||
)
|
||||
);
|
||||
$response->addJSON('new_row', PMA_RTN_getRowForList($routine));
|
||||
$response->addJSON('insert', !empty($routine));
|
||||
$response->addJSON('message', $output);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backup the privileges
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function PMA_RTN_backupPrivileges()
|
||||
{
|
||||
if (defined('PMA_DRIZZLE') && PMA_DRIZZLE) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if (!(isset($GLOBALS['proc_priv']) && $GLOBALS['proc_priv']
|
||||
&& isset($GLOBALS['flush_priv'])
|
||||
&& $GLOBALS['flush_priv'])
|
||||
) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// Backup the Old Privileges before dropping
|
||||
// if $_REQUEST['item_adjust_privileges'] set
|
||||
if (!isset($_REQUEST['item_adjust_privileges'])
|
||||
|| empty($_REQUEST['item_adjust_privileges'])
|
||||
) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$privilegesBackupQuery = 'SELECT * FROM ' . PMA_Util::backquote(
|
||||
'mysql'
|
||||
)
|
||||
. '.' . PMA_Util::backquote('procs_priv')
|
||||
. ' where Routine_name = "' . $_REQUEST['item_original_name']
|
||||
. '" AND Routine_type = "' . $_REQUEST['item_original_type']
|
||||
. '";';
|
||||
|
||||
$privilegesBackup = $GLOBALS['dbi']->fetchResult(
|
||||
$privilegesBackupQuery,
|
||||
0
|
||||
);
|
||||
|
||||
return $privilegesBackup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the routine
|
||||
*
|
||||
* @param string $routine_query Query to create routine
|
||||
* @param string $create_routine Query to restore routine
|
||||
* @param array $privilegesBackup Privileges backup
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function PMA_RTN_createRoutine(
|
||||
$routine_query,
|
||||
$create_routine,
|
||||
$privilegesBackup
|
||||
) {
|
||||
$result = $GLOBALS['dbi']->tryQuery($routine_query);
|
||||
if (!$result) {
|
||||
$errors = array();
|
||||
$errors[] = sprintf(
|
||||
__('The following query has failed: "%s"'),
|
||||
htmlspecialchars($routine_query)
|
||||
)
|
||||
. '<br />'
|
||||
. __('MySQL said: ') . $GLOBALS['dbi']->getError(null);
|
||||
// We dropped the old routine,
|
||||
// but were unable to create the new one
|
||||
// Try to restore the backup query
|
||||
$result = $GLOBALS['dbi']->tryQuery($create_routine);
|
||||
$errors = checkResult(
|
||||
$result,
|
||||
__(
|
||||
'Sorry, we failed to restore'
|
||||
. ' the dropped routine.'
|
||||
),
|
||||
$create_routine,
|
||||
$errors
|
||||
);
|
||||
|
||||
return array($errors, null);
|
||||
}
|
||||
|
||||
// Default value
|
||||
$resultAdjust = false;
|
||||
|
||||
if (!defined('PMA_DRIZZLE') || !PMA_DRIZZLE) {
|
||||
if (isset($GLOBALS['proc_priv']) && $GLOBALS['proc_priv']
|
||||
&& isset($GLOBALS['flush_priv'])
|
||||
&& $GLOBALS['flush_priv']
|
||||
) {
|
||||
// Insert all the previous privileges
|
||||
// but with the new name and the new type
|
||||
foreach ($privilegesBackup as $priv) {
|
||||
$adjustProcPrivilege = 'INSERT INTO '
|
||||
. PMA_Util::backquote('mysql') . '.'
|
||||
. PMA_Util::backquote('procs_priv')
|
||||
. ' VALUES("' . $priv[0] . '", "'
|
||||
. $priv[1] . '", "' . $priv[2] . '", "'
|
||||
. $_REQUEST['item_name'] . '", "'
|
||||
. $_REQUEST['item_type'] . '", "'
|
||||
. $priv[5] . '", "'
|
||||
. $priv[6] . '", "'
|
||||
. $priv[7] . '");';
|
||||
$resultAdjust = $GLOBALS['dbi']->query(
|
||||
$adjustProcPrivilege
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$message = PMA_RTN_flushPrivileges($resultAdjust);
|
||||
|
||||
return array(array(), $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush privileges and get message
|
||||
*
|
||||
* @param bool $flushPrivileges Flush privileges
|
||||
*
|
||||
* @return PMA_Message
|
||||
*/
|
||||
function PMA_RTN_flushPrivileges($flushPrivileges)
|
||||
{
|
||||
if ($flushPrivileges) {
|
||||
// Flush the Privileges
|
||||
$flushPrivQuery = 'FLUSH PRIVILEGES;';
|
||||
$GLOBALS['dbi']->query($flushPrivQuery);
|
||||
|
||||
$message = PMA_Message::success(
|
||||
__(
|
||||
'Routine %1$s has been modified. Privileges have been adjusted.'
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$message = PMA_Message::success(
|
||||
__('Routine %1$s has been modified.')
|
||||
);
|
||||
}
|
||||
$message->addParam(
|
||||
PMA_Util::backquote($_REQUEST['item_name'])
|
||||
);
|
||||
|
||||
return $message;
|
||||
} // end PMA_RTN_handleEditor()
|
||||
|
||||
/**
|
||||
|
||||
@ -358,13 +358,24 @@ function PMA_getHtmlForNoticeEnableStatistics($url_query, $html)
|
||||
. 'heavy traffic between the web server and the MySQL server.'
|
||||
)
|
||||
)->getDisplay();
|
||||
$html = $html . $notice;
|
||||
$html .= '<ul><li id="li_switch_dbstats"><strong>' . "\n";
|
||||
$html .= '<a href="server_databases.php' . $url_query . '&dbstats=1"'
|
||||
. ' title="' . __('Enable Statistics') . '">' . "\n"
|
||||
. ' ' . __('Enable Statistics');
|
||||
$html .= '</a></strong><br />' . "\n";
|
||||
$html .= '</li>' . "\n" . '</ul>' . "\n";
|
||||
$html .= $notice;
|
||||
|
||||
$items = array();
|
||||
$items[] = array(
|
||||
'content' => '<strong>' . "\n"
|
||||
. __('Enable Statistics')
|
||||
. '</strong><br />' . "\n",
|
||||
'class' => 'li_switch_dbstats',
|
||||
'url' => array(
|
||||
'href' => 'server_databases.php' . $url_query . '&dbstats=1',
|
||||
'title' => __('Enable Statistics')
|
||||
),
|
||||
);
|
||||
|
||||
include_once './libraries/Template.class.php';
|
||||
$html .= PMA\Template::get('list/unordered')->render(
|
||||
array('items' => $items,)
|
||||
);
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
@ -30,6 +30,13 @@ function PMA_getHtmlForServerStatus($ServerStatusData)
|
||||
//display the server state connection information
|
||||
$retval .= PMA_getHtmlForServerStateConnections($ServerStatusData);
|
||||
|
||||
// display replication information
|
||||
if ($GLOBALS['replication_info']['master']['status']
|
||||
|| $GLOBALS['replication_info']['slave']['status']
|
||||
) {
|
||||
$retval .= PMA_getHtmlForReplicationInfo();
|
||||
}
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
@ -69,48 +76,50 @@ function PMA_getHtmlForServerStateGeneralInfo($ServerStatusData)
|
||||
) . "\n";
|
||||
$retval .= '</p>';
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns HTML to display replication information
|
||||
*
|
||||
* @return string HTML on replication
|
||||
*/
|
||||
function PMA_getHtmlForReplicationInfo()
|
||||
{
|
||||
$retval = '<p class="notice clearfloat">';
|
||||
if ($GLOBALS['replication_info']['master']['status']
|
||||
|| $GLOBALS['replication_info']['slave']['status']
|
||||
&& $GLOBALS['replication_info']['slave']['status']
|
||||
) {
|
||||
$retval .= '<p class="notice">';
|
||||
if ($GLOBALS['replication_info']['master']['status']
|
||||
&& $GLOBALS['replication_info']['slave']['status']
|
||||
) {
|
||||
$retval .= __(
|
||||
'This MySQL server works as <b>master</b> and '
|
||||
. '<b>slave</b> in <b>replication</b> process.'
|
||||
);
|
||||
} elseif ($GLOBALS['replication_info']['master']['status']) {
|
||||
$retval .= __(
|
||||
'This MySQL server works as <b>master</b> '
|
||||
. 'in <b>replication</b> process.'
|
||||
);
|
||||
} elseif ($GLOBALS['replication_info']['slave']['status']) {
|
||||
$retval .= __(
|
||||
'This MySQL server works as <b>slave</b> '
|
||||
. 'in <b>replication</b> process.'
|
||||
);
|
||||
}
|
||||
$retval .= '</p>';
|
||||
$retval .= __(
|
||||
'This MySQL server works as <b>master</b> and '
|
||||
. '<b>slave</b> in <b>replication</b> process.'
|
||||
);
|
||||
} elseif ($GLOBALS['replication_info']['master']['status']) {
|
||||
$retval .= __(
|
||||
'This MySQL server works as <b>master</b> '
|
||||
. 'in <b>replication</b> process.'
|
||||
);
|
||||
} elseif ($GLOBALS['replication_info']['slave']['status']) {
|
||||
$retval .= __(
|
||||
'This MySQL server works as <b>slave</b> '
|
||||
. 'in <b>replication</b> process.'
|
||||
);
|
||||
}
|
||||
$retval .= '</p>';
|
||||
|
||||
/*
|
||||
* if the server works as master or slave in replication process,
|
||||
* display useful information
|
||||
*/
|
||||
if ($GLOBALS['replication_info']['master']['status']
|
||||
|| $GLOBALS['replication_info']['slave']['status']
|
||||
) {
|
||||
$retval .= '<hr class="clearfloat" />';
|
||||
$retval .= '<h3><a name="replication">';
|
||||
$retval .= __('Replication status');
|
||||
$retval .= '</a></h3>';
|
||||
foreach ($GLOBALS['replication_types'] as $type) {
|
||||
if (isset($GLOBALS['replication_info'][$type]['status'])
|
||||
&& $GLOBALS['replication_info'][$type]['status']
|
||||
) {
|
||||
$retval .= PMA_getHtmlForReplicationStatusTable($type);
|
||||
}
|
||||
$retval .= '<hr class="clearfloat" />';
|
||||
$retval .= '<h3><a name="replication">';
|
||||
$retval .= __('Replication status');
|
||||
$retval .= '</a></h3>';
|
||||
foreach ($GLOBALS['replication_types'] as $type) {
|
||||
if (isset($GLOBALS['replication_info'][$type]['status'])
|
||||
&& $GLOBALS['replication_info'][$type]['status']
|
||||
) {
|
||||
$retval .= PMA_getHtmlForReplicationStatusTable($type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -70,12 +70,13 @@ namespace SqlParser {
|
||||
* `static::parse`.
|
||||
*
|
||||
* @param mixed $component The component to be built.
|
||||
* @param array $options Parameters for building.
|
||||
*
|
||||
* @throws \Exception Not implemented yet.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function build($component)
|
||||
public static function build($component, array $options = array())
|
||||
{
|
||||
// This method should be abstract, but it can't be both static and
|
||||
// abstract.
|
||||
|
||||
@ -31,47 +31,55 @@ class AlterOperation extends Component
|
||||
* @var array
|
||||
*/
|
||||
public static $OPTIONS = array(
|
||||
'ADD' => 3,
|
||||
'ALTER' => 3,
|
||||
'ANALYZE' => 3,
|
||||
'CHANGE' => 3,
|
||||
'CHECK' => 3,
|
||||
'COALESCE' => 3,
|
||||
'CONVERT' => 3,
|
||||
'DISABLE' => 3,
|
||||
'DISCARD' => 3,
|
||||
'DROP' => 3,
|
||||
'ENABLE' => 3,
|
||||
'IMPORT' => 3,
|
||||
'MODIFY' => 3,
|
||||
'OPTIMIZE' => 3,
|
||||
'ORDER' => 3,
|
||||
'PARTITION' => 3,
|
||||
'REBUILD' => 3,
|
||||
'REMOVE' => 3,
|
||||
'RENAME' => 3,
|
||||
'REORGANIZE' => 3,
|
||||
'REPAIR' => 3,
|
||||
|
||||
'COLUMN' => 4,
|
||||
'CONSTRAINT' => 4,
|
||||
'DEFAULT' => 4,
|
||||
'TO' => 4,
|
||||
'BY' => 4,
|
||||
'FOREIGN' => 4,
|
||||
'FULLTEXT' => 4,
|
||||
'KEY' => 4,
|
||||
'KEYS' => 4,
|
||||
'PARTITIONING' => 4,
|
||||
'PRIMARY KEY' => 4,
|
||||
'SPATIAL' => 4,
|
||||
'TABLESPACE' => 4,
|
||||
'INDEX' => 4,
|
||||
// table_options
|
||||
'ENGINE' => array(1, 'var='),
|
||||
'AUTO_INCREMENT' => array(1, 'var='),
|
||||
'AVG_ROW_LENGTH' => array(1, 'var'),
|
||||
'MAX_ROWS' => array(1, 'var'),
|
||||
'ROW_FORMAT' => array(1, 'var'),
|
||||
|
||||
'DEFAULT CHARACTER SET' => array(5, 'var'),
|
||||
'DEFAULT CHARSET' => array(5, 'var'),
|
||||
'ADD' => 1,
|
||||
'ALTER' => 1,
|
||||
'ANALYZE' => 1,
|
||||
'CHANGE' => 1,
|
||||
'CHECK' => 1,
|
||||
'COALESCE' => 1,
|
||||
'CONVERT' => 1,
|
||||
'DISABLE' => 1,
|
||||
'DISCARD' => 1,
|
||||
'DROP' => 1,
|
||||
'ENABLE' => 1,
|
||||
'IMPORT' => 1,
|
||||
'MODIFY' => 1,
|
||||
'OPTIMIZE' => 1,
|
||||
'ORDER' => 1,
|
||||
'PARTITION' => 1,
|
||||
'REBUILD' => 1,
|
||||
'REMOVE' => 1,
|
||||
'RENAME' => 1,
|
||||
'REORGANIZE' => 1,
|
||||
'REPAIR' => 1,
|
||||
|
||||
'COLLATE' => array(6, 'var'),
|
||||
'COLUMN' => 2,
|
||||
'CONSTRAINT' => 2,
|
||||
'DEFAULT' => 2,
|
||||
'TO' => 2,
|
||||
'BY' => 2,
|
||||
'FOREIGN' => 2,
|
||||
'FULLTEXT' => 2,
|
||||
'KEY' => 2,
|
||||
'KEYS' => 2,
|
||||
'PARTITIONING' => 2,
|
||||
'PRIMARY KEY' => 2,
|
||||
'SPATIAL' => 2,
|
||||
'TABLESPACE' => 2,
|
||||
'INDEX' => 2,
|
||||
|
||||
'DEFAULT CHARACTER SET' => array(3, 'var'),
|
||||
'DEFAULT CHARSET' => array(3, 'var'),
|
||||
|
||||
'COLLATE' => array(4, 'var'),
|
||||
);
|
||||
|
||||
/**
|
||||
@ -108,6 +116,7 @@ class AlterOperation extends Component
|
||||
|
||||
/**
|
||||
* Counts brackets.
|
||||
*
|
||||
* @var int $brackets
|
||||
*/
|
||||
$brackets = 0;
|
||||
@ -123,13 +132,15 @@ class AlterOperation extends Component
|
||||
*
|
||||
* 2 -------------------------[ , ]-----------------------> 0
|
||||
*
|
||||
* @var int
|
||||
* @var int $state
|
||||
*/
|
||||
$state = 0;
|
||||
|
||||
for (; $list->idx < $list->count; ++$list->idx) {
|
||||
|
||||
/**
|
||||
* Token parsed at this moment.
|
||||
*
|
||||
* @var Token $token
|
||||
*/
|
||||
$token = $list->tokens[$list->idx];
|
||||
@ -191,7 +202,6 @@ class AlterOperation extends Component
|
||||
__('Unrecognized alter operation.'),
|
||||
$list->tokens[$list->idx]
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
--$list->idx;
|
||||
@ -200,14 +210,15 @@ class AlterOperation extends Component
|
||||
|
||||
/**
|
||||
* @param AlterOperation $component The component to be built.
|
||||
* @param array $options Parameters for building.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function build($component)
|
||||
public static function build($component, array $options = array())
|
||||
{
|
||||
$ret = OptionsArray::build($component->options) . ' ';
|
||||
if (!empty($component->field)) {
|
||||
$ret .= Expression::build($component->field) . ' ';
|
||||
$ret = $component->options . ' ';
|
||||
if ((isset($component->field)) && ($component->field !== '')) {
|
||||
$ret .= $component->field . ' ';
|
||||
}
|
||||
$ret .= TokensList::build($component->unknown);
|
||||
return $ret;
|
||||
|
||||
@ -38,7 +38,8 @@ class Array2d extends Component
|
||||
|
||||
/**
|
||||
* The number of values in each set.
|
||||
* @var int
|
||||
*
|
||||
* @var int $count
|
||||
*/
|
||||
$count = -1;
|
||||
|
||||
@ -47,18 +48,20 @@ class Array2d extends Component
|
||||
*
|
||||
* Below are the states of the parser.
|
||||
*
|
||||
* 0 ----------------------[ array ]---------------------> 1
|
||||
* 0 ----------------------[ array ]----------------------> 1
|
||||
*
|
||||
* 1 ------------------------[ , ]------------------------> 0
|
||||
* 1 -----------------------[ else ]----------------------> -1
|
||||
* 1 -----------------------[ else ]----------------------> (END)
|
||||
*
|
||||
* @var int
|
||||
* @var int $state
|
||||
*/
|
||||
$state = 0;
|
||||
|
||||
for (; $list->idx < $list->count; ++$list->idx) {
|
||||
|
||||
/**
|
||||
* Token parsed at this moment.
|
||||
*
|
||||
* @var Token $token
|
||||
*/
|
||||
$token = $list->tokens[$list->idx];
|
||||
@ -118,4 +121,15 @@ class Array2d extends Component
|
||||
--$list->idx;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ArrayObj[] $component The component to be built.
|
||||
* @param array $options Parameters for building.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function build($component, array $options = array())
|
||||
{
|
||||
return ArrayObj::build($component);
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,11 +56,11 @@ class ArrayObj extends Component
|
||||
* @param TokensList $list The list of tokens that are being parsed.
|
||||
* @param array $options Parameters for parsing.
|
||||
*
|
||||
* @return ArrayObj
|
||||
* @return mixed
|
||||
*/
|
||||
public static function parse(Parser $parser, TokensList $list, array $options = array())
|
||||
{
|
||||
$ret = new ArrayObj();
|
||||
$ret = empty($options['type']) ? new ArrayObj() : array();
|
||||
|
||||
/**
|
||||
* The state of the parser.
|
||||
@ -72,15 +72,17 @@ class ArrayObj extends Component
|
||||
* 1 ------------------[ array element ]-----------------> 2
|
||||
*
|
||||
* 2 ------------------------[ , ]-----------------------> 1
|
||||
* 2 ------------------------[ ) ]-----------------------> -1
|
||||
* 2 ------------------------[ ) ]-----------------------> (END)
|
||||
*
|
||||
* @var int
|
||||
* @var int $state
|
||||
*/
|
||||
$state = 0;
|
||||
|
||||
for (; $list->idx < $list->count; ++$list->idx) {
|
||||
|
||||
/**
|
||||
* Token parsed at this moment.
|
||||
*
|
||||
* @var Token $token
|
||||
*/
|
||||
$token = $list->tokens[$list->idx];
|
||||
@ -109,8 +111,16 @@ class ArrayObj extends Component
|
||||
// Empty array.
|
||||
break;
|
||||
}
|
||||
$ret->values[] = $token->value;
|
||||
$ret->raw[] = $token->token;
|
||||
if (empty($options['type'])) {
|
||||
$ret->values[] = $token->value;
|
||||
$ret->raw[] = $token->token;
|
||||
} else {
|
||||
$ret[] = $options['type']::parse(
|
||||
$parser,
|
||||
$list,
|
||||
empty($options['typeOptions']) ? array() : $options['typeOptions']
|
||||
);
|
||||
}
|
||||
$state = 2;
|
||||
} elseif ($state === 2) {
|
||||
if (($token->type !== Token::TYPE_OPERATOR) || (($token->value !== ',') && ($token->value !== ')'))) {
|
||||
@ -126,27 +136,25 @@ class ArrayObj extends Component
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ArrayObj $component The component to be built.
|
||||
* @param ArrayObj|ArrayObj[] $component The component to be built.
|
||||
* @param array $options Parameters for building.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function build($component)
|
||||
public static function build($component, array $options = array())
|
||||
{
|
||||
$values = array();
|
||||
if (!empty($component->raw)) {
|
||||
$values = $component->raw;
|
||||
if (is_array($component)) {
|
||||
return implode(', ', $component);
|
||||
} elseif (!empty($component->raw)) {
|
||||
return '(' . implode(', ', $component->raw) . ')';
|
||||
} else {
|
||||
foreach ($component->values as $value) {
|
||||
$values[] = $value;
|
||||
}
|
||||
return '(' . implode(', ', $component->values) . ')';
|
||||
}
|
||||
return '(' . implode(', ', $values) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,6 +95,7 @@ class Condition extends Component
|
||||
|
||||
/**
|
||||
* Counts brackets.
|
||||
*
|
||||
* @var int $brackets
|
||||
*/
|
||||
$brackets = 0;
|
||||
@ -104,7 +105,8 @@ class Condition extends Component
|
||||
* It is required to keep track of them because their structure contains
|
||||
* the keyword `AND`, which is also an operator that delimits
|
||||
* expressions.
|
||||
* @var bool
|
||||
*
|
||||
* @var bool $betweenBefore
|
||||
*/
|
||||
$betweenBefore = false;
|
||||
|
||||
@ -112,6 +114,7 @@ class Condition extends Component
|
||||
|
||||
/**
|
||||
* Token parsed at this moment.
|
||||
*
|
||||
* @var Token $token
|
||||
*/
|
||||
$token = $list->tokens[$list->idx];
|
||||
@ -194,15 +197,16 @@ class Condition extends Component
|
||||
|
||||
/**
|
||||
* @param Condition[] $component The component to be built.
|
||||
* @param array $options Parameters for building.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function build($component)
|
||||
public static function build($component, array $options = array())
|
||||
{
|
||||
$ret = array();
|
||||
foreach ($component as $c) {
|
||||
$ret[] = $c->expr;
|
||||
if (is_array($component)) {
|
||||
return implode(' ', $component);
|
||||
} else {
|
||||
return $component->expr;
|
||||
}
|
||||
return implode(' ', $ret);
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,13 +173,15 @@ class CreateDefinition extends Component
|
||||
* 5 ------------------------[ , ]-----------------------> 1
|
||||
* 5 ------------------------[ ) ]-----------------------> 6 (-1)
|
||||
*
|
||||
* @var int
|
||||
* @var int $state
|
||||
*/
|
||||
$state = 0;
|
||||
|
||||
for (; $list->idx < $list->count; ++$list->idx) {
|
||||
|
||||
/**
|
||||
* Token parsed at this moment.
|
||||
*
|
||||
* @var Token $token
|
||||
*/
|
||||
$token = $list->tokens[$list->idx];
|
||||
@ -270,17 +272,14 @@ class CreateDefinition extends Component
|
||||
|
||||
/**
|
||||
* @param CreateDefinition|CreateDefinition[] $component The component to be built.
|
||||
* @param array $options Parameters for building.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function build($component)
|
||||
public static function build($component, array $options = array())
|
||||
{
|
||||
if (is_array($component)) {
|
||||
$ret = array();
|
||||
foreach ($component as $c) {
|
||||
$ret[] = static::build($c);
|
||||
}
|
||||
return "(\n" . implode(",\n", $ret) . "\n)";
|
||||
return "(\n " . implode(",\n ", $component) . "\n)";
|
||||
} else {
|
||||
$tmp = '';
|
||||
|
||||
@ -288,23 +287,26 @@ class CreateDefinition extends Component
|
||||
$tmp .= 'CONSTRAINT ';
|
||||
}
|
||||
|
||||
if (!empty($component->name)) {
|
||||
if ((isset($component->name)) && ($component->name !== '')) {
|
||||
$tmp .= Context::escape($component->name) . ' ';
|
||||
}
|
||||
|
||||
if (!empty($component->type)) {
|
||||
$tmp .= DataType::build($component->type) . ' ';
|
||||
$tmp .= DataType::build(
|
||||
$component->type,
|
||||
array('lowercase' => true)
|
||||
) . ' ';
|
||||
}
|
||||
|
||||
if (!empty($component->key)) {
|
||||
$tmp .= Key::build($component->key) . ' ';
|
||||
$tmp .= $component->key . ' ';
|
||||
}
|
||||
|
||||
if (!empty($component->references)) {
|
||||
$tmp .= 'REFERENCES ' . Reference::build($component->references) . ' ';
|
||||
$tmp .= 'REFERENCES ' . $component->references . ' ';
|
||||
}
|
||||
|
||||
$tmp .= OptionsArray::build($component->options);
|
||||
$tmp .= $component->options;
|
||||
|
||||
return trim($tmp);
|
||||
}
|
||||
|
||||
@ -103,13 +103,15 @@ class DataType extends Component
|
||||
*
|
||||
* 1 ----------------[ size and options ]----------------> 2
|
||||
*
|
||||
* @var int
|
||||
* @var int $state
|
||||
*/
|
||||
$state = 0;
|
||||
|
||||
for (; $list->idx < $list->count; ++$list->idx) {
|
||||
|
||||
/**
|
||||
* Token parsed at this moment.
|
||||
*
|
||||
* @var Token $token
|
||||
*/
|
||||
$token = $list->tokens[$list->idx];
|
||||
@ -149,18 +151,20 @@ class DataType extends Component
|
||||
|
||||
/**
|
||||
* @param DataType $component The component to be built.
|
||||
* @param array $options Parameters for building.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function build($component)
|
||||
public static function build($component, array $options = array())
|
||||
{
|
||||
$tmp = '';
|
||||
$name = (empty($options['lowercase'])) ?
|
||||
$component->name : strtolower($component->name);
|
||||
|
||||
$parameters = '';
|
||||
if (!empty($component->parameters)) {
|
||||
$tmp = '(' . implode(', ', $component->parameters) . ')';
|
||||
$parameters = '(' . implode(',', $component->parameters) . ')';
|
||||
}
|
||||
return trim(
|
||||
$component->name . $tmp . ' '
|
||||
. OptionsArray::build($component->options)
|
||||
);
|
||||
|
||||
return trim($name . $parameters . ' ' . $component->options);
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,24 +122,28 @@ class Expression extends Component
|
||||
|
||||
/**
|
||||
* Whether current tokens make an expression or a table reference.
|
||||
*
|
||||
* @var bool $isExpr
|
||||
*/
|
||||
$isExpr = false;
|
||||
|
||||
/**
|
||||
* Whether a period was previously found.
|
||||
*
|
||||
* @var bool $dot
|
||||
*/
|
||||
$dot = false;
|
||||
|
||||
/**
|
||||
* Whether an alias is expected. Is 2 if `AS` keyword was found.
|
||||
*
|
||||
* @var int $alias
|
||||
*/
|
||||
$alias = 0;
|
||||
|
||||
/**
|
||||
* Counts brackets.
|
||||
*
|
||||
* @var int $brackets
|
||||
*/
|
||||
$brackets = 0;
|
||||
@ -150,13 +154,16 @@ class Expression extends Component
|
||||
* string, if function was previously found;
|
||||
* true, if opening bracket was previously found;
|
||||
* null, in any other case.
|
||||
*
|
||||
* @var string|bool $prev
|
||||
*/
|
||||
$prev = null;
|
||||
|
||||
for (; $list->idx < $list->count; ++$list->idx) {
|
||||
|
||||
/**
|
||||
* Token parsed at this moment.
|
||||
*
|
||||
* @var Token $token
|
||||
*/
|
||||
$token = $list->tokens[$list->idx];
|
||||
@ -343,32 +350,37 @@ class Expression extends Component
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Expression $component The component to be built.
|
||||
* @param Expression|Expression[] $component The component to be built.
|
||||
* @param array $options Parameters for building.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function build($component)
|
||||
public static function build($component, array $options = array())
|
||||
{
|
||||
if (!empty($component->expr)) {
|
||||
$ret = $component->expr;
|
||||
if (is_array($component)) {
|
||||
return implode($component, ', ');
|
||||
} else {
|
||||
$fields = array();
|
||||
if (!empty($component->database)) {
|
||||
$fields[] = $component->database;
|
||||
if (!empty($component->expr)) {
|
||||
$ret = $component->expr;
|
||||
} else {
|
||||
$fields = array();
|
||||
if ((isset($component->database)) && ($component->database !== '')) {
|
||||
$fields[] = $component->database;
|
||||
}
|
||||
if ((isset($component->table)) && ($component->table !== '')) {
|
||||
$fields[] = $component->table;
|
||||
}
|
||||
if ((isset($component->column)) && ($component->column !== '')) {
|
||||
$fields[] = $component->column;
|
||||
}
|
||||
$ret = implode('.', Context::escape($fields));
|
||||
}
|
||||
if (!empty($component->table)) {
|
||||
$fields[] = $component->table;
|
||||
}
|
||||
if (!empty($component->column)) {
|
||||
$fields[] = $component->column;
|
||||
}
|
||||
$ret = implode('.', Context::escape($fields));
|
||||
}
|
||||
|
||||
if (!empty($component->alias)) {
|
||||
$ret .= ' AS ' . Context::escape($component->alias);
|
||||
}
|
||||
if (!empty($component->alias)) {
|
||||
$ret .= ' AS ' . Context::escape($component->alias);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Parses a a list of expression delimited by a comma.
|
||||
* Parses a a list of expressions delimited by a comma.
|
||||
*
|
||||
* @package SqlParser
|
||||
* @subpackage Components
|
||||
@ -14,7 +14,7 @@ use SqlParser\Token;
|
||||
use SqlParser\TokensList;
|
||||
|
||||
/**
|
||||
* Parses a a list of expression delimited by a comma.
|
||||
* Parses a a list of expressions delimited by a comma.
|
||||
*
|
||||
* @category Keywords
|
||||
* @package SqlParser
|
||||
@ -44,15 +44,17 @@ class ExpressionArray extends Component
|
||||
* 0 ----------------------[ array ]---------------------> 1
|
||||
*
|
||||
* 1 ------------------------[ , ]------------------------> 0
|
||||
* 1 -----------------------[ else ]----------------------> -1
|
||||
* 1 -----------------------[ else ]----------------------> (END)
|
||||
*
|
||||
* @var int
|
||||
* @var int $state
|
||||
*/
|
||||
$state = 0;
|
||||
|
||||
for (; $list->idx < $list->count; ++$list->idx) {
|
||||
|
||||
/**
|
||||
* Token parsed at this moment.
|
||||
*
|
||||
* @var Token $token
|
||||
*/
|
||||
$token = $list->tokens[$list->idx];
|
||||
@ -104,10 +106,11 @@ class ExpressionArray extends Component
|
||||
|
||||
/**
|
||||
* @param Expression[] $component The component to be built.
|
||||
* @param array $options Parameters for building.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function build($component)
|
||||
public static function build($component, array $options = array())
|
||||
{
|
||||
$ret = array();
|
||||
foreach ($component as $frag) {
|
||||
|
||||
@ -73,15 +73,17 @@ class FunctionCall extends Component
|
||||
*
|
||||
* 0 ----------------------[ name ]-----------------------> 1
|
||||
*
|
||||
* 1 --------------------[ parameters ]-------------------> -1
|
||||
* 1 --------------------[ parameters ]-------------------> (END)
|
||||
*
|
||||
* @var int
|
||||
* @var int $state
|
||||
*/
|
||||
$state = 0;
|
||||
|
||||
for (; $list->idx < $list->count; ++$list->idx) {
|
||||
|
||||
/**
|
||||
* Token parsed at this moment.
|
||||
*
|
||||
* @var Token $token
|
||||
*/
|
||||
$token = $list->tokens[$list->idx];
|
||||
@ -113,11 +115,12 @@ class FunctionCall extends Component
|
||||
|
||||
/**
|
||||
* @param FunctionCall $component The component to be built.
|
||||
* @param array $options Parameters for building.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function build($component)
|
||||
public static function build($component, array $options = array())
|
||||
{
|
||||
return $component->name . ArrayObj::build($component->parameters);
|
||||
return $component->name . $component->parameters;
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,17 +65,19 @@ class IntoKeyword extends Component
|
||||
* 0 -----------------------[ name ]----------------------> 1
|
||||
* 0 ---------------------[ OUTFILE ]---------------------> 2
|
||||
*
|
||||
* 1 ------------------------[ ( ]------------------------> -1
|
||||
* 1 ------------------------[ ( ]------------------------> (END)
|
||||
*
|
||||
* 2 ---------------------[ filename ]--------------------> 1
|
||||
*
|
||||
* @var int
|
||||
* @var int $state
|
||||
*/
|
||||
$state = 0;
|
||||
|
||||
for (; $list->idx < $list->count; ++$list->idx) {
|
||||
|
||||
/**
|
||||
* Token parsed at this moment.
|
||||
*
|
||||
* @var Token $token
|
||||
*/
|
||||
$token = $list->tokens[$list->idx];
|
||||
@ -128,4 +130,21 @@ class IntoKeyword extends Component
|
||||
--$list->idx;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IntoKeyword $component The component to be built.
|
||||
* @param array $options Parameters for building.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function build($component, array $options = array())
|
||||
{
|
||||
if ($component->dest instanceof Expression) {
|
||||
$columns = !empty($component->columns) ?
|
||||
'(' . implode(', ', $component->columns) . ')' : '';
|
||||
return $component->dest . $columns;
|
||||
} else {
|
||||
return 'OUTFILE "' . $component->dest . '"';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ class JoinKeyword extends Component
|
||||
{
|
||||
$ret = array();
|
||||
|
||||
$expr = new JoinKeyword();;
|
||||
$expr = new JoinKeyword();
|
||||
|
||||
/**
|
||||
* The state of the parser.
|
||||
@ -86,7 +86,7 @@ class JoinKeyword extends Component
|
||||
*
|
||||
* 3 --------------------[ conditions ]-------------------> 0
|
||||
*
|
||||
* @var int
|
||||
* @var int $state
|
||||
*/
|
||||
$state = 0;
|
||||
|
||||
@ -98,8 +98,10 @@ class JoinKeyword extends Component
|
||||
}
|
||||
|
||||
for (; $list->idx < $list->count; ++$list->idx) {
|
||||
|
||||
/**
|
||||
* Token parsed at this moment.
|
||||
*
|
||||
* @var Token $token
|
||||
*/
|
||||
$token = $list->tokens[$list->idx];
|
||||
@ -149,15 +151,16 @@ class JoinKeyword extends Component
|
||||
|
||||
/**
|
||||
* @param JoinKeyword[] $component The component to be built.
|
||||
* @param array $options Parameters for building.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function build($component)
|
||||
public static function build($component, array $options = array())
|
||||
{
|
||||
$ret = array();
|
||||
foreach ($component as $c) {
|
||||
$ret[] = (($c->type === 'JOIN') ? 'JOIN ' : ($c->type . ' JOIN ')) .
|
||||
Expression::build($c->expr) . ' ON ' . Condition::build($c->on);
|
||||
$ret[] = (($c->type === 'JOIN') ? 'JOIN ' : ($c->type . ' JOIN '))
|
||||
. $c->expr . ' ON ' . Condition::build($c->on);
|
||||
}
|
||||
return implode(' ', $ret);
|
||||
}
|
||||
|
||||
@ -107,13 +107,15 @@ class Key extends Component
|
||||
*
|
||||
* 2 ---------------------[ options ]---------------------> 3
|
||||
*
|
||||
* @var int
|
||||
* @var int $state
|
||||
*/
|
||||
$state = 0;
|
||||
|
||||
for (; $list->idx < $list->count; ++$list->idx) {
|
||||
|
||||
/**
|
||||
* Token parsed at this moment.
|
||||
*
|
||||
* @var Token $token
|
||||
*/
|
||||
$token = $list->tokens[$list->idx];
|
||||
@ -143,7 +145,6 @@ class Key extends Component
|
||||
++$list->idx;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
--$list->idx;
|
||||
@ -151,18 +152,19 @@ class Key extends Component
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Key $component The component to be built.
|
||||
* @param Key $component The component to be built.
|
||||
* @param array $options Parameters for building.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function build($component)
|
||||
public static function build($component, array $options = array())
|
||||
{
|
||||
$ret = $component->type . ' ';
|
||||
if (!empty($component->name)) {
|
||||
$ret .= Context::escape($component->name) . ' ';
|
||||
}
|
||||
$ret .= '(' . implode(', ', Context::escape($component->columns)) . ')';
|
||||
$ret .= OptionsArray::build($component->options);
|
||||
$ret .= '(' . implode(',', Context::escape($component->columns)) . ') '
|
||||
. $component->options;
|
||||
return trim($ret);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user