Linux ip-172-31-33-47 5.4.0-1045-aws #47~18.04.1-Ubuntu SMP Tue Apr 13 15:58:14 UTC 2021 x86_64
Apache/2.4.29 (Ubuntu)
: 172.31.33.47 | : 18.188.192.62
Cant Read [ /etc/named.conf ]
7.4.20
www-data
www.github.com/MadExploits
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
CREATE RDP
PHP Mailer
BACKCONNECT
UNLOCK SHELL
HASH IDENTIFIER
CPANEL RESET
CREATE WP USER
README
+ Create Folder
+ Create File
/
var /
www /
html /
restaurants /
var /
phpmyadmin /
src /
[ HOME SHELL ]
Name
Size
Permission
Action
Advisory
[ DIR ]
drwxr-xr-x
Bookmarks
[ DIR ]
drwxr-xr-x
Charsets
[ DIR ]
drwxr-xr-x
Command
[ DIR ]
drwxr-xr-x
Config
[ DIR ]
drwxr-xr-x
ConfigStorage
[ DIR ]
drwxr-xr-x
Container
[ DIR ]
drwxr-xr-x
Controllers
[ DIR ]
drwxr-xr-x
Crypto
[ DIR ]
drwxr-xr-x
Database
[ DIR ]
drwxr-xr-x
Dbal
[ DIR ]
drwxr-xr-x
Display
[ DIR ]
drwxr-xr-x
Engines
[ DIR ]
drwxr-xr-x
Error
[ DIR ]
drwxr-xr-x
Exceptions
[ DIR ]
drwxr-xr-x
Export
[ DIR ]
drwxr-xr-x
Favorites
[ DIR ]
drwxr-xr-x
Gis
[ DIR ]
drwxr-xr-x
Html
[ DIR ]
drwxr-xr-x
Http
[ DIR ]
drwxr-xr-x
Identifiers
[ DIR ]
drwxr-xr-x
Image
[ DIR ]
drwxr-xr-x
Import
[ DIR ]
drwxr-xr-x
Navigation
[ DIR ]
drwxr-xr-x
Partitioning
[ DIR ]
drwxr-xr-x
Plugins
[ DIR ]
drwxr-xr-x
Properties
[ DIR ]
drwxr-xr-x
Providers
[ DIR ]
drwxr-xr-x
Query
[ DIR ]
drwxr-xr-x
Replication
[ DIR ]
drwxr-xr-x
Routing
[ DIR ]
drwxr-xr-x
Server
[ DIR ]
drwxr-xr-x
Setup
[ DIR ]
drwxr-xr-x
Table
[ DIR ]
drwxr-xr-x
Theme
[ DIR ]
drwxr-xr-x
Tracking
[ DIR ]
drwxr-xr-x
Triggers
[ DIR ]
drwxr-xr-x
Twig
[ DIR ]
drwxr-xr-x
Utils
[ DIR ]
drwxr-xr-x
WebAuthn
[ DIR ]
drwxr-xr-x
Application.php
6.31
KB
-rw-r--r--
BrowseForeigners.php
10.24
KB
-rw-r--r--
Cache.php
1.44
KB
-rw-r--r--
Charsets.php
7.08
KB
-rw-r--r--
Column.php
363
B
-rw-r--r--
ColumnFull.php
500
B
-rw-r--r--
Config.php
38.1
KB
-rw-r--r--
Console.php
3.14
KB
-rw-r--r--
Core.php
22.22
KB
-rw-r--r--
CreateAddField.php
14.6
KB
-rw-r--r--
Current.php
228
B
-rw-r--r--
DatabaseInterface.php
66.01
KB
-rw-r--r--
DbTableExists.php
1.4
KB
-rw-r--r--
EditField.php
495
B
-rw-r--r--
Encoding.php
7.97
KB
-rw-r--r--
FieldMetadata.php
10.64
KB
-rw-r--r--
File.php
19.72
KB
-rw-r--r--
FileListing.php
3.04
KB
-rw-r--r--
FlashMessages.php
1.23
KB
-rw-r--r--
Font.php
4.26
KB
-rw-r--r--
Footer.php
6.82
KB
-rw-r--r--
Git.php
18.5
KB
-rw-r--r--
Header.php
19.81
KB
-rw-r--r--
Index.php
14.45
KB
-rw-r--r--
IndexColumn.php
4.7
KB
-rw-r--r--
InsertEdit.php
73.25
KB
-rw-r--r--
InsertEditColumn.php
1.96
KB
-rw-r--r--
InternalRelations.php
17
KB
-rw-r--r--
IpAllowDeny.php
9
KB
-rw-r--r--
Language.php
4.12
KB
-rw-r--r--
LanguageManager.php
22.27
KB
-rw-r--r--
Linter.php
4.89
KB
-rw-r--r--
ListDatabase.php
4.93
KB
-rw-r--r--
Logging.php
2.79
KB
-rw-r--r--
Menu.php
19.9
KB
-rw-r--r--
Message.php
14.58
KB
-rw-r--r--
Mime.php
893
B
-rw-r--r--
Normalization.php
39.54
KB
-rw-r--r--
OpenDocument.php
8.78
KB
-rw-r--r--
Operations.php
34.63
KB
-rw-r--r--
ParseAnalyze.php
2.23
KB
-rw-r--r--
Pdf.php
3.89
KB
-rw-r--r--
Plugins.php
22.28
KB
-rw-r--r--
Profiling.php
2.17
KB
-rw-r--r--
Release.php
298
B
-rw-r--r--
ResponseRenderer.php
13.03
KB
-rw-r--r--
Sanitize.php
8.62
KB
-rw-r--r--
Scripts.php
3.7
KB
-rw-r--r--
Session.php
7.88
KB
-rw-r--r--
ShowGrants.php
2.06
KB
-rw-r--r--
Sql.php
60.06
KB
-rw-r--r--
SqlQueryForm.php
6.93
KB
-rw-r--r--
StorageEngine.php
15.08
KB
-rw-r--r--
SystemColumn.php
267
B
-rw-r--r--
SystemDatabase.php
4.62
KB
-rw-r--r--
Template.php
3.98
KB
-rw-r--r--
Transformations.php
17.2
KB
-rw-r--r--
TwoFactor.php
7.61
KB
-rw-r--r--
Types.php
23.88
KB
-rw-r--r--
UniqueCondition.php
8.26
KB
-rw-r--r--
Url.php
10.54
KB
-rw-r--r--
UrlRedirector.php
1.43
KB
-rw-r--r--
UserPassword.php
8.25
KB
-rw-r--r--
UserPreferences.php
10.22
KB
-rw-r--r--
UserPrivileges.php
520
B
-rw-r--r--
UserPrivilegesFactory.php
8.61
KB
-rw-r--r--
Util.php
68.74
KB
-rw-r--r--
Version.php
554
B
-rw-r--r--
VersionInformation.php
7.18
KB
-rw-r--r--
ZipExtension.php
10.01
KB
-rw-r--r--
Delete
Unzip
Zip
${this.title}
Close
Code Editor : Operations.php
<?php declare(strict_types=1); namespace PhpMyAdmin; use PhpMyAdmin\ConfigStorage\Relation; use PhpMyAdmin\Database\Events; use PhpMyAdmin\Database\Routines; use PhpMyAdmin\Engines\Innodb; use PhpMyAdmin\Identifiers\DatabaseName; use PhpMyAdmin\Partitioning\Partition; use PhpMyAdmin\Plugins\Export\ExportSql; use PhpMyAdmin\Table\Table; use PhpMyAdmin\Triggers\Triggers; use function __; use function array_merge; use function count; use function explode; use function in_array; use function is_scalar; use function is_string; use function mb_strtolower; use function str_replace; use function strtolower; use function urldecode; /** * Set of functions with the operations section in phpMyAdmin */ class Operations { public function __construct(private DatabaseInterface $dbi, private Relation $relation) { } /** * Run the Procedure definitions and function definitions * * to avoid selecting alternatively the current and new db * we would need to modify the CREATE definitions to qualify * the db name * * @param string $db database name */ public function runProcedureAndFunctionDefinitions(string $db, DatabaseName $newDatabaseName): void { foreach (Routines::getProcedureNames($this->dbi, $db) as $procedureName) { $this->dbi->selectDb($db); $query = Routines::getProcedureDefinition($this->dbi, $db, $procedureName); if ($query === null) { continue; } // collect for later display $GLOBALS['sql_query'] .= "\n" . $query; $this->dbi->selectDb($newDatabaseName); $this->dbi->query($query); } foreach (Routines::getFunctionNames($this->dbi, $db) as $functionName) { $this->dbi->selectDb($db); $query = Routines::getFunctionDefinition($this->dbi, $db, $functionName); if ($query === null) { continue; } // collect for later display $GLOBALS['sql_query'] .= "\n" . $query; $this->dbi->selectDb($newDatabaseName); $this->dbi->query($query); } } /** * Create database before copy */ public function createDbBeforeCopy(UserPrivileges $userPrivileges, DatabaseName $newDatabaseName): void { $localQuery = 'CREATE DATABASE IF NOT EXISTS ' . Util::backquote($newDatabaseName); if (isset($_POST['db_collation'])) { $localQuery .= ' DEFAULT' . Util::getCharsetQueryPart($_POST['db_collation']); } $localQuery .= ';'; $GLOBALS['sql_query'] .= $localQuery; // save the original db name because Tracker.php which // may be called under $this->dbi->query() changes \PhpMyAdmin\Current::$database // for some statements, one of which being CREATE DATABASE $originalDb = Current::$database; $this->dbi->query($localQuery); Current::$database = $originalDb; // Set the SQL mode to NO_AUTO_VALUE_ON_ZERO to prevent MySQL from creating // export statements it cannot import $sqlSetMode = "SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO'"; $this->dbi->query($sqlSetMode); // rebuild the database list because Table::moveCopy // checks in this list if the target db exists $this->dbi->getDatabaseList()->build($userPrivileges); } /** * Get views as an array and create SQL view stand-in * * @param string[] $tables array of all tables in given db or dbs * @param ExportSql $exportSqlPlugin export plugin instance * @param string $db database name * * @return string[] */ public function getViewsAndCreateSqlViewStandIn( array $tables, ExportSql $exportSqlPlugin, string $db, DatabaseName $newDatabaseName, ): array { $views = []; foreach ($tables as $table) { // to be able to rename a db containing views, // first all the views are collected and a stand-in is created // the real views are created after the tables if (! $this->dbi->getTable($db, $table)->isView()) { continue; } // If view exists, and 'add drop view' is selected: Drop it! if ($_POST['what'] !== 'nocopy' && isset($_POST['drop_if_exists']) && $_POST['drop_if_exists'] === 'true') { $dropQuery = 'DROP VIEW IF EXISTS ' . Util::backquote($newDatabaseName) . '.' . Util::backquote($table); $this->dbi->query($dropQuery); $GLOBALS['sql_query'] .= "\n" . $dropQuery . ';'; } $views[] = $table; // Create stand-in definition to resolve view dependencies $sqlViewStandin = $exportSqlPlugin->getTableDefStandIn($db, $table); $this->dbi->selectDb($newDatabaseName); $this->dbi->query($sqlViewStandin); $GLOBALS['sql_query'] .= "\n" . $sqlViewStandin; } return $views; } /** * Get sql query for copy/rename table and boolean for whether copy/rename or not * * @param string[] $tables array of all tables in given db or dbs * @param bool $move whether database name is empty or not * @param string $db database name * * @return mixed[] SQL queries for the constraints */ public function copyTables(array $tables, bool $move, string $db, DatabaseName $newDatabaseName): array { $sqlContraints = []; foreach ($tables as $table) { // skip the views; we have created stand-in definitions if ($this->dbi->getTable($db, $table)->isView()) { continue; } // value of $what for this table only $copyMode = $_POST['what']; // do not copy the data from a Merge table // note: on the calling FORM, 'data' means 'structure and data' if ($this->dbi->getTable($db, $table)->isMerge()) { if ($copyMode === 'data') { $copyMode = 'structure'; } if ($copyMode === 'dataonly') { $copyMode = 'nocopy'; } } if ($copyMode === 'nocopy') { continue; } // keep the triggers from the original db+table // (third param is empty because delimiters are only intended // for importing via the mysql client or our Import feature) $triggers = Triggers::getDetails($this->dbi, $db, $table); if ( ! Table::moveCopy( $db, $table, $newDatabaseName->getName(), $table, $copyMode ?? 'data', $move, 'db_copy', isset($_POST['drop_if_exists']) && $_POST['drop_if_exists'] === 'true', ) ) { $GLOBALS['_error'] = true; break; } // apply the triggers to the destination db+table if ($triggers !== []) { $this->dbi->selectDb($newDatabaseName); foreach ($triggers as $trigger) { $createSqlQuery = $trigger->getCreateSql(''); $this->dbi->query($createSqlQuery); $GLOBALS['sql_query'] .= "\n" . $createSqlQuery . ';'; } } // this does not apply to a rename operation if (! isset($_POST['add_constraints']) || empty($GLOBALS['sql_constraints_query'])) { continue; } $sqlContraints[] = $GLOBALS['sql_constraints_query']; unset($GLOBALS['sql_constraints_query']); } return $sqlContraints; } /** * Run the EVENT definition for selected database * * to avoid selecting alternatively the current and new db * we would need to modify the CREATE definitions to qualify * the db name * * @param string $db database name */ public function runEventDefinitionsForDb(string $db, DatabaseName $newDatabaseName): void { /** @var string[] $eventNames */ $eventNames = $this->dbi->fetchResult( 'SELECT EVENT_NAME FROM information_schema.EVENTS WHERE EVENT_SCHEMA= ' . $this->dbi->quoteString($db) . ';', ); foreach ($eventNames as $eventName) { $this->dbi->selectDb($db); $query = Events::getDefinition($this->dbi, $db, $eventName); // collect for later display $GLOBALS['sql_query'] .= "\n" . $query; $this->dbi->selectDb($newDatabaseName); $this->dbi->query($query); } } /** * Handle the views, return the boolean value whether table rename/copy or not * * @param string[] $views views as an array * @param bool $move whether database name is empty or not * @param string $db database name */ public function handleTheViews(array $views, bool $move, string $db, DatabaseName $newDatabaseName): void { // Add DROP IF EXIST to CREATE VIEW query, to remove stand-in VIEW that was created earlier. foreach ($views as $view) { $copyingSucceeded = Table::moveCopy( $db, $view, $newDatabaseName->getName(), $view, 'structure', $move, 'db_copy', true, ); if (! $copyingSucceeded) { $GLOBALS['_error'] = true; break; } } } /** * Adjust the privileges after Renaming the db * * @param string $oldDb Database name before renaming */ public function adjustPrivilegesMoveDb( UserPrivileges $userPrivileges, string $oldDb, DatabaseName $newDatabaseName, ): void { if ( ! $userPrivileges->database || ! $userPrivileges->table || ! $userPrivileges->column || ! $userPrivileges->routines || ! $userPrivileges->isReload ) { return; } $this->dbi->selectDb('mysql'); $newName = str_replace('_', '\_', $newDatabaseName->getName()); $oldDb = str_replace('_', '\_', $oldDb); // For Db specific privileges $this->dbi->query('UPDATE ' . Util::backquote('db') . 'SET Db = ' . $this->dbi->quoteString($newName) . ' where Db = ' . $this->dbi->quoteString($oldDb) . ';'); // For table specific privileges $this->dbi->query('UPDATE ' . Util::backquote('tables_priv') . 'SET Db = ' . $this->dbi->quoteString($newName) . ' where Db = ' . $this->dbi->quoteString($oldDb) . ';'); // For column specific privileges $this->dbi->query('UPDATE ' . Util::backquote('columns_priv') . 'SET Db = ' . $this->dbi->quoteString($newName) . ' where Db = ' . $this->dbi->quoteString($oldDb) . ';'); // For procedures specific privileges $this->dbi->query('UPDATE ' . Util::backquote('procs_priv') . 'SET Db = ' . $this->dbi->quoteString($newName) . ' where Db = ' . $this->dbi->quoteString($oldDb) . ';'); // Finally FLUSH the new privileges $this->dbi->query('FLUSH PRIVILEGES;'); } /** * Adjust the privileges after Copying the db * * @param string $oldDb Database name before copying */ public function adjustPrivilegesCopyDb( UserPrivileges $userPrivileges, string $oldDb, DatabaseName $newDatabaseName, ): void { if ( ! $userPrivileges->database || ! $userPrivileges->table || ! $userPrivileges->column || ! $userPrivileges->routines || ! $userPrivileges->isReload ) { return; } $this->dbi->selectDb('mysql'); $newName = str_replace('_', '\_', $newDatabaseName->getName()); $oldDb = str_replace('_', '\_', $oldDb); $queryDbSpecificOld = 'SELECT * FROM ' . Util::backquote('db') . ' WHERE ' . 'Db = "' . $oldDb . '";'; $oldPrivsDb = $this->dbi->fetchResult($queryDbSpecificOld, 0); foreach ($oldPrivsDb as $oldPriv) { $newDbDbPrivsQuery = 'INSERT INTO ' . Util::backquote('db') . ' VALUES("' . $oldPriv[0] . '", "' . $newName . '"'; $privCount = count($oldPriv); for ($i = 2; $i < $privCount; $i++) { $newDbDbPrivsQuery .= ', "' . $oldPriv[$i] . '"'; } $newDbDbPrivsQuery .= ')'; $this->dbi->query($newDbDbPrivsQuery); } // For Table Specific privileges $queryTableSpecificOld = 'SELECT * FROM ' . Util::backquote('tables_priv') . ' WHERE ' . 'Db = "' . $oldDb . '";'; $oldPrivsTable = $this->dbi->fetchResult($queryTableSpecificOld, 0); foreach ($oldPrivsTable as $oldPriv) { $newDbTablePrivsQuery = 'INSERT INTO ' . Util::backquote( 'tables_priv', ) . ' VALUES("' . $oldPriv[0] . '", "' . $newName . '", "' . $oldPriv[2] . '", "' . $oldPriv[3] . '", "' . $oldPriv[4] . '", "' . $oldPriv[5] . '", "' . $oldPriv[6] . '", "' . $oldPriv[7] . '");'; $this->dbi->query($newDbTablePrivsQuery); } // For Column Specific privileges $queryColSpecificOld = 'SELECT * FROM ' . Util::backquote('columns_priv') . ' WHERE ' . 'Db = "' . $oldDb . '";'; $oldPrivsCol = $this->dbi->fetchResult($queryColSpecificOld, 0); foreach ($oldPrivsCol as $oldPriv) { $newDbColPrivsQuery = 'INSERT INTO ' . Util::backquote( 'columns_priv', ) . ' VALUES("' . $oldPriv[0] . '", "' . $newName . '", "' . $oldPriv[2] . '", "' . $oldPriv[3] . '", "' . $oldPriv[4] . '", "' . $oldPriv[5] . '", "' . $oldPriv[6] . '");'; $this->dbi->query($newDbColPrivsQuery); } // For Procedure Specific privileges $queryProcSpecificOld = 'SELECT * FROM ' . Util::backquote('procs_priv') . ' WHERE ' . 'Db = "' . $oldDb . '";'; $oldPrivsProc = $this->dbi->fetchResult($queryProcSpecificOld, 0); foreach ($oldPrivsProc as $oldPriv) { $newDbProcPrivsQuery = 'INSERT INTO ' . Util::backquote( 'procs_priv', ) . ' VALUES("' . $oldPriv[0] . '", "' . $newName . '", "' . $oldPriv[2] . '", "' . $oldPriv[3] . '", "' . $oldPriv[4] . '", "' . $oldPriv[5] . '", "' . $oldPriv[6] . '", "' . $oldPriv[7] . '");'; $this->dbi->query($newDbProcPrivsQuery); } // Finally FLUSH the new privileges $this->dbi->query('FLUSH PRIVILEGES;'); } /** * Create all accumulated constraints * * @param mixed[] $sqlConstraints array of sql constraints for the database */ public function createAllAccumulatedConstraints(array $sqlConstraints, DatabaseName $newDatabaseName): void { $this->dbi->selectDb($newDatabaseName); foreach ($sqlConstraints as $query) { $this->dbi->query($query); // and prepare to display them $GLOBALS['sql_query'] .= "\n" . $query; } } /** * Duplicate the bookmarks for the db (done once for each db) * * @param bool $error whether table rename/copy or not * @param string $db database name */ public function duplicateBookmarks(bool $error, string $db, DatabaseName $newDatabaseName): void { if ($error || $db === $newDatabaseName->getName()) { return; } $getFields = ['user', 'label', 'query']; $whereFields = ['dbase' => $db]; $newFields = ['dbase' => $newDatabaseName->getName()]; Table::duplicateInfo('bookmarkwork', 'bookmark', $getFields, $whereFields, $newFields); } /** * Get array of possible row formats * * @return string[][] */ public function getPossibleRowFormat(): array { // the outer array is for engines, the inner array contains the dropdown // option values as keys then the dropdown option labels $possibleRowFormats = [ 'ARCHIVE' => ['COMPRESSED' => 'COMPRESSED'], 'ARIA' => ['FIXED' => 'FIXED', 'DYNAMIC' => 'DYNAMIC', 'PAGE' => 'PAGE'], 'MARIA' => ['FIXED' => 'FIXED', 'DYNAMIC' => 'DYNAMIC', 'PAGE' => 'PAGE'], 'MYISAM' => ['FIXED' => 'FIXED', 'DYNAMIC' => 'DYNAMIC'], 'PBXT' => ['FIXED' => 'FIXED', 'DYNAMIC' => 'DYNAMIC'], 'INNODB' => ['COMPACT' => 'COMPACT', 'REDUNDANT' => 'REDUNDANT'], ]; /** @var Innodb $innodbEnginePlugin */ $innodbEnginePlugin = StorageEngine::getEngine('Innodb'); $innodbPluginVersion = $innodbEnginePlugin->getInnodbPluginVersion(); $innodbFileFormat = ''; if ($innodbPluginVersion !== '') { $innodbFileFormat = $innodbEnginePlugin->getInnodbFileFormat() ?? ''; } /** * Newer MySQL/MariaDB always return empty a.k.a '' on $innodbFileFormat otherwise * old versions of MySQL/MariaDB must be returning something or not empty. * This patch is to support newer MySQL/MariaDB while also for backward compatibilities. */ if ( (strtolower($innodbFileFormat) === 'barracuda') || ($innodbFileFormat == '') && $innodbEnginePlugin->supportsFilePerTable() ) { $possibleRowFormats['INNODB']['DYNAMIC'] = 'DYNAMIC'; $possibleRowFormats['INNODB']['COMPRESSED'] = 'COMPRESSED'; } return $possibleRowFormats; } /** @return array<string, string> */ public function getPartitionMaintenanceChoices(): array { $choices = [ 'ANALYZE' => __('Analyze'), 'CHECK' => __('Check'), 'OPTIMIZE' => __('Optimize'), 'REBUILD' => __('Rebuild'), 'REPAIR' => __('Repair'), 'TRUNCATE' => __('Truncate'), ]; $partitionMethod = Partition::getPartitionMethod(Current::$database, Current::$table); // add COALESCE or DROP option to choices array depending on Partition method if ( $partitionMethod === 'RANGE' || $partitionMethod === 'RANGE COLUMNS' || $partitionMethod === 'LIST' || $partitionMethod === 'LIST COLUMNS' ) { $choices['DROP'] = __('Drop'); } else { $choices['COALESCE'] = __('Coalesce'); } return $choices; } /** * @param mixed[] $urlParams Array of url parameters. * @param bool $hasRelationFeature If relation feature is enabled. * * @return mixed[] */ public function getForeignersForReferentialIntegrityCheck( array $urlParams, bool $hasRelationFeature, ): array { if (! $hasRelationFeature) { return []; } $foreigners = []; $this->dbi->selectDb(Current::$database); $foreign = $this->relation->getForeigners(Current::$database, Current::$table, '', 'internal'); foreach ($foreign as $master => $arr) { $joinQuery = 'SELECT ' . Util::backquote(Current::$table) . '.*' . ' FROM ' . Util::backquote(Current::$table) . ' LEFT JOIN ' . Util::backquote($arr['foreign_db']) . '.' . Util::backquote($arr['foreign_table']); if ($arr['foreign_table'] == Current::$table) { $foreignTable = Current::$table . '1'; $joinQuery .= ' AS ' . Util::backquote($foreignTable); } else { $foreignTable = $arr['foreign_table']; } $joinQuery .= ' ON ' . Util::backquote(Current::$table) . '.' . Util::backquote($master) . ' = ' . Util::backquote($arr['foreign_db']) . '.' . Util::backquote($foreignTable) . '.' . Util::backquote($arr['foreign_field']) . ' WHERE ' . Util::backquote($arr['foreign_db']) . '.' . Util::backquote($foreignTable) . '.' . Util::backquote($arr['foreign_field']) . ' IS NULL AND ' . Util::backquote(Current::$table) . '.' . Util::backquote($master) . ' IS NOT NULL'; $thisUrlParams = array_merge( $urlParams, ['sql_query' => $joinQuery, 'sql_signature' => Core::signSqlQuery($joinQuery)], ); $foreigners[] = [ 'params' => $thisUrlParams, 'master' => $master, 'db' => $arr['foreign_db'], 'table' => $arr['foreign_table'], 'field' => $arr['foreign_field'], ]; } return $foreigners; } /** * Get table alters array * * @param Table $pmaTable The Table object * @param string $packKeys pack keys * @param string $checksum value of checksum * @param string $pageChecksum value of page checksum * @param string $delayKeyWrite delay key write * @param string $rowFormat row format * @param string $newTblStorageEngine table storage engine * @param string $transactional value of transactional * @param string $tableCollation collation of the table * * @return string[] */ public function getTableAltersArray( Table $pmaTable, string $packKeys, string $checksum, string $pageChecksum, string $delayKeyWrite, string $rowFormat, string $newTblStorageEngine, string $transactional, string $tableCollation, string $tableStorageEngine, ): array { $GLOBALS['auto_increment'] ??= null; $tableAlters = []; if (isset($_POST['comment']) && urldecode($_POST['prev_comment']) !== $_POST['comment']) { $tableAlters[] = 'COMMENT = ' . $this->dbi->quoteString($_POST['comment']); } if ( $newTblStorageEngine !== '' && mb_strtolower($newTblStorageEngine) !== mb_strtolower($tableStorageEngine) ) { $tableAlters[] = 'ENGINE = ' . $newTblStorageEngine; } if (! empty($_POST['tbl_collation']) && $_POST['tbl_collation'] !== $tableCollation) { $tableAlters[] = 'DEFAULT ' . Util::getCharsetQueryPart($_POST['tbl_collation']); } if ( $pmaTable->isEngine(['MYISAM', 'ARIA', 'ISAM']) && isset($_POST['new_pack_keys']) && $_POST['new_pack_keys'] != $packKeys ) { $tableAlters[] = 'pack_keys = ' . $_POST['new_pack_keys']; } $newChecksum = empty($_POST['new_checksum']) ? '0' : '1'; if ($pmaTable->isEngine(['MYISAM', 'ARIA']) && $newChecksum !== $checksum) { $tableAlters[] = 'checksum = ' . $newChecksum; } $newTransactional = empty($_POST['new_transactional']) ? '0' : '1'; if ($pmaTable->isEngine('ARIA') && $newTransactional !== $transactional) { $tableAlters[] = 'TRANSACTIONAL = ' . $newTransactional; } $newPageChecksum = empty($_POST['new_page_checksum']) ? '0' : '1'; if ($pmaTable->isEngine('ARIA') && $newPageChecksum !== $pageChecksum) { $tableAlters[] = 'PAGE_CHECKSUM = ' . $newPageChecksum; } $newDelayKeyWrite = empty($_POST['new_delay_key_write']) ? '0' : '1'; if ($pmaTable->isEngine(['MYISAM', 'ARIA']) && $newDelayKeyWrite !== $delayKeyWrite) { $tableAlters[] = 'delay_key_write = ' . $newDelayKeyWrite; } if ( $pmaTable->isEngine(['MYISAM', 'ARIA', 'INNODB', 'PBXT', 'ROCKSDB']) && ! empty($_POST['new_auto_increment']) && (! isset($GLOBALS['auto_increment']) || $_POST['new_auto_increment'] !== $GLOBALS['auto_increment']) && $_POST['new_auto_increment'] !== $_POST['hidden_auto_increment'] ) { $tableAlters[] = 'auto_increment = ' . (int) $_POST['new_auto_increment']; } if (! empty($_POST['new_row_format'])) { $newRowFormat = $_POST['new_row_format']; $newRowFormatLower = mb_strtolower($newRowFormat); if ( $pmaTable->isEngine(['MYISAM', 'ARIA', 'INNODB', 'PBXT']) && ($rowFormat === '' || $newRowFormatLower !== mb_strtolower($rowFormat)) && in_array($newRowFormat, ['DEFAULT', 'DYNAMIC', 'FIXED', 'COMPRESSED', 'REDUNDANT', 'COMPACT'], true) ) { $tableAlters[] = 'ROW_FORMAT = ' . $newRowFormat; } } return $tableAlters; } /** * Get warning messages array * * @return string[] */ public function getWarningMessagesArray(mixed $newTableStorageEngine): array { $warningMessages = []; foreach ($this->dbi->getWarnings() as $warning) { // In MariaDB 5.1.44, when altering a table from Maria to MyISAM // and if TRANSACTIONAL was set, the system reports an error; // I discussed with a Maria developer and he agrees that this // should not be reported with a Level of Error, so here // I just ignore it. But there are other 1478 messages // that it's better to show. if ( $newTableStorageEngine === 'MyISAM' && $warning->code === 1478 && $warning->level === 'Error' ) { continue; } $warningMessages[] = (string) $warning; } return $warningMessages; } /** * Adjust the privileges after renaming/moving a table * * @param string $oldDb Database name before table renaming/moving table * @param string $oldTable Table name before table renaming/moving table * @param string $newDb Database name after table renaming/ moving table * @param string $newTable Table name after table renaming/moving table */ public function adjustPrivilegesRenameOrMoveTable( UserPrivileges $userPrivileges, string $oldDb, string $oldTable, string $newDb, string $newTable, ): void { if (! $userPrivileges->table || ! $userPrivileges->column || ! $userPrivileges->isReload) { return; } $this->dbi->selectDb('mysql'); // For table specific privileges $this->dbi->query('UPDATE ' . Util::backquote('tables_priv') . 'SET Db = ' . $this->dbi->quoteString($newDb) . ', Table_name = ' . $this->dbi->quoteString($newTable) . ' where Db = ' . $this->dbi->quoteString($oldDb) . ' AND Table_name = ' . $this->dbi->quoteString($oldTable) . ';'); // For column specific privileges $this->dbi->query('UPDATE ' . Util::backquote('columns_priv') . 'SET Db = ' . $this->dbi->quoteString($newDb) . ', Table_name = ' . $this->dbi->quoteString($newTable) . ' where Db = ' . $this->dbi->quoteString($oldDb) . ' AND Table_name = ' . $this->dbi->quoteString($oldTable) . ';'); // Finally FLUSH the new privileges $this->dbi->query('FLUSH PRIVILEGES;'); } /** * Adjust the privileges after copying a table * * @param string $oldDb Database name before table copying * @param string $oldTable Table name before table copying * @param string $newDb Database name after table copying * @param string $newTable Table name after table copying */ public function adjustPrivilegesCopyTable( UserPrivileges $userPrivileges, string $oldDb, string $oldTable, string $newDb, string $newTable, ): void { if (! $userPrivileges->table || ! $userPrivileges->column || ! $userPrivileges->isReload) { return; } $this->dbi->selectDb('mysql'); // For Table Specific privileges $queryTableSpecificOld = 'SELECT * FROM ' . Util::backquote('tables_priv') . ' where ' . 'Db = "' . $oldDb . '" AND Table_name = "' . $oldTable . '";'; $oldPrivsTable = $this->dbi->fetchResult($queryTableSpecificOld, 0); foreach ($oldPrivsTable as $oldPriv) { $newDbTablePrivsQuery = 'INSERT INTO ' . Util::backquote('tables_priv') . ' VALUES("' . $oldPriv[0] . '", "' . $newDb . '", "' . $oldPriv[2] . '", "' . $newTable . '", "' . $oldPriv[4] . '", "' . $oldPriv[5] . '", "' . $oldPriv[6] . '", "' . $oldPriv[7] . '");'; $this->dbi->query($newDbTablePrivsQuery); } // For Column Specific privileges $queryColSpecificOld = 'SELECT * FROM ' . Util::backquote('columns_priv') . ' WHERE ' . 'Db = "' . $oldDb . '" AND Table_name = "' . $oldTable . '";'; $oldPrivsCol = $this->dbi->fetchResult($queryColSpecificOld, 0); foreach ($oldPrivsCol as $oldPriv) { $newDbColPrivsQuery = 'INSERT INTO ' . Util::backquote('columns_priv') . ' VALUES("' . $oldPriv[0] . '", "' . $newDb . '", "' . $oldPriv[2] . '", "' . $newTable . '", "' . $oldPriv[4] . '", "' . $oldPriv[5] . '", "' . $oldPriv[6] . '");'; $this->dbi->query($newDbColPrivsQuery); } // Finally FLUSH the new privileges $this->dbi->query('FLUSH PRIVILEGES;'); } /** * Change all collations and character sets of all columns in table * * @param string $db Database name * @param string $table Table name * @param string $tableCollation Collation Name */ public function changeAllColumnsCollation(string $db, string $table, string $tableCollation): void { $this->dbi->selectDb($db); $changeAllCollationsQuery = 'ALTER TABLE ' . Util::backquote($table) . ' CONVERT TO'; [$charset] = explode('_', $tableCollation); $changeAllCollationsQuery .= ' CHARACTER SET ' . $charset . ($charset === $tableCollation ? '' : ' COLLATE ' . $tableCollation); $this->dbi->query($changeAllCollationsQuery); } /** * Move or copy a table * * @param string $db current database name * @param string $table current table name */ public function moveOrCopyTable(UserPrivileges $userPrivileges, string $db, string $table): Message { /** * Selects the database to work with */ $this->dbi->selectDb($db); /** * $_POST['target_db'] could be empty in case we came from an input field * (when there are many databases, no drop-down) */ $targetDb = $db; if (isset($_POST['target_db']) && is_string($_POST['target_db']) && $_POST['target_db'] !== '') { $targetDb = $_POST['target_db']; } /** * A target table name has been sent to this script -> do the work */ if (isset($_POST['new_name']) && is_scalar($_POST['new_name']) && (string) $_POST['new_name'] !== '') { if ($db === $targetDb && $table == $_POST['new_name']) { if (isset($_POST['submit_move'])) { $message = Message::error(__('Can\'t move table to same one!')); } else { $message = Message::error(__('Can\'t copy table to same one!')); } } else { Table::moveCopy( $db, $table, $targetDb, (string) $_POST['new_name'], $_POST['what'], isset($_POST['submit_move']), 'one_table', isset($_POST['drop_if_exists']) && $_POST['drop_if_exists'] === 'true', ); if (! empty($_POST['adjust_privileges'])) { if (isset($_POST['submit_move'])) { $this->adjustPrivilegesRenameOrMoveTable( $userPrivileges, $db, $table, $targetDb, (string) $_POST['new_name'], ); } else { $this->adjustPrivilegesCopyTable( $userPrivileges, $db, $table, $targetDb, (string) $_POST['new_name'], ); } if (isset($_POST['submit_move'])) { $message = Message::success( __( 'Table %s has been moved to %s. Privileges have been adjusted.', ), ); } else { $message = Message::success( __( 'Table %s has been copied to %s. Privileges have been adjusted.', ), ); } } elseif (isset($_POST['submit_move'])) { $message = Message::success( __('Table %s has been moved to %s.'), ); } else { $message = Message::success( __('Table %s has been copied to %s.'), ); } $old = Util::backquote($db) . '.' . Util::backquote($table); $message->addParam($old); $newName = (string) $_POST['new_name']; if ($this->dbi->getLowerCaseNames() === 1) { $newName = strtolower($newName); } Current::$table = $newName; $new = Util::backquote($targetDb) . '.' . Util::backquote($newName); $message->addParam($new); } } else { /** * No new name for the table! */ $message = Message::error(__('The table name is empty!')); } return $message; } }
Close