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
;
22 * Get the variables sent or posted to this script and a core script
24 include_once 'libraries/common.inc.php';
26 * If we are sending the export file (as opposed to just displaying it
27 * as text), we have to bypass the usual PhpMyAdmin\Response mechanism
29 if (isset($_POST['output_format']) && $_POST['output_format'] == 'sendit') {
30 $response = Response
::getInstance();
34 $response = Response
::getInstance();
35 $header = $response->getHeader();
36 $scripts = $header->getScripts();
37 $scripts->addFile('export_output.js');
39 $export = new Export();
41 //check if it's the GET request to check export time out
42 if (isset($_GET['check_time_out'])) {
43 if (isset($_SESSION['pma_export_error'])) {
44 $err = $_SESSION['pma_export_error'];
45 unset($_SESSION['pma_export_error']);
53 * Sets globals from $_POST
55 * - Please keep the parameters in order of their appearance in the form
56 * - Some of these parameters are not used, as the code below directly
57 * verifies from the superglobal $_POST or $_REQUEST
58 * TODO: this should be removed to avoid passing user input to GLOBALS
86 'htmlword_structure_or_data',
90 'mediawiki_structure_or_data',
92 'pdf_structure_or_data',
93 'odt_structure_or_data',
99 'codegen_structure_or_data',
105 'excel_structure_or_data',
106 'yaml_structure_or_data',
108 'ods_structure_or_data',
110 'json_structure_or_data',
113 'xml_structure_or_data',
115 'xml_export_functions',
116 'xml_export_procedures',
118 'xml_export_triggers',
120 'xml_export_contents',
121 'texytext_structure_or_data',
124 'phparray_structure_or_data',
125 'sql_include_comments',
126 'sql_header_comment',
130 'sql_use_transaction',
133 'sql_structure_or_data',
134 'sql_create_database',
136 'sql_procedure_function',
139 'sql_create_trigger',
141 'sql_auto_increment',
148 'sql_max_query_size',
149 'sql_hex_for_binary',
152 'sql_views_as_tables',
161 'csv_structure_or_data',
162 // csv_replace should have been here but we use it directly from $_POST
164 'latex_structure_or_data',
165 'latex_structure_caption',
166 'latex_structure_continued_caption',
167 'latex_structure_label',
172 'latex_data_caption',
173 'latex_data_continued_caption',
179 foreach ($post_params as $one_post_param) {
180 if (isset($_POST[$one_post_param])) {
181 $GLOBALS[$one_post_param] = $_POST[$one_post_param];
185 $table = $GLOBALS['table'];
187 PhpMyAdmin\Util
::checkParameters(['what', 'export_type']);
189 // sanitize this parameter which will be used below in a file inclusion
190 $what = Core
::securePath($_POST['what']);
192 // export class instance, not array of properties, as before
193 /* @var $export_plugin ExportPlugin */
194 $export_plugin = Plugins
::getPlugin(
197 'libraries/classes/Plugins/Export/',
199 'export_type' => $export_type,
200 'single_table' => isset($single_table)
205 if (empty($export_plugin)) {
206 Core
::fatalError(__('Bad type!'));
210 * valid compression methods
212 $compression_methods = [
218 * init and variable checking
222 $save_on_server = false;
223 $buffer_needed = false;
230 $separate_files = '';
232 // Is it a quick or custom export?
233 if (isset($_REQUEST['quick_or_custom'])
234 && $_REQUEST['quick_or_custom'] == 'quick'
236 $quick_export = true;
238 $quick_export = false;
241 if ($_REQUEST['output_format'] == 'astext') {
245 if (isset($_REQUEST['as_separate_files'])
246 && ! empty($_REQUEST['as_separate_files'])
248 if (isset($_REQUEST['compression'])
249 && ! empty($_REQUEST['compression'])
250 && $_REQUEST['compression'] == 'zip'
252 $separate_files = $_REQUEST['as_separate_files'];
255 if (in_array($_REQUEST['compression'], $compression_methods)) {
256 $compression = $_REQUEST['compression'];
257 $buffer_needed = true;
259 if (($quick_export && ! empty($_REQUEST['quick_export_onserver']))
260 ||
(! $quick_export && ! empty($_REQUEST['onserver']))
263 $onserver = $_REQUEST['quick_export_onserver'];
265 $onserver = $_REQUEST['onserver'];
267 // Will we save dump on server?
268 $save_on_server = ! empty($cfg['SaveDir']) && $onserver;
272 // Generate error url and check for needed variables
273 if ($export_type == 'server') {
274 $err_url = 'server_export.php' . Url
::getCommon();
275 } elseif ($export_type == 'database' && strlen($db) > 0) {
276 $err_url = 'db_export.php' . Url
::getCommon(['db' => $db]);
277 // Check if we have something to export
278 if (isset($table_select)) {
279 $tables = $table_select;
283 } elseif ($export_type == 'table' && strlen($db) > 0 && strlen($table) > 0) {
284 $err_url = 'tbl_export.php' . Url
::getCommon(
286 'db' => $db, 'table' => $table
290 Core
::fatalError(__('Bad parameters!'));
293 // Merge SQL Query aliases with Export aliases from
294 // export page, Export page aliases are given more
295 // preference over SQL Query aliases.
296 $parser = new \PhpMyAdmin\SqlParser\
Parser($sql_query);
298 if ((!empty($parser->statements
[0]))
299 && ($parser->statements
[0] instanceof \PhpMyAdmin\SqlParser\Statements\SelectStatement
)
301 $aliases = \PhpMyAdmin\SqlParser\Utils\Misc
::getAliases($parser->statements
[0], $db);
303 if (!empty($_REQUEST['aliases'])) {
304 $aliases = $export->mergeAliases($aliases, $_REQUEST['aliases']);
305 $_SESSION['tmpval']['aliases'] = $_REQUEST['aliases'];
309 * Increase time limit for script execution and initializes some variables
311 Util
::setTimeLimit();
312 if (! empty($cfg['MemoryLimit'])) {
313 ini_set('memory_limit', $cfg['MemoryLimit']);
315 register_shutdown_function([$export, 'shutdown']);
316 // Start with empty buffer
318 $dump_buffer_len = 0;
320 // Array of dump_buffers - used in separate file exports
321 $dump_buffer_objects = [];
323 // We send fake headers to avoid browser timeout when buffering
324 $time_start = time();
326 // Defines the default <CR><LF> format.
327 // For SQL always use \n as MySQL wants this on all platforms.
328 if ($what == 'sql') {
334 $output_kanji_conversion = Encoding
::canConvertKanji();
336 // Do we need to convert charset?
337 $output_charset_conversion = $asfile
338 && Encoding
::isSupported()
339 && isset($charset) && $charset != 'utf-8';
341 // Use on the fly compression?
342 $GLOBALS['onfly_compression'] = $GLOBALS['cfg']['CompressOnFly']
343 && $compression == 'gzip';
344 if ($GLOBALS['onfly_compression']) {
345 $GLOBALS['memory_limit'] = $export->getMemoryLimit();
348 // Generate filename and mime type if needed
350 if (empty($remember_template)) {
351 $remember_template = '';
353 list($filename, $mime_type) = $export->getFilenameAndMimetype(
364 // Open file on server if needed
365 if ($save_on_server) {
366 list($save_filename, $message, $file_handle) = $export->openFile(
371 // problem opening export file on server?
372 if (! empty($message)) {
373 $export->showPage($db, $table, $export_type);
377 * Send headers depending on whether the user chose to download a dump file
382 // (avoid rewriting data containing HTML with anchors and forms;
383 // this was reported to happen under Plesk)
384 ini_set('url_rewriter.tags', '');
385 $filename = Sanitize
::sanitizeFilename($filename);
387 Core
::downloadHeader($filename, $mime_type);
390 if ($export_type == 'database') {
391 $num_tables = count($tables);
392 if ($num_tables == 0) {
393 $message = PhpMyAdmin\Message
::error(
394 __('No tables found in database.')
396 $active_page = 'db_export.php';
397 include 'db_export.php';
401 list($html, $back_button, $refreshButton) = $export->getHtmlForDisplayedExportHeader(
411 $relation = new Relation($GLOBALS['dbi']);
413 // Fake loop just to allow skip of remain of this code by break, I'd really
414 // need exceptions here :-)
418 $dump_buffer_len = 0;
420 // Add possibly some comments to export
421 if (! $export_plugin->exportHeader()) {
425 // Will we need relation & co. setup?
426 $do_relation = isset($GLOBALS[$what . '_relation']);
427 $do_comments = isset($GLOBALS[$what . '_include_comments'])
428 ||
isset($GLOBALS[$what . '_comments']);
429 $do_mime = isset($GLOBALS[$what . '_mime']);
430 if ($do_relation ||
$do_comments ||
$do_mime) {
431 $cfgRelation = $relation->getRelationsParam();
434 // Include dates in export?
435 $do_dates = isset($GLOBALS[$what . '_dates']);
437 $whatStrucOrData = $GLOBALS[$what . '_structure_or_data'];
442 if ($export_type == 'server') {
443 if (! isset($db_select)) {
446 $export->exportServer(
460 } elseif ($export_type == 'database') {
461 if (!isset($table_structure) ||
!is_array($table_structure)) {
462 $table_structure = [];
464 if (!isset($table_data) ||
!is_array($table_data)) {
467 if (!empty($_REQUEST['structure_or_data_forced'])) {
468 $table_structure = $tables;
469 $table_data = $tables;
471 if (isset($lock_tables)) {
472 $export->lockTables($db, $tables, "READ");
474 $export->exportDatabase(
492 $export->unlockTables();
495 $export->exportDatabase(
514 // We export just one table
515 // $allrows comes from the form when "Dump all rows" has been selected
516 if (! isset($allrows)) {
519 if (! isset($limit_to)) {
522 if (! isset($limit_from)) {
525 if (isset($lock_tables)) {
527 $export->lockTables($db, [$table], "READ");
528 $export->exportTable(
547 $export->unlockTables();
550 $export->exportTable(
570 if (! $export_plugin->exportFooter()) {
576 if ($save_on_server && ! empty($message)) {
577 $export->showPage($db, $table, $export_type);
581 * Send the dump as a file...
583 if (empty($asfile)) {
584 echo $export->getHtmlForDisplayedExportFooter($back_button, $refreshButton);
588 // Convert the charset if required.
589 if ($output_charset_conversion) {
590 $dump_buffer = Encoding
::convertString(
597 // Compression needed?
599 if (! empty($separate_files)) {
600 $dump_buffer = $export->compress(
601 $dump_buffer_objects,
606 $dump_buffer = $export->compress($dump_buffer, $compression, $filename);
610 /* If we saved on server, we have to close file now */
611 if ($save_on_server) {
612 $message = $export->closeFile(
617 $export->showPage($db, $table, $export_type);