Translated using Weblate (German)
[phpmyadmin.git] / export.php
blobd002b6b46e9464b3d6d4dbc432fdb021145a2379
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Main export handling code
6 * @package PhpMyAdmin
7 */
8 declare(strict_types=1);
10 use PhpMyAdmin\Core;
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;
17 use PhpMyAdmin\Url;
18 use PhpMyAdmin\Util;
19 use PhpMyAdmin\Response;
21 /**
22 * Get the variables sent or posted to this script and a core script
24 include_once 'libraries/common.inc.php';
25 /**
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();
31 $response->disable();
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']);
46 echo "timeout";
47 } else {
48 echo "success";
50 exit;
52 /**
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
59 * without checking
61 $post_params = [
62 'db',
63 'table',
64 'what',
65 'single_table',
66 'export_type',
67 'export_method',
68 'quick_or_custom',
69 'db_select',
70 'table_select',
71 'table_structure',
72 'table_data',
73 'limit_to',
74 'limit_from',
75 'allrows',
76 'lock_tables',
77 'output_format',
78 'filename_template',
79 'maxsize',
80 'remember_template',
81 'charset',
82 'compression',
83 'as_separate_files',
84 'knjenc',
85 'xkana',
86 'htmlword_structure_or_data',
87 'htmlword_null',
88 'htmlword_columns',
89 'mediawiki_headers',
90 'mediawiki_structure_or_data',
91 'mediawiki_caption',
92 'pdf_structure_or_data',
93 'odt_structure_or_data',
94 'odt_relation',
95 'odt_comments',
96 'odt_mime',
97 'odt_columns',
98 'odt_null',
99 'codegen_structure_or_data',
100 'codegen_format',
101 'excel_null',
102 'excel_removeCRLF',
103 'excel_columns',
104 'excel_edition',
105 'excel_structure_or_data',
106 'yaml_structure_or_data',
107 'ods_null',
108 'ods_structure_or_data',
109 'ods_columns',
110 'json_structure_or_data',
111 'json_pretty_print',
112 'json_unicode',
113 'xml_structure_or_data',
114 'xml_export_events',
115 'xml_export_functions',
116 'xml_export_procedures',
117 'xml_export_tables',
118 'xml_export_triggers',
119 'xml_export_views',
120 'xml_export_contents',
121 'texytext_structure_or_data',
122 'texytext_columns',
123 'texytext_null',
124 'phparray_structure_or_data',
125 'sql_include_comments',
126 'sql_header_comment',
127 'sql_dates',
128 'sql_relation',
129 'sql_mime',
130 'sql_use_transaction',
131 'sql_disable_fk',
132 'sql_compatibility',
133 'sql_structure_or_data',
134 'sql_create_database',
135 'sql_drop_table',
136 'sql_procedure_function',
137 'sql_create_table',
138 'sql_create_view',
139 'sql_create_trigger',
140 'sql_view_current_user',
141 'sql_if_not_exists',
142 'sql_or_replace_view',
143 'sql_auto_increment',
144 'sql_backquotes',
145 'sql_truncate',
146 'sql_delayed',
147 'sql_ignore',
148 'sql_type',
149 'sql_insert_syntax',
150 'sql_max_query_size',
151 'sql_hex_for_binary',
152 'sql_utc_time',
153 'sql_drop_database',
154 'sql_views_as_tables',
155 'sql_metadata',
156 'csv_separator',
157 'csv_enclosed',
158 'csv_escaped',
159 'csv_terminated',
160 'csv_null',
161 'csv_removeCRLF',
162 'csv_columns',
163 'csv_structure_or_data',
164 // csv_replace should have been here but we use it directly from $_POST
165 'latex_caption',
166 'latex_structure_or_data',
167 'latex_structure_caption',
168 'latex_structure_continued_caption',
169 'latex_structure_label',
170 'latex_relation',
171 'latex_comments',
172 'latex_mime',
173 'latex_columns',
174 'latex_data_caption',
175 'latex_data_continued_caption',
176 'latex_data_label',
177 'latex_null',
178 'aliases'
181 foreach ($post_params as $one_post_param) {
182 if (isset($_POST[$one_post_param])) {
183 $GLOBALS[$one_post_param] = $_POST[$one_post_param];
187 $table = $GLOBALS['table'];
189 PhpMyAdmin\Util::checkParameters(['what', 'export_type']);
191 // sanitize this parameter which will be used below in a file inclusion
192 $what = Core::securePath($_POST['what']);
194 // export class instance, not array of properties, as before
195 /* @var $export_plugin ExportPlugin */
196 $export_plugin = Plugins::getPlugin(
197 "export",
198 $what,
199 'libraries/classes/Plugins/Export/',
201 'export_type' => $export_type,
202 'single_table' => isset($single_table)
206 // Check export type
207 if (empty($export_plugin)) {
208 Core::fatalError(__('Bad type!'));
212 * valid compression methods
214 $compression_methods = [
215 'zip',
216 'gzip'
220 * init and variable checking
222 $compression = '';
223 $onserver = false;
224 $save_on_server = false;
225 $buffer_needed = false;
226 $back_button = '';
227 $refreshButton = '';
228 $save_filename = '';
229 $file_handle = '';
230 $err_url = '';
231 $filename = '';
232 $separate_files = '';
234 // Is it a quick or custom export?
235 if (isset($_REQUEST['quick_or_custom'])
236 && $_REQUEST['quick_or_custom'] == 'quick'
238 $quick_export = true;
239 } else {
240 $quick_export = false;
243 if ($_REQUEST['output_format'] == 'astext') {
244 $asfile = false;
245 } else {
246 $asfile = true;
247 if (isset($_REQUEST['as_separate_files'])
248 && ! empty($_REQUEST['as_separate_files'])
250 if (isset($_REQUEST['compression'])
251 && ! empty($_REQUEST['compression'])
252 && $_REQUEST['compression'] == 'zip'
254 $separate_files = $_REQUEST['as_separate_files'];
257 if (in_array($_REQUEST['compression'], $compression_methods)) {
258 $compression = $_REQUEST['compression'];
259 $buffer_needed = true;
261 if (($quick_export && ! empty($_REQUEST['quick_export_onserver']))
262 || (! $quick_export && ! empty($_REQUEST['onserver']))
264 if ($quick_export) {
265 $onserver = $_REQUEST['quick_export_onserver'];
266 } else {
267 $onserver = $_REQUEST['onserver'];
269 // Will we save dump on server?
270 $save_on_server = ! empty($cfg['SaveDir']) && $onserver;
273 $tables = [];
274 // Generate error url and check for needed variables
275 if ($export_type == 'server') {
276 $err_url = 'server_export.php' . Url::getCommon();
277 } elseif ($export_type == 'database' && strlen($db) > 0) {
278 $err_url = 'db_export.php' . Url::getCommon(['db' => $db]);
279 // Check if we have something to export
280 if (isset($table_select)) {
281 $tables = $table_select;
282 } else {
283 $tables = [];
285 } elseif ($export_type == 'table' && strlen($db) > 0 && strlen($table) > 0) {
286 $err_url = 'tbl_export.php' . Url::getCommon(
288 'db' => $db, 'table' => $table
291 } else {
292 Core::fatalError(__('Bad parameters!'));
295 // Merge SQL Query aliases with Export aliases from
296 // export page, Export page aliases are given more
297 // preference over SQL Query aliases.
298 $parser = new \PhpMyAdmin\SqlParser\Parser($sql_query);
299 $aliases = [];
300 if ((!empty($parser->statements[0]))
301 && ($parser->statements[0] instanceof \PhpMyAdmin\SqlParser\Statements\SelectStatement)
303 $aliases = \PhpMyAdmin\SqlParser\Utils\Misc::getAliases($parser->statements[0], $db);
305 if (!empty($_REQUEST['aliases'])) {
306 $aliases = $export->mergeAliases($aliases, $_REQUEST['aliases']);
307 $_SESSION['tmpval']['aliases'] = $_REQUEST['aliases'];
311 * Increase time limit for script execution and initializes some variables
313 Util::setTimeLimit();
314 if (! empty($cfg['MemoryLimit'])) {
315 ini_set('memory_limit', $cfg['MemoryLimit']);
317 register_shutdown_function([$export, 'shutdown']);
318 // Start with empty buffer
319 $dump_buffer = '';
320 $dump_buffer_len = 0;
322 // Array of dump_buffers - used in separate file exports
323 $dump_buffer_objects = [];
325 // We send fake headers to avoid browser timeout when buffering
326 $time_start = time();
328 // Defines the default <CR><LF> format.
329 // For SQL always use \n as MySQL wants this on all platforms.
330 if ($what == 'sql') {
331 $crlf = "\n";
332 } else {
333 $crlf = PHP_EOL;
336 $output_kanji_conversion = Encoding::canConvertKanji();
338 // Do we need to convert charset?
339 $output_charset_conversion = $asfile
340 && Encoding::isSupported()
341 && isset($charset) && $charset != 'utf-8';
343 // Use on the fly compression?
344 $GLOBALS['onfly_compression'] = $GLOBALS['cfg']['CompressOnFly']
345 && $compression == 'gzip';
346 if ($GLOBALS['onfly_compression']) {
347 $GLOBALS['memory_limit'] = $export->getMemoryLimit();
350 // Generate filename and mime type if needed
351 if ($asfile) {
352 if (empty($remember_template)) {
353 $remember_template = '';
355 list($filename, $mime_type) = $export->getFilenameAndMimetype(
356 $export_type,
357 $remember_template,
358 $export_plugin,
359 $compression,
360 $filename_template
362 } else {
363 $mime_type = '';
366 // Open file on server if needed
367 if ($save_on_server) {
368 list($save_filename, $message, $file_handle) = $export->openFile(
369 $filename,
370 $quick_export
373 // problem opening export file on server?
374 if (! empty($message)) {
375 $export->showPage($db, $table, $export_type);
377 } else {
379 * Send headers depending on whether the user chose to download a dump file
380 * or not
382 if ($asfile) {
383 // Download
384 // (avoid rewriting data containing HTML with anchors and forms;
385 // this was reported to happen under Plesk)
386 ini_set('url_rewriter.tags', '');
387 $filename = Sanitize::sanitizeFilename($filename);
389 Core::downloadHeader($filename, $mime_type);
390 } else {
391 // HTML
392 if ($export_type == 'database') {
393 $num_tables = count($tables);
394 if ($num_tables == 0) {
395 $message = PhpMyAdmin\Message::error(
396 __('No tables found in database.')
398 $active_page = 'db_export.php';
399 include 'db_export.php';
400 exit();
403 list($html, $back_button, $refreshButton) = $export->getHtmlForDisplayedExportHeader(
404 $export_type,
405 $db,
406 $table
408 echo $html;
409 unset($html);
410 } // end download
413 $relation = new Relation($GLOBALS['dbi']);
415 // Fake loop just to allow skip of remain of this code by break, I'd really
416 // need exceptions here :-)
417 do {
418 // Re - initialize
419 $dump_buffer = '';
420 $dump_buffer_len = 0;
422 // Add possibly some comments to export
423 if (! $export_plugin->exportHeader()) {
424 break;
427 // Will we need relation & co. setup?
428 $do_relation = isset($GLOBALS[$what . '_relation']);
429 $do_comments = isset($GLOBALS[$what . '_include_comments'])
430 || isset($GLOBALS[$what . '_comments']);
431 $do_mime = isset($GLOBALS[$what . '_mime']);
432 if ($do_relation || $do_comments || $do_mime) {
433 $cfgRelation = $relation->getRelationsParam();
436 // Include dates in export?
437 $do_dates = isset($GLOBALS[$what . '_dates']);
439 $whatStrucOrData = $GLOBALS[$what . '_structure_or_data'];
442 * Builds the dump
444 if ($export_type == 'server') {
445 if (! isset($db_select)) {
446 $db_select = '';
448 $export->exportServer(
449 $db_select,
450 $whatStrucOrData,
451 $export_plugin,
452 $crlf,
453 $err_url,
454 $export_type,
455 $do_relation,
456 $do_comments,
457 $do_mime,
458 $do_dates,
459 $aliases,
460 $separate_files
462 } elseif ($export_type == 'database') {
463 if (!isset($table_structure) || !is_array($table_structure)) {
464 $table_structure = [];
466 if (!isset($table_data) || !is_array($table_data)) {
467 $table_data = [];
469 if (!empty($_REQUEST['structure_or_data_forced'])) {
470 $table_structure = $tables;
471 $table_data = $tables;
473 if (isset($lock_tables)) {
474 $export->lockTables($db, $tables, "READ");
475 try {
476 $export->exportDatabase(
477 $db,
478 $tables,
479 $whatStrucOrData,
480 $table_structure,
481 $table_data,
482 $export_plugin,
483 $crlf,
484 $err_url,
485 $export_type,
486 $do_relation,
487 $do_comments,
488 $do_mime,
489 $do_dates,
490 $aliases,
491 $separate_files
493 } finally {
494 $export->unlockTables();
496 } else {
497 $export->exportDatabase(
498 $db,
499 $tables,
500 $whatStrucOrData,
501 $table_structure,
502 $table_data,
503 $export_plugin,
504 $crlf,
505 $err_url,
506 $export_type,
507 $do_relation,
508 $do_comments,
509 $do_mime,
510 $do_dates,
511 $aliases,
512 $separate_files
515 } else {
516 // We export just one table
517 // $allrows comes from the form when "Dump all rows" has been selected
518 if (! isset($allrows)) {
519 $allrows = '';
521 if (! isset($limit_to)) {
522 $limit_to = '0';
524 if (! isset($limit_from)) {
525 $limit_from = '0';
527 if (isset($lock_tables)) {
528 try {
529 $export->lockTables($db, [$table], "READ");
530 $export->exportTable(
531 $db,
532 $table,
533 $whatStrucOrData,
534 $export_plugin,
535 $crlf,
536 $err_url,
537 $export_type,
538 $do_relation,
539 $do_comments,
540 $do_mime,
541 $do_dates,
542 $allrows,
543 $limit_to,
544 $limit_from,
545 $sql_query,
546 $aliases
548 } finally {
549 $export->unlockTables();
551 } else {
552 $export->exportTable(
553 $db,
554 $table,
555 $whatStrucOrData,
556 $export_plugin,
557 $crlf,
558 $err_url,
559 $export_type,
560 $do_relation,
561 $do_comments,
562 $do_mime,
563 $do_dates,
564 $allrows,
565 $limit_to,
566 $limit_from,
567 $sql_query,
568 $aliases
572 if (! $export_plugin->exportFooter()) {
573 break;
575 } while (false);
576 // End of fake loop
578 if ($save_on_server && ! empty($message)) {
579 $export->showPage($db, $table, $export_type);
583 * Send the dump as a file...
585 if (empty($asfile)) {
586 echo $export->getHtmlForDisplayedExportFooter($back_button, $refreshButton);
587 return;
588 } // end if
590 // Convert the charset if required.
591 if ($output_charset_conversion) {
592 $dump_buffer = Encoding::convertString(
593 'utf-8',
594 $GLOBALS['charset'],
595 $dump_buffer
599 // Compression needed?
600 if ($compression) {
601 if (! empty($separate_files)) {
602 $dump_buffer = $export->compress(
603 $dump_buffer_objects,
604 $compression,
605 $filename
607 } else {
608 $dump_buffer = $export->compress($dump_buffer, $compression, $filename);
612 /* If we saved on server, we have to close file now */
613 if ($save_on_server) {
614 $message = $export->closeFile(
615 $file_handle,
616 $dump_buffer,
617 $save_filename
619 $export->showPage($db, $table, $export_type);
620 } else {
621 echo $dump_buffer;