Translated using Weblate (Finnish)
[phpmyadmin.git] / import.php
blob5425dcc28765e6f70180ea99bb8b13e16dd9936b
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Core script for import, this is just the glue around all other stuff
6 * @package PhpMyAdmin
7 */
8 use PMA\libraries\Encoding;
9 use PMA\libraries\plugins\ImportPlugin;
10 use PMA\libraries\File;
11 use PMA\libraries\URL;
12 use PMA\libraries\Bookmark;
14 /**
15 * Get the variables sent or posted to this script and a core script
17 require_once 'libraries/common.inc.php';
18 require_once 'libraries/sql.lib.php';
19 //require_once 'libraries/display_import_functions.lib.php';
21 if (isset($_REQUEST['show_as_php'])) {
22 $GLOBALS['show_as_php'] = $_REQUEST['show_as_php'];
25 // Import functions.
26 require_once 'libraries/import.lib.php';
28 // If there is a request to 'Simulate DML'.
29 if (isset($_REQUEST['simulate_dml'])) {
30 PMA_handleSimulateDMLRequest();
31 exit;
34 // If it's a refresh console bookmarks request
35 if (isset($_REQUEST['console_bookmark_refresh'])) {
36 $response = PMA\libraries\Response::getInstance();
37 $response->addJSON(
38 'console_message_bookmark', PMA\libraries\Console::getBookmarkContent()
40 exit;
42 // If it's a console bookmark add request
43 if (isset($_REQUEST['console_bookmark_add'])) {
44 $response = PMA\libraries\Response::getInstance();
45 if (isset($_REQUEST['label']) && isset($_REQUEST['db'])
46 && isset($_REQUEST['bookmark_query']) && isset($_REQUEST['shared'])
47 ) {
48 $cfgBookmark = Bookmark::getParams();
49 $bookmarkFields = array(
50 'bkm_database' => $_REQUEST['db'],
51 'bkm_user' => $cfgBookmark['user'],
52 'bkm_sql_query' => $_REQUEST['bookmark_query'],
53 'bkm_label' => $_REQUEST['label']
55 $isShared = ($_REQUEST['shared'] == 'true' ? true : false);
56 $bookmark = Bookmark::createBookmark($bookmarkFields, $isShared);
57 if ($bookmark !== false && $bookmark->save()) {
58 $response->addJSON('message', __('Succeeded'));
59 $response->addJSON('data', $bookmarkFields);
60 $response->addJSON('isShared', $isShared);
61 } else {
62 $response->addJSON('message', __('Failed'));
64 die();
65 } else {
66 $response->addJSON('message', __('Incomplete params'));
67 die();
71 $format = '';
73 /**
74 * Sets globals from $_POST
76 $post_params = array(
77 'charset_of_file',
78 'format',
79 'import_type',
80 'is_js_confirmed',
81 'MAX_FILE_SIZE',
82 'message_to_show',
83 'noplugin',
84 'skip_queries',
85 'local_import_file'
88 foreach ($post_params as $one_post_param) {
89 if (isset($_POST[$one_post_param])) {
90 $GLOBALS[$one_post_param] = $_POST[$one_post_param];
94 // reset import messages for ajax request
95 $_SESSION['Import_message']['message'] = null;
96 $_SESSION['Import_message']['go_back_url'] = null;
97 // default values
98 $GLOBALS['reload'] = false;
100 // Use to identify current cycle is executing
101 // a multiquery statement or stored routine
102 if (!isset($_SESSION['is_multi_query'])) {
103 $_SESSION['is_multi_query'] = false;
106 $ajax_reload = array();
107 // Are we just executing plain query or sql file?
108 // (eg. non import, but query box/window run)
109 if (! empty($sql_query)) {
111 // apply values for parameters
112 if (! empty($_REQUEST['parameterized'])
113 && ! empty($_REQUEST['parameters'])
114 && is_array($_REQUEST['parameters'])
116 $parameters = $_REQUEST['parameters'];
117 foreach ($parameters as $parameter => $replacement) {
118 $quoted = preg_quote($parameter, '/');
119 // making sure that :param does not apply values to :param1
120 $sql_query = preg_replace(
121 '/' . $quoted . '([^a-zA-Z0-9_])/',
122 PMA\libraries\Util::sqlAddSlashes($replacement) . '${1}',
123 $sql_query
125 // for parameters the appear at the end of the string
126 $sql_query = preg_replace(
127 '/' . $quoted . '$/',
128 PMA\libraries\Util::sqlAddSlashes($replacement),
129 $sql_query
134 // run SQL query
135 $import_text = $sql_query;
136 $import_type = 'query';
137 $format = 'sql';
138 $_SESSION['sql_from_query_box'] = true;
140 // If there is a request to ROLLBACK when finished.
141 if (isset($_REQUEST['rollback_query'])) {
142 PMA_handleRollbackRequest($import_text);
145 // refresh navigation and main panels
146 if (preg_match('/^(DROP)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i', $sql_query)) {
147 $GLOBALS['reload'] = true;
148 $ajax_reload['reload'] = true;
151 // refresh navigation panel only
152 if (preg_match(
153 '/^(CREATE|ALTER)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i',
154 $sql_query
155 )) {
156 $ajax_reload['reload'] = true;
159 // do a dynamic reload if table is RENAMED
160 // (by sending the instruction to the AJAX response handler)
161 if (preg_match(
162 '/^RENAME\s+TABLE\s+(.*?)\s+TO\s+(.*?)($|;|\s)/i',
163 $sql_query,
164 $rename_table_names
165 )) {
166 $ajax_reload['reload'] = true;
167 $ajax_reload['table_name'] = PMA\libraries\Util::unQuote(
168 $rename_table_names[2]
172 $sql_query = '';
173 } elseif (! empty($sql_file)) {
174 // run uploaded SQL file
175 $import_file = $sql_file;
176 $import_type = 'queryfile';
177 $format = 'sql';
178 unset($sql_file);
179 } elseif (! empty($_REQUEST['id_bookmark'])) {
180 // run bookmark
181 $import_type = 'query';
182 $format = 'sql';
185 // If we didn't get any parameters, either user called this directly, or
186 // upload limit has been reached, let's assume the second possibility.
187 if ($_POST == array() && $_GET == array()) {
188 $message = PMA\libraries\Message::error(
190 'You probably tried to upload a file that is too large. Please refer ' .
191 'to %sdocumentation%s for a workaround for this limit.'
194 $message->addParam('[doc@faq1-16]');
195 $message->addParam('[/doc]');
197 // so we can obtain the message
198 $_SESSION['Import_message']['message'] = $message->getDisplay();
199 $_SESSION['Import_message']['go_back_url'] = $GLOBALS['goto'];
201 $message->display();
202 exit; // the footer is displayed automatically
205 // Add console message id to response output
206 if (isset($_POST['console_message_id'])) {
207 $response = PMA\libraries\Response::getInstance();
208 $response->addJSON('console_message_id', $_POST['console_message_id']);
212 * Sets globals from $_POST patterns, for import plugins
213 * We only need to load the selected plugin
216 if (! in_array(
217 $format,
218 array(
219 'csv',
220 'ldi',
221 'mediawiki',
222 'ods',
223 'shp',
224 'sql',
225 'xml'
229 // this should not happen for a normal user
230 // but only during an attack
231 PMA_fatalError('Incorrect format parameter');
234 $post_patterns = array(
235 '/^force_file_/',
236 '/^' . $format . '_/'
239 PMA_setPostAsGlobal($post_patterns);
241 // Check needed parameters
242 PMA\libraries\Util::checkParameters(array('import_type', 'format'));
244 // We don't want anything special in format
245 $format = PMA_securePath($format);
247 // Create error and goto url
248 if ($import_type == 'table') {
249 $err_url = 'tbl_import.php' . URL::getCommon(
250 array(
251 'db' => $db, 'table' => $table
254 $_SESSION['Import_message']['go_back_url'] = $err_url;
255 $goto = 'tbl_import.php';
256 } elseif ($import_type == 'database') {
257 $err_url = 'db_import.php' . URL::getCommon(array('db' => $db));
258 $_SESSION['Import_message']['go_back_url'] = $err_url;
259 $goto = 'db_import.php';
260 } elseif ($import_type == 'server') {
261 $err_url = 'server_import.php' . URL::getCommon();
262 $_SESSION['Import_message']['go_back_url'] = $err_url;
263 $goto = 'server_import.php';
264 } else {
265 if (empty($goto) || !preg_match('@^(server|db|tbl)(_[a-z]*)*\.php$@i', $goto)) {
266 if (mb_strlen($table) && mb_strlen($db)) {
267 $goto = 'tbl_structure.php';
268 } elseif (mb_strlen($db)) {
269 $goto = 'db_structure.php';
270 } else {
271 $goto = 'server_sql.php';
274 if (mb_strlen($table) && mb_strlen($db)) {
275 $common = URL::getCommon(array('db' => $db, 'table' => $table));
276 } elseif (mb_strlen($db)) {
277 $common = URL::getCommon(array('db' => $db));
278 } else {
279 $common = URL::getCommon();
281 $err_url = $goto . $common
282 . (preg_match('@^tbl_[a-z]*\.php$@', $goto)
283 ? '&amp;table=' . htmlspecialchars($table)
284 : '');
285 $_SESSION['Import_message']['go_back_url'] = $err_url;
287 // Avoid setting selflink to 'import.php'
288 // problem similar to bug 4276
289 if (basename($_SERVER['SCRIPT_NAME']) === 'import.php') {
290 $_SERVER['SCRIPT_NAME'] = $goto;
294 if (mb_strlen($db)) {
295 $GLOBALS['dbi']->selectDb($db);
298 @set_time_limit($cfg['ExecTimeLimit']);
299 if (! empty($cfg['MemoryLimit'])) {
300 @ini_set('memory_limit', $cfg['MemoryLimit']);
303 $timestamp = time();
304 if (isset($_REQUEST['allow_interrupt'])) {
305 $maximum_time = ini_get('max_execution_time');
306 } else {
307 $maximum_time = 0;
310 // set default values
311 $timeout_passed = false;
312 $error = false;
313 $read_multiply = 1;
314 $finished = false;
315 $offset = 0;
316 $max_sql_len = 0;
317 $file_to_unlink = '';
318 $sql_query = '';
319 $sql_query_disabled = false;
320 $go_sql = false;
321 $executed_queries = 0;
322 $run_query = true;
323 $charset_conversion = false;
324 $reset_charset = false;
325 $bookmark_created = false;
327 // Bookmark Support: get a query back from bookmark if required
328 if (! empty($_REQUEST['id_bookmark'])) {
329 $id_bookmark = (int)$_REQUEST['id_bookmark'];
330 switch ($_REQUEST['action_bookmark']) {
331 case 0: // bookmarked query that have to be run
332 $bookmark = Bookmark::get(
333 $db,
334 $id_bookmark,
335 'id',
336 isset($_REQUEST['action_bookmark_all'])
339 if (! empty($_REQUEST['bookmark_variable'])) {
340 $import_text = $bookmark->applyVariables(
341 $_REQUEST['bookmark_variable']
343 } else {
344 $import_text = $bookmark->getQuery();
347 // refresh navigation and main panels
348 if (preg_match(
349 '/^(DROP)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i',
350 $import_text
351 )) {
352 $GLOBALS['reload'] = true;
353 $ajax_reload['reload'] = true;
356 // refresh navigation panel only
357 if (preg_match(
358 '/^(CREATE|ALTER)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i',
359 $import_text
362 $ajax_reload['reload'] = true;
364 break;
365 case 1: // bookmarked query that have to be displayed
366 $bookmark = Bookmark::get($db, $id_bookmark);
367 $import_text = $bookmark->getQuery();
368 if ($GLOBALS['is_ajax_request'] == true) {
369 $message = PMA\libraries\Message::success(__('Showing bookmark'));
370 $response = PMA\libraries\Response::getInstance();
371 $response->setRequestStatus($message->isSuccess());
372 $response->addJSON('message', $message);
373 $response->addJSON('sql_query', $import_text);
374 $response->addJSON('action_bookmark', $_REQUEST['action_bookmark']);
375 exit;
376 } else {
377 $run_query = false;
379 break;
380 case 2: // bookmarked query that have to be deleted
381 $bookmark = Bookmark::get($db, $id_bookmark);
382 if (! empty($bookmark)) {
383 $bookmark->delete();
384 if ($GLOBALS['is_ajax_request'] == true) {
385 $message = PMA\libraries\Message::success(
386 __('The bookmark has been deleted.')
388 $response = PMA\libraries\Response::getInstance();
389 $response->setRequestStatus($message->isSuccess());
390 $response->addJSON('message', $message);
391 $response->addJSON('action_bookmark', $_REQUEST['action_bookmark']);
392 $response->addJSON('id_bookmark', $id_bookmark);
393 exit;
394 } else {
395 $run_query = false;
396 $error = true; // this is kind of hack to skip processing the query
400 break;
402 } // end bookmarks reading
404 // Do no run query if we show PHP code
405 if (isset($GLOBALS['show_as_php'])) {
406 $run_query = false;
407 $go_sql = true;
410 // We can not read all at once, otherwise we can run out of memory
411 $memory_limit = trim(@ini_get('memory_limit'));
412 // 2 MB as default
413 if (empty($memory_limit)) {
414 $memory_limit = 2 * 1024 * 1024;
416 // In case no memory limit we work on 10MB chunks
417 if ($memory_limit == -1) {
418 $memory_limit = 10 * 1024 * 1024;
421 // Calculate value of the limit
422 $memoryUnit = mb_strtolower(substr($memory_limit, -1));
423 if ('m' == $memoryUnit) {
424 $memory_limit = (int)substr($memory_limit, 0, -1) * 1024 * 1024;
425 } elseif ('k' == $memoryUnit) {
426 $memory_limit = (int)substr($memory_limit, 0, -1) * 1024;
427 } elseif ('g' == $memoryUnit) {
428 $memory_limit = (int)substr($memory_limit, 0, -1) * 1024 * 1024 * 1024;
429 } else {
430 $memory_limit = (int)$memory_limit;
433 // Just to be sure, there might be lot of memory needed for uncompression
434 $read_limit = $memory_limit / 8;
436 // handle filenames
437 if (isset($_FILES['import_file'])) {
438 $import_file = $_FILES['import_file']['tmp_name'];
440 if (! empty($local_import_file) && ! empty($cfg['UploadDir'])) {
442 // sanitize $local_import_file as it comes from a POST
443 $local_import_file = PMA_securePath($local_import_file);
445 $import_file = PMA\libraries\Util::userDir($cfg['UploadDir'])
446 . $local_import_file;
448 } elseif (empty($import_file) || ! is_uploaded_file($import_file)) {
449 $import_file = 'none';
452 // Do we have file to import?
454 if ($import_file != 'none' && ! $error) {
456 * Handle file compression
458 $import_handle = new File($import_file);
459 $import_handle->checkUploadedFile();
460 if ($import_handle->isError()) {
461 PMA_stopImport($import_handle->getError());
463 $import_handle->setDecompressContent(true);
464 $import_handle->open();
465 if ($import_handle->isError()) {
466 PMA_stopImport($import_handle->getError());
468 } elseif (! $error) {
469 if (! isset($import_text) || empty($import_text)) {
470 $message = PMA\libraries\Message::error(
472 'No data was received to import. Either no file name was ' .
473 'submitted, or the file size exceeded the maximum size permitted ' .
474 'by your PHP configuration. See [doc@faq1-16]FAQ 1.16[/doc].'
477 PMA_stopImport($message);
481 // so we can obtain the message
482 //$_SESSION['Import_message'] = $message->getDisplay();
484 // Convert the file's charset if necessary
485 if (Encoding::isSupported() && isset($charset_of_file)) {
486 if ($charset_of_file != 'utf-8') {
487 $charset_conversion = true;
489 } elseif (isset($charset_of_file) && $charset_of_file != 'utf-8') {
490 $GLOBALS['dbi']->query('SET NAMES \'' . $charset_of_file . '\'');
491 // We can not show query in this case, it is in different charset
492 $sql_query_disabled = true;
493 $reset_charset = true;
496 // Something to skip? (because timeout has passed)
497 if (! $error && isset($_POST['skip'])) {
498 $original_skip = $skip = $_POST['skip'];
499 while ($skip > 0) {
500 PMA_importGetNextChunk($skip < $read_limit ? $skip : $read_limit);
501 // Disable read progressivity, otherwise we eat all memory!
502 $read_multiply = 1;
503 $skip -= $read_limit;
505 unset($skip);
508 // This array contain the data like numberof valid sql queries in the statement
509 // and complete valid sql statement (which affected for rows)
510 $sql_data = array('valid_sql' => array(), 'valid_queries' => 0);
512 if (! $error) {
513 // Check for file existence
514 include_once "libraries/plugin_interface.lib.php";
515 /* @var $import_plugin ImportPlugin */
516 $import_plugin = PMA_getPlugin(
517 "import",
518 $format,
519 'libraries/plugins/import/',
520 $import_type
522 if ($import_plugin == null) {
523 $message = PMA\libraries\Message::error(
524 __('Could not load import plugins, please check your installation!')
526 PMA_stopImport($message);
527 } else {
528 // Do the real import
529 try {
530 $default_fk_check = PMA\libraries\Util::handleDisableFKCheckInit();
531 $import_plugin->doImport($sql_data);
532 PMA\libraries\Util::handleDisableFKCheckCleanup($default_fk_check);
533 } catch (Exception $e) {
534 PMA\libraries\Util::handleDisableFKCheckCleanup($default_fk_check);
535 throw $e;
540 if (isset($import_handle)) {
541 $import_handle->close();
544 // Cleanup temporary file
545 if ($file_to_unlink != '') {
546 unlink($file_to_unlink);
549 // Reset charset back, if we did some changes
550 if ($reset_charset) {
551 $GLOBALS['dbi']->query('SET CHARACTER SET utf8');
552 $GLOBALS['dbi']->query(
553 'SET SESSION collation_connection =\'' . $collation_connection . '\''
557 // Show correct message
558 if (! empty($id_bookmark) && $_REQUEST['action_bookmark'] == 2) {
559 $message = PMA\libraries\Message::success(__('The bookmark has been deleted.'));
560 $display_query = $import_text;
561 $error = false; // unset error marker, it was used just to skip processing
562 } elseif (! empty($id_bookmark) && $_REQUEST['action_bookmark'] == 1) {
563 $message = PMA\libraries\Message::notice(__('Showing bookmark'));
564 } elseif ($bookmark_created) {
565 $special_message = '[br]' . sprintf(
566 __('Bookmark %s has been created.'),
567 htmlspecialchars($_POST['bkm_label'])
569 } elseif ($finished && ! $error) {
570 // Do not display the query with message, we do it separately
571 $display_query = ';';
572 if ($import_type != 'query') {
573 $message = PMA\libraries\Message::success(
574 '<em>'
575 . _ngettext(
576 'Import has been successfully finished, %d query executed.',
577 'Import has been successfully finished, %d queries executed.',
578 $executed_queries
580 . '</em>'
582 $message->addParam($executed_queries);
584 if ($import_notice) {
585 $message->addHtml($import_notice);
587 if (! empty($local_import_file)) {
588 $message->addText('(' . $local_import_file . ')');
589 } else {
590 $message->addText('(' . $_FILES['import_file']['name'] . ')');
595 // Did we hit timeout? Tell it user.
596 if ($timeout_passed) {
597 $importUrl = $err_url .= '&timeout_passed=1&offset=' . urlencode(
598 $GLOBALS['offset']
600 if (isset($local_import_file)) {
601 $importUrl .= '&local_import_file=' . urlencode($local_import_file);
603 $message = PMA\libraries\Message::error(
605 'Script timeout passed, if you want to finish import,'
606 . ' please %sresubmit the same file%s and import will resume.'
609 $message->addParamHtml('<a href="' . $importUrl . '">');
610 $message->addParamHtml('</a>');
612 if ($offset == 0 || (isset($original_skip) && $original_skip == $offset)) {
613 $message->addText(
615 'However on last run no data has been parsed,'
616 . ' this usually means phpMyAdmin won\'t be able to'
617 . ' finish this import unless you increase php time limits.'
623 // if there is any message, copy it into $_SESSION as well,
624 // so we can obtain it by AJAX call
625 if (isset($message)) {
626 $_SESSION['Import_message']['message'] = $message->getDisplay();
628 // Parse and analyze the query, for correct db and table name
629 // in case of a query typed in the query window
630 // (but if the query is too large, in case of an imported file, the parser
631 // can choke on it so avoid parsing)
632 $sqlLength = mb_strlen($sql_query);
633 if ($sqlLength <= $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) {
634 include_once 'libraries/parse_analyze.lib.php';
636 list(
637 $analyzed_sql_results,
638 $db,
639 $table
640 ) = PMA_parseAnalyze($sql_query, $db);
641 // @todo: possibly refactor
642 extract($analyzed_sql_results);
645 // There was an error?
646 if (isset($my_die)) {
647 foreach ($my_die as $key => $die) {
648 PMA\libraries\Util::mysqlDie(
649 $die['error'], $die['sql'], false, $err_url, $error
654 if ($go_sql) {
656 if (! empty($sql_data) && ($sql_data['valid_queries'] > 1)) {
657 $_SESSION['is_multi_query'] = true;
658 $sql_queries = $sql_data['valid_sql'];
659 } else {
660 $sql_queries = array($sql_query);
663 $html_output = '';
664 foreach ($sql_queries as $sql_query) {
666 // parse sql query
667 include_once 'libraries/parse_analyze.lib.php';
668 list(
669 $analyzed_sql_results,
670 $db,
671 $table
672 ) = PMA_parseAnalyze($sql_query, $db);
673 // @todo: possibly refactor
674 extract($analyzed_sql_results);
676 $html_output .= PMA_executeQueryAndGetQueryResponse(
677 $analyzed_sql_results, // analyzed_sql_results
678 false, // is_gotofile
679 $db, // db
680 $table, // table
681 null, // find_real_end
682 $_REQUEST['sql_query'], // sql_query_for_bookmark
683 null, // extra_data
684 null, // message_to_show
685 null, // message
686 null, // sql_data
687 $goto, // goto
688 $pmaThemeImage, // pmaThemeImage
689 null, // disp_query
690 null, // disp_message
691 null, // query_type
692 $sql_query, // sql_query
693 null, // selectedTables
694 null // complete_query
698 $response = PMA\libraries\Response::getInstance();
699 $response->addJSON('ajax_reload', $ajax_reload);
700 $response->addHTML($html_output);
701 exit();
703 } else if ($result) {
704 // Save a Bookmark with more than one queries (if Bookmark label given).
705 if (! empty($_POST['bkm_label']) && ! empty($import_text)) {
706 $cfgBookmark = Bookmark::getParams();
707 PMA_storeTheQueryAsBookmark(
708 $db, $cfgBookmark['user'],
709 $_REQUEST['sql_query'], $_POST['bkm_label'],
710 isset($_POST['bkm_replace']) ? $_POST['bkm_replace'] : null
714 $response = PMA\libraries\Response::getInstance();
715 $response->setRequestStatus(true);
716 $response->addJSON('message', PMA\libraries\Message::success($msg));
717 $response->addJSON(
718 'sql_query',
719 PMA\libraries\Util::getMessage($msg, $sql_query, 'success')
721 } else if ($result == false) {
722 $response = PMA\libraries\Response::getInstance();
723 $response->setRequestStatus(false);
724 $response->addJSON('message', PMA\libraries\Message::error($msg));
725 } else {
726 $active_page = $goto;
727 include '' . $goto;
730 // If there is request for ROLLBACK in the end.
731 if (isset($_REQUEST['rollback_query'])) {
732 $GLOBALS['dbi']->query('ROLLBACK');