2 /* vim: set expandtab sw=4 ts=4 sts=4: */
4 * Main export handling code
8 declare(strict_types
=1);
11 use PhpMyAdmin\Encoding
;
12 use PhpMyAdmin\Export
;
13 use PhpMyAdmin\Plugins
;
14 use PhpMyAdmin\Plugins\ExportPlugin
;
15 use PhpMyAdmin\Relation
;
16 use PhpMyAdmin\Sanitize
;
19 use PhpMyAdmin\Response
;
21 if (! defined('ROOT_PATH')) {
22 define('ROOT_PATH', __DIR__
. DIRECTORY_SEPARATOR
);
26 * Get the variables sent or posted to this script and a core script
28 include_once ROOT_PATH
. 'libraries/common.inc.php';
30 $response = Response
::getInstance();
31 $header = $response->getHeader();
32 $scripts = $header->getScripts();
33 $scripts->addFile('export_output.js');
35 $export = new Export();
37 //check if it's the GET request to check export time out
38 if (isset($_GET['check_time_out'])) {
39 if (isset($_SESSION['pma_export_error'])) {
40 $err = $_SESSION['pma_export_error'];
41 unset($_SESSION['pma_export_error']);
50 * Sets globals from $_POST
52 * - Please keep the parameters in order of their appearance in the form
53 * - Some of these parameters are not used, as the code below directly
54 * verifies from the superglobal $_POST or $_REQUEST
55 * TODO: this should be removed to avoid passing user input to GLOBALS
83 'htmlword_structure_or_data',
87 'mediawiki_structure_or_data',
89 'pdf_structure_or_data',
90 'odt_structure_or_data',
96 'codegen_structure_or_data',
102 'excel_structure_or_data',
103 'yaml_structure_or_data',
105 'ods_structure_or_data',
107 'json_structure_or_data',
110 'xml_structure_or_data',
112 'xml_export_functions',
113 'xml_export_procedures',
115 'xml_export_triggers',
117 'xml_export_contents',
118 'texytext_structure_or_data',
121 'phparray_structure_or_data',
122 'sql_include_comments',
123 'sql_header_comment',
127 'sql_use_transaction',
130 'sql_structure_or_data',
131 'sql_create_database',
133 'sql_procedure_function',
136 'sql_create_trigger',
137 'sql_view_current_user',
139 'sql_or_replace_view',
140 'sql_auto_increment',
147 'sql_max_query_size',
148 'sql_hex_for_binary',
151 'sql_views_as_tables',
160 'csv_structure_or_data',
161 // csv_replace should have been here but we use it directly from $_POST
163 'latex_structure_or_data',
164 'latex_structure_caption',
165 'latex_structure_continued_caption',
166 'latex_structure_label',
171 'latex_data_caption',
172 'latex_data_continued_caption',
178 foreach ($post_params as $one_post_param) {
179 if (isset($_POST[$one_post_param])) {
180 $GLOBALS[$one_post_param] = $_POST[$one_post_param];
184 $table = $GLOBALS['table'];
186 PhpMyAdmin\Util
::checkParameters(['what', 'export_type']);
188 // sanitize this parameter which will be used below in a file inclusion
189 $what = Core
::securePath($_POST['what']);
191 // export class instance, not array of properties, as before
192 /** @var ExportPlugin $export_plugin */
193 $export_plugin = Plugins
::getPlugin(
196 'libraries/classes/Plugins/Export/',
198 'export_type' => $export_type,
199 'single_table' => isset($single_table),
204 if (empty($export_plugin)) {
205 Core
::fatalError(__('Bad type!'));
209 * valid compression methods
211 $compression_methods = [
217 * init and variable checking
221 $save_on_server = false;
222 $buffer_needed = false;
229 $separate_files = '';
231 // Is it a quick or custom export?
232 if (isset($_POST['quick_or_custom'])
233 && $_POST['quick_or_custom'] == 'quick'
235 $quick_export = true;
237 $quick_export = false;
240 if ($_POST['output_format'] == 'astext') {
244 if (isset($_POST['as_separate_files'])
245 && ! empty($_POST['as_separate_files'])
247 if (isset($_POST['compression'])
248 && ! empty($_POST['compression'])
249 && $_POST['compression'] == 'zip'
251 $separate_files = $_POST['as_separate_files'];
254 if (in_array($_POST['compression'], $compression_methods)) {
255 $compression = $_POST['compression'];
256 $buffer_needed = true;
258 if (($quick_export && ! empty($_POST['quick_export_onserver']))
259 ||
(! $quick_export && ! empty($_POST['onserver']))
262 $onserver = $_POST['quick_export_onserver'];
264 $onserver = $_POST['onserver'];
266 // Will we save dump on server?
267 $save_on_server = ! empty($cfg['SaveDir']) && $onserver;
272 * If we are sending the export file (as opposed to just displaying it
273 * as text), we have to bypass the usual PhpMyAdmin\Response mechanism
275 if (isset($_POST['output_format']) && $_POST['output_format'] == 'sendit' && ! $save_on_server) {
276 $response->disable();
280 // Generate error url and check for needed variables
281 if ($export_type == 'server') {
282 $err_url = 'server_export.php' . Url
::getCommon();
283 } elseif ($export_type == 'database' && strlen($db) > 0) {
284 $err_url = 'db_export.php' . Url
::getCommon(['db' => $db]);
285 // Check if we have something to export
286 if (isset($table_select)) {
287 $tables = $table_select;
291 } elseif ($export_type == 'table' && strlen($db) > 0 && strlen($table) > 0) {
292 $err_url = 'tbl_export.php' . Url
::getCommon(
299 Core
::fatalError(__('Bad parameters!'));
302 // Merge SQL Query aliases with Export aliases from
303 // export page, Export page aliases are given more
304 // preference over SQL Query aliases.
305 $parser = new \PhpMyAdmin\SqlParser\
Parser($sql_query);
307 if (! empty($parser->statements
[0])
308 && ($parser->statements
[0] instanceof \PhpMyAdmin\SqlParser\Statements\SelectStatement
)
310 $aliases = \PhpMyAdmin\SqlParser\Utils\Misc
::getAliases($parser->statements
[0], $db);
312 if (! empty($_POST['aliases'])) {
313 $aliases = $export->mergeAliases($aliases, $_POST['aliases']);
314 $_SESSION['tmpval']['aliases'] = $_POST['aliases'];
318 * Increase time limit for script execution and initializes some variables
320 Util
::setTimeLimit();
321 if (! empty($cfg['MemoryLimit'])) {
322 ini_set('memory_limit', $cfg['MemoryLimit']);
324 register_shutdown_function([$export, 'shutdown']);
325 // Start with empty buffer
327 $dump_buffer_len = 0;
329 // Array of dump_buffers - used in separate file exports
330 $dump_buffer_objects = [];
332 // We send fake headers to avoid browser timeout when buffering
333 $time_start = time();
335 // Defines the default <CR><LF> format.
336 // For SQL always use \n as MySQL wants this on all platforms.
337 if ($what == 'sql') {
343 $output_kanji_conversion = Encoding
::canConvertKanji();
345 // Do we need to convert charset?
346 $output_charset_conversion = $asfile
347 && Encoding
::isSupported()
348 && isset($charset) && $charset != 'utf-8';
350 // Use on the fly compression?
351 $GLOBALS['onfly_compression'] = $GLOBALS['cfg']['CompressOnFly']
352 && $compression == 'gzip';
353 if ($GLOBALS['onfly_compression']) {
354 $GLOBALS['memory_limit'] = $export->getMemoryLimit();
357 // Generate filename and mime type if needed
359 if (empty($remember_template)) {
360 $remember_template = '';
362 list($filename, $mime_type) = $export->getFilenameAndMimetype(
373 // Open file on server if needed
374 if ($save_on_server) {
375 list($save_filename, $message, $file_handle) = $export->openFile(
380 // problem opening export file on server?
381 if (! empty($message)) {
382 $export->showPage($db, $table, $export_type);
386 * Send headers depending on whether the user chose to download a dump file
391 // (avoid rewriting data containing HTML with anchors and forms;
392 // this was reported to happen under Plesk)
393 ini_set('url_rewriter.tags', '');
394 $filename = Sanitize
::sanitizeFilename($filename);
396 Core
::downloadHeader($filename, $mime_type);
399 if ($export_type == 'database') {
400 $num_tables = count($tables);
401 if ($num_tables == 0) {
402 $message = PhpMyAdmin\Message
::error(
403 __('No tables found in database.')
405 $active_page = 'db_export.php';
406 include ROOT_PATH
. 'db_export.php';
410 list($html, $back_button, $refreshButton) = $export->getHtmlForDisplayedExportHeader(
420 $relation = new Relation($GLOBALS['dbi']);
422 // Fake loop just to allow skip of remain of this code by break, I'd really
423 // need exceptions here :-)
427 $dump_buffer_len = 0;
429 // Add possibly some comments to export
430 if (! $export_plugin->exportHeader()) {
434 // Will we need relation & co. setup?
435 $do_relation = isset($GLOBALS[$what . '_relation']);
436 $do_comments = isset($GLOBALS[$what . '_include_comments'])
437 ||
isset($GLOBALS[$what . '_comments']);
438 $do_mime = isset($GLOBALS[$what . '_mime']);
439 if ($do_relation ||
$do_comments ||
$do_mime) {
440 $cfgRelation = $relation->getRelationsParam();
443 // Include dates in export?
444 $do_dates = isset($GLOBALS[$what . '_dates']);
446 $whatStrucOrData = $GLOBALS[$what . '_structure_or_data'];
451 if ($export_type == 'server') {
452 if (! isset($db_select)) {
455 $export->exportServer(
469 } elseif ($export_type == 'database') {
470 if (! isset($table_structure) ||
! is_array($table_structure)) {
471 $table_structure = [];
473 if (! isset($table_data) ||
! is_array($table_data)) {
476 if (! empty($_POST['structure_or_data_forced'])) {
477 $table_structure = $tables;
478 $table_data = $tables;
480 if (isset($lock_tables)) {
481 $export->lockTables($db, $tables, "READ");
483 $export->exportDatabase(
501 $export->unlockTables();
504 $export->exportDatabase(
523 // We export just one table
524 // $allrows comes from the form when "Dump all rows" has been selected
525 if (! isset($allrows)) {
528 if (! isset($limit_to)) {
531 if (! isset($limit_from)) {
534 if (isset($lock_tables)) {
536 $export->lockTables($db, [$table], "READ");
537 $export->exportTable(
556 $export->unlockTables();
559 $export->exportTable(
579 if (! $export_plugin->exportFooter()) {
585 if ($save_on_server && ! empty($message)) {
586 $export->showPage($db, $table, $export_type);
590 * Send the dump as a file...
592 if (empty($asfile)) {
593 echo $export->getHtmlForDisplayedExportFooter($back_button, $refreshButton);
597 // Convert the charset if required.
598 if ($output_charset_conversion) {
599 $dump_buffer = Encoding
::convertString(
606 // Compression needed?
608 if (! empty($separate_files)) {
609 $dump_buffer = $export->compress(
610 $dump_buffer_objects,
615 $dump_buffer = $export->compress($dump_buffer, $compression, $filename);
619 /* If we saved on server, we have to close file now */
620 if ($save_on_server) {
621 $message = $export->closeFile(
626 $export->showPage($db, $table, $export_type);