/** * Handles the whole import logic * * @param array &$sql_data 2-element array with sql data * * @return void */ public function doImport(&$sql_data = array()) { global $error, $timeout_passed; $buffer = ''; // Defaults for parser $sql = ''; $start_pos = 0; $i = 0; $len = 0; $big_value = 2147483647; // include the space because it's mandatory $delimiter_keyword = 'DELIMITER '; $length_of_delimiter_keyword = strlen($delimiter_keyword); if (isset($_POST['sql_delimiter'])) { $sql_delimiter = $_POST['sql_delimiter']; } else { $sql_delimiter = ';'; } // Handle compatibility options $sql_modes = array(); if (isset($_REQUEST['sql_compatibility']) && 'NONE' != $_REQUEST['sql_compatibility']) { $sql_modes[] = $_REQUEST['sql_compatibility']; } if (isset($_REQUEST['sql_no_auto_value_on_zero'])) { $sql_modes[] = 'NO_AUTO_VALUE_ON_ZERO'; } if (count($sql_modes) > 0) { $GLOBALS['dbi']->tryQuery('SET SQL_MODE="' . implode(',', $sql_modes) . '"'); } unset($sql_modes); /** * will be set in PMA_importGetNextChunk() * * @global boolean $GLOBALS['finished'] */ $GLOBALS['finished'] = false; while (!($GLOBALS['finished'] && $i >= $len) && !$error && !$timeout_passed) { $data = PMA_importGetNextChunk(); if ($data === false) { // subtract data we didn't handle yet and stop processing $GLOBALS['offset'] -= strlen($buffer); break; } elseif ($data === true) { // Handle rest of buffer } else { // Append new data to buffer $buffer .= $data; // free memory unset($data); // Do not parse string when we're not at the end // and don't have ; inside if (strpos($buffer, $sql_delimiter, $i) === false && !$GLOBALS['finished']) { continue; } } // Convert CR (but not CRLF) to LF otherwise all queries // may not get executed on some platforms $buffer = preg_replace("/\r(\$|[^\n])/", "\n\$1", $buffer); // Current length of our buffer $len = strlen($buffer); // Grab some SQL queries out of it while ($i < $len) { $found_delimiter = false; // Find first interesting character $old_i = $i; // this is about 7 times faster that looking for each sequence i // one by one with strpos() $match = preg_match('/(\'|"|#|-- |\\/\\*|`|(?i)(?<![A-Z0-9_])' . $delimiter_keyword . ')/', $buffer, $matches, PREG_OFFSET_CAPTURE, $i); if ($match) { // in $matches, index 0 contains the match for the complete // expression but we don't use it $first_position = $matches[1][1]; } else { $first_position = $big_value; } /** * @todo we should not look for a delimiter that might be * inside quotes (or even double-quotes) */ // the cost of doing this one with preg_match() would be too high $first_sql_delimiter = strpos($buffer, $sql_delimiter, $i); if ($first_sql_delimiter === false) { $first_sql_delimiter = $big_value; } else { $found_delimiter = true; } // set $i to the position of the first quote, // comment.start or delimiter found $i = min($first_position, $first_sql_delimiter); if ($i == $big_value) { // none of the above was found in the string $i = $old_i; if (!$GLOBALS['finished']) { break; } // at the end there might be some whitespace... if (trim($buffer) == '') { $buffer = ''; $len = 0; break; } // We hit end of query, go there! $i = strlen($buffer) - 1; } // Grab current character $ch = $buffer[$i]; // Quotes if (strpos('\'"`', $ch) !== false) { $quote = $ch; $endq = false; while (!$endq) { // Find next quote $pos = strpos($buffer, $quote, $i + 1); /* * Behave same as MySQL and accept end of query as end * of backtick. * I know this is sick, but MySQL behaves like this: * * SELECT * FROM `table * * is treated like * * SELECT * FROM `table` */ if ($pos === false && $quote == '`' && $found_delimiter) { $pos = $first_sql_delimiter - 1; } elseif ($pos === false) { // No quote? Too short string // We hit end of string => unclosed quote, // but we handle it as end of query if ($GLOBALS['finished']) { $endq = true; $i = $len - 1; } $found_delimiter = false; break; } // Was not the quote escaped? $j = $pos - 1; while ($buffer[$j] == '\\') { $j--; } // Even count means it was not escaped $endq = ($pos - 1 - $j) % 2 == 0; // Skip the string $i = $pos; if ($first_sql_delimiter < $pos) { $found_delimiter = false; } } if (!$endq) { break; } $i++; // Aren't we at the end? if ($GLOBALS['finished'] && $i == $len) { $i--; } else { continue; } } // Not enough data to decide if (($i == $len - 1 && ($ch == '-' || $ch == '/') || $i == $len - 2 && ($ch == '-' && $buffer[$i + 1] == '-' || $ch == '/' && $buffer[$i + 1] == '*')) && !$GLOBALS['finished']) { break; } // Comments if ($ch == '#' || $i < $len - 1 && $ch == '-' && $buffer[$i + 1] == '-' && ($i < $len - 2 && $buffer[$i + 2] <= ' ' || $i == $len - 1 && $GLOBALS['finished']) || $i < $len - 1 && $ch == '/' && $buffer[$i + 1] == '*') { // Copy current string to SQL if ($start_pos != $i) { $sql .= substr($buffer, $start_pos, $i - $start_pos); } // Skip the rest $start_of_comment = $i; // do not use PHP_EOL here instead of "\n", because the export // file might have been produced on a different system $i = strpos($buffer, $ch == '/' ? '*/' : "\n", $i); // didn't we hit end of string? if ($i === false) { if ($GLOBALS['finished']) { $i = $len - 1; } else { break; } } // Skip * if ($ch == '/') { $i++; } // Skip last char $i++; // We need to send the comment part in case we are defining // a procedure or function and comments in it are valuable $sql .= substr($buffer, $start_of_comment, $i - $start_of_comment); // Next query part will start here $start_pos = $i; // Aren't we at the end? if ($i == $len) { $i--; } else { continue; } } // Change delimiter, if redefined, and skip it // (don't send to server!) if ($i + $length_of_delimiter_keyword < $len && strtoupper(substr($buffer, $i, $length_of_delimiter_keyword)) == $delimiter_keyword) { // look for EOL on the character immediately after 'DELIMITER ' // (see previous comment about PHP_EOL) $new_line_pos = strpos($buffer, "\n", $i + $length_of_delimiter_keyword); // it might happen that there is no EOL if (false === $new_line_pos) { $new_line_pos = $len; } $sql_delimiter = substr($buffer, $i + $length_of_delimiter_keyword, $new_line_pos - $i - $length_of_delimiter_keyword); $i = $new_line_pos + 1; // Next query part will start here $start_pos = $i; continue; } // End of SQL if ($found_delimiter || $GLOBALS['finished'] && $i == $len - 1) { $tmp_sql = $sql; if ($start_pos < $len) { $length_to_grab = $i - $start_pos; if (!$found_delimiter) { $length_to_grab++; } $tmp_sql .= substr($buffer, $start_pos, $length_to_grab); unset($length_to_grab); } // Do not try to execute empty SQL if (!preg_match('/^([\\s]*;)*$/', trim($tmp_sql))) { $sql = $tmp_sql; PMA_importRunQuery($sql, substr($buffer, 0, $i + strlen($sql_delimiter)), false, $sql_data); $buffer = substr($buffer, $i + strlen($sql_delimiter)); // Reset parser: $len = strlen($buffer); $sql = ''; $i = 0; $start_pos = 0; // Any chance we will get a complete query? //if ((strpos($buffer, ';') === false) //&& ! $GLOBALS['finished']) { if (strpos($buffer, $sql_delimiter) === false && !$GLOBALS['finished']) { break; } } else { $i++; $start_pos = $i; } } } // End of parser loop } // End of import loop // Commit any possible data in buffers PMA_importRunQuery('', substr($buffer, 0, $len), false, $sql_data); PMA_importRunQuery('', '', false, $sql_data); }
} if (strlen($ldi_escaped) > 0) { $sql .= ' ESCAPED BY \'' . PMA_sqlAddslashes($ldi_escaped) . '\''; } if (strlen($ldi_new_line) > 0) { if ($ldi_new_line == 'auto') { $ldi_new_line = PMA_whichCrlf() == "\n" ? '\\n' : '\\r\\n'; } $sql .= ' LINES TERMINATED BY \'' . $ldi_new_line . '\''; } if ($skip_queries > 0) { $sql .= ' IGNORE ' . $skip_queries . ' LINES'; $skip_queries = 0; } if (strlen($ldi_columns) > 0) { $sql .= ' ('; $tmp = preg_split('/,( ?)/', $ldi_columns); $cnt_tmp = count($tmp); for ($i = 0; $i < $cnt_tmp; $i++) { if ($i > 0) { $sql .= ', '; } /* Trim also `, if user already included backquoted fields */ $sql .= PMA_backquote(trim($tmp[$i], " \t\r\n\v`")); } // end for $sql .= ')'; } PMA_importRunQuery($sql, $sql); PMA_importRunQuery(); $finished = TRUE;
/** * Imports data from a single table * * @param array $table containing all table info: * <code> * $table[0] - string containing table name * $table[1] - array[] of table headers * $table[2] - array[][] of table content rows * </code> * * @global bool $analyze whether to scan for column types * * @return void */ private function _importDataOneTable($table) { $analyze = $this->_getAnalyze(); if ($analyze) { // Set the table name $this->_setTableName($table[0]); // Set generic names for table headers if they don't exist $this->_setTableHeaders($table[1], $table[2][0]); // Create the tables array to be used in PMA_buildSQL() $tables = array(); $tables[] = array($table[0], $table[1], $table[2]); // Obtain the best-fit MySQL types for each column $analyses = array(); $analyses[] = PMA_analyzeTable($tables[0]); $this->_executeImportTables($tables, $analyses); } // Commit any possible data in buffers PMA_importRunQuery(); }
/** * Handles the whole import logic * * @param array &$sql_data 2-element array with sql data * * @return void */ public function doImport(&$sql_data = array()) { global $error, $timeout_passed; // Handle compatibility options. $this->_setSQLMode($GLOBALS['dbi'], $_REQUEST); $bq = new SqlParser\Utils\BufferedQuery(); if (isset($_POST['sql_delimiter'])) { $bq->setDelimiter($_POST['sql_delimiter']); } /** * Will be set in PMA_importGetNextChunk(). * * @global bool $GLOBALS ['finished'] */ $GLOBALS['finished'] = false; while (!$error && !$timeout_passed) { // Getting the first statement, the remaining data and the last // delimiter. $statement = $bq->extract(); // If there is no full statement, we are looking for more data. if (empty($statement)) { // Importing new data. $newData = PMA_importGetNextChunk(); // Subtract data we didn't handle yet and stop processing. if ($newData === false) { $GLOBALS['offset'] -= mb_strlen($bq->query); break; } // Checking if the input buffer has finished. if ($newData === true) { $GLOBALS['finished'] = true; break; } // Convert CR (but not CRLF) to LF otherwise all queries may // not get executed on some platforms. $bq->query .= preg_replace("/\r(\$|[^\n])/", "\n\$1", $newData); continue; } // Executing the query. PMA_importRunQuery($statement, $statement, false, $sql_data); } // Extracting remaining statements. while (!$error && !$timeout_passed && !empty($bq->query)) { $statement = $bq->extract(true); if (!empty($statement)) { PMA_importRunQuery($statement, $statement, false, $sql_data); } } // Finishing. PMA_importRunQuery('', '', false, $sql_data); }
/** * Handles the whole import logic * * @param array &$sql_data 2-element array with sql data * * @return void */ public function doImport(&$sql_data = array()) { global $db, $table, $csv_terminated, $csv_enclosed, $csv_escaped, $csv_new_line, $csv_columns, $err_url; // $csv_replace and $csv_ignore should have been here, // but we use directly from $_POST global $error, $timeout_passed, $finished, $message; $replacements = array('\\n' => "\n", '\\t' => "\t", '\\r' => "\r"); $csv_terminated = strtr($csv_terminated, $replacements); $csv_enclosed = strtr($csv_enclosed, $replacements); $csv_escaped = strtr($csv_escaped, $replacements); $csv_new_line = strtr($csv_new_line, $replacements); $param_error = false; if (mb_strlen($csv_terminated) < 1) { $message = PMA\libraries\Message::error(__('Invalid parameter for CSV import: %s')); $message->addParam(__('Columns terminated with'), false); $error = true; $param_error = true; // The default dialog of MS Excel when generating a CSV produces a // semi-colon-separated file with no chance of specifying the // enclosing character. Thus, users who want to import this file // tend to remove the enclosing character on the Import dialog. // I could not find a test case where having no enclosing characters // confuses this script. // But the parser won't work correctly with strings so we allow just // one character. } elseif (mb_strlen($csv_enclosed) > 1) { $message = PMA\libraries\Message::error(__('Invalid parameter for CSV import: %s')); $message->addParam(__('Columns enclosed with'), false); $error = true; $param_error = true; // I could not find a test case where having no escaping characters // confuses this script. // But the parser won't work correctly with strings so we allow just // one character. } elseif (mb_strlen($csv_escaped) > 1) { $message = PMA\libraries\Message::error(__('Invalid parameter for CSV import: %s')); $message->addParam(__('Columns escaped with'), false); $error = true; $param_error = true; } elseif (mb_strlen($csv_new_line) != 1 && $csv_new_line != 'auto') { $message = PMA\libraries\Message::error(__('Invalid parameter for CSV import: %s')); $message->addParam(__('Lines terminated with'), false); $error = true; $param_error = true; } // If there is an error in the parameters entered, // indicate that immediately. if ($param_error) { PMA\libraries\Util::mysqlDie($message->getMessage(), '', false, $err_url); } $buffer = ''; $required_fields = 0; if (!$this->_getAnalyze()) { $sql_template = 'INSERT'; if (isset($_POST['csv_ignore'])) { $sql_template .= ' IGNORE'; } $sql_template .= ' INTO ' . PMA\libraries\Util::backquote($table); $tmp_fields = $GLOBALS['dbi']->getColumns($db, $table); if (empty($csv_columns)) { $fields = $tmp_fields; } else { $sql_template .= ' ('; $fields = array(); $tmp = preg_split('/,( ?)/', $csv_columns); foreach ($tmp as $key => $val) { if (count($fields) > 0) { $sql_template .= ', '; } /* Trim also `, if user already included backquoted fields */ $val = trim($val, " \t\r\n\v`"); $found = false; foreach ($tmp_fields as $field) { if ($field['Field'] == $val) { $found = true; break; } } if (!$found) { $message = PMA\libraries\Message::error(__('Invalid column (%s) specified! Ensure that columns' . ' names are spelled correctly, separated by commas' . ', and not enclosed in quotes.')); $message->addParam($val); $error = true; break; } $fields[] = $field; $sql_template .= PMA\libraries\Util::backquote($val); } $sql_template .= ') '; } $required_fields = count($fields); $sql_template .= ' VALUES ('; } // Defaults for parser $i = 0; $len = 0; $lastlen = null; $line = 1; $lasti = -1; $values = array(); $csv_finish = false; $tempRow = array(); $rows = array(); $col_names = array(); $tables = array(); $col_count = 0; $max_cols = 0; $csv_terminated_len = mb_strlen($csv_terminated); while (!($finished && $i >= $len) && !$error && !$timeout_passed) { $data = PMA_importGetNextChunk(); if ($data === false) { // subtract data we didn't handle yet and stop processing $GLOBALS['offset'] -= strlen($buffer); break; } elseif ($data === true) { // Handle rest of buffer } else { // Append new data to buffer $buffer .= $data; unset($data); // Force a trailing new line at EOF to prevent parsing problems if ($finished && $buffer) { $finalch = mb_substr($buffer, -1); if ($csv_new_line == 'auto' && $finalch != "\r" && $finalch != "\n") { $buffer .= "\n"; } elseif ($csv_new_line != 'auto' && $finalch != $csv_new_line) { $buffer .= $csv_new_line; } } // Do not parse string when we're not at the end // and don't have new line inside if ($csv_new_line == 'auto' && mb_strpos($buffer, "\r") === false && mb_strpos($buffer, "\n") === false || $csv_new_line != 'auto' && mb_strpos($buffer, $csv_new_line) === false) { continue; } } // Current length of our buffer $len = mb_strlen($buffer); // Currently parsed char $ch = mb_substr($buffer, $i, 1); if ($csv_terminated_len > 1 && $ch == $csv_terminated[0]) { $ch = $this->readCsvTerminatedString($buffer, $ch, $i, $csv_terminated_len); $i += $csv_terminated_len - 1; } while ($i < $len) { // Deadlock protection if ($lasti == $i && $lastlen == $len) { $message = PMA\libraries\Message::error(__('Invalid format of CSV input on line %d.')); $message->addParam($line); $error = true; break; } $lasti = $i; $lastlen = $len; // This can happen with auto EOL and \r at the end of buffer if (!$csv_finish) { // Grab empty field if ($ch == $csv_terminated) { if ($i == $len - 1) { break; } $values[] = ''; $i++; $ch = mb_substr($buffer, $i, 1); if ($csv_terminated_len > 1 && $ch == $csv_terminated[0]) { $ch = $this->readCsvTerminatedString($buffer, $ch, $i, $csv_terminated_len); $i += $csv_terminated_len - 1; } continue; } // Grab one field $fallbacki = $i; if ($ch == $csv_enclosed) { if ($i == $len - 1) { break; } $need_end = true; $i++; $ch = mb_substr($buffer, $i, 1); if ($csv_terminated_len > 1 && $ch == $csv_terminated[0]) { $ch = $this->readCsvTerminatedString($buffer, $ch, $i, $csv_terminated_len); $i += $csv_terminated_len - 1; } } else { $need_end = false; } $fail = false; $value = ''; while ($need_end && ($ch != $csv_enclosed || $csv_enclosed == $csv_escaped) || !$need_end && !($ch == $csv_terminated || $ch == $csv_new_line || $csv_new_line == 'auto' && ($ch == "\r" || $ch == "\n"))) { if ($ch == $csv_escaped) { if ($i == $len - 1) { $fail = true; break; } $i++; $ch = mb_substr($buffer, $i, 1); if ($csv_terminated_len > 1 && $ch == $csv_terminated[0]) { $ch = $this->readCsvTerminatedString($buffer, $ch, $i, $csv_terminated_len); $i += $csv_terminated_len - 1; } if ($csv_enclosed == $csv_escaped && ($ch == $csv_terminated || $ch == $csv_new_line || $csv_new_line == 'auto' && ($ch == "\r" || $ch == "\n"))) { break; } } $value .= $ch; if ($i == $len - 1) { if (!$finished) { $fail = true; } break; } $i++; $ch = mb_substr($buffer, $i, 1); if ($csv_terminated_len > 1 && $ch == $csv_terminated[0]) { $ch = $this->readCsvTerminatedString($buffer, $ch, $i, $csv_terminated_len); $i += $csv_terminated_len - 1; } } // unquoted NULL string if (false === $need_end && $value === 'NULL') { $value = null; } if ($fail) { $i = $fallbacki; $ch = mb_substr($buffer, $i, 1); if ($csv_terminated_len > 1 && $ch == $csv_terminated[0]) { $i += $csv_terminated_len - 1; } break; } // Need to strip trailing enclosing char? if ($need_end && $ch == $csv_enclosed) { if ($finished && $i == $len - 1) { $ch = null; } elseif ($i == $len - 1) { $i = $fallbacki; $ch = mb_substr($buffer, $i, 1); if ($csv_terminated_len > 1 && $ch == $csv_terminated[0]) { $i += $csv_terminated_len - 1; } break; } else { $i++; $ch = mb_substr($buffer, $i, 1); if ($csv_terminated_len > 1 && $ch == $csv_terminated[0]) { $ch = $this->readCsvTerminatedString($buffer, $ch, $i, $csv_terminated_len); $i += $csv_terminated_len - 1; } } } // Are we at the end? if ($ch == $csv_new_line || $csv_new_line == 'auto' && ($ch == "\r" || $ch == "\n") || $finished && $i == $len - 1) { $csv_finish = true; } // Go to next char if ($ch == $csv_terminated) { if ($i == $len - 1) { $i = $fallbacki; $ch = mb_substr($buffer, $i, 1); if ($csv_terminated_len > 1 && $ch == $csv_terminated[0]) { $i += $csv_terminated_len - 1; } break; } $i++; $ch = mb_substr($buffer, $i, 1); if ($csv_terminated_len > 1 && $ch == $csv_terminated[0]) { $ch = $this->readCsvTerminatedString($buffer, $ch, $i, $csv_terminated_len); $i += $csv_terminated_len - 1; } } // If everything went okay, store value $values[] = $value; } // End of line if ($csv_finish || $ch == $csv_new_line || $csv_new_line == 'auto' && ($ch == "\r" || $ch == "\n")) { if ($csv_new_line == 'auto' && $ch == "\r") { // Handle "\r\n" if ($i >= $len - 2 && !$finished) { break; // We need more data to decide new line } if (mb_substr($buffer, $i + 1, 1) == "\n") { $i++; } } // We didn't parse value till the end of line, so there was // empty one if (!$csv_finish) { $values[] = ''; } if ($this->_getAnalyze()) { foreach ($values as $val) { $tempRow[] = $val; ++$col_count; } if ($col_count > $max_cols) { $max_cols = $col_count; } $col_count = 0; $rows[] = $tempRow; $tempRow = array(); } else { // Do we have correct count of values? if (count($values) != $required_fields) { // Hack for excel if ($values[count($values) - 1] == ';') { unset($values[count($values) - 1]); } else { $message = PMA\libraries\Message::error(__('Invalid column count in CSV input' . ' on line %d.')); $message->addParam($line); $error = true; break; } } $first = true; $sql = $sql_template; foreach ($values as $key => $val) { if (!$first) { $sql .= ', '; } if ($val === null) { $sql .= 'NULL'; } else { $sql .= '\'' . PMA\libraries\Util::sqlAddSlashes($val) . '\''; } $first = false; } $sql .= ')'; if (isset($_POST['csv_replace'])) { $sql .= " ON DUPLICATE KEY UPDATE "; foreach ($fields as $field) { $fieldName = PMA\libraries\Util::backquote($field['Field']); $sql .= $fieldName . " = VALUES(" . $fieldName . "), "; } $sql = rtrim($sql, ', '); } /** * @todo maybe we could add original line to verbose * SQL in comment */ PMA_importRunQuery($sql, $sql, $sql_data); } $line++; $csv_finish = false; $values = array(); $buffer = mb_substr($buffer, $i + 1); $len = mb_strlen($buffer); $i = 0; $lasti = -1; $ch = mb_substr($buffer, 0, 1); } } // End of parser loop } // End of import loop if ($this->_getAnalyze()) { /* Fill out all rows */ $num_rows = count($rows); for ($i = 0; $i < $num_rows; ++$i) { for ($j = count($rows[$i]); $j < $max_cols; ++$j) { $rows[$i][] = 'NULL'; } } if (isset($_REQUEST['csv_col_names'])) { $col_names = array_splice($rows, 0, 1); $col_names = $col_names[0]; // MySQL column names can't end with a space character. foreach ($col_names as $key => $col_name) { $col_names[$key] = rtrim($col_name); } } if (isset($col_names) && count($col_names) != $max_cols || !isset($col_names)) { // Fill out column names for ($i = 0; $i < $max_cols; ++$i) { $col_names[] = 'COL ' . ($i + 1); } } if (mb_strlen($db)) { $result = $GLOBALS['dbi']->fetchResult('SHOW TABLES'); $tbl_name = 'TABLE ' . (count($result) + 1); } else { $tbl_name = 'TBL_NAME'; } $tables[] = array($tbl_name, $col_names, $rows); /* Obtain the best-fit MySQL types for each column */ $analyses = array(); $analyses[] = PMA_analyzeTable($tables[0]); /** * string $db_name (no backquotes) * * array $table = array(table_name, array() column_names, array()() rows) * array $tables = array of "$table"s * * array $analysis = array(array() column_types, array() column_sizes) * array $analyses = array of "$analysis"s * * array $create = array of SQL strings * * array $options = an associative array of options */ /* Set database name to the currently selected one, if applicable */ list($db_name, $options) = $this->getDbnameAndOptions($db, 'CSV_DB'); /* Non-applicable parameters */ $create = null; /* Created and execute necessary SQL statements from data */ PMA_buildSQL($db_name, $tables, $analyses, $create, $options, $sql_data); unset($tables); unset($analyses); } // Commit any possible data in buffers PMA_importRunQuery('', '', $sql_data); if (count($values) != 0 && !$error) { $message = PMA\libraries\Message::error(__('Invalid format of CSV input on line %d.')); $message->addParam($line); $error = true; } }
/** * Handles the whole import logic * * @return void */ public function doImport() { global $db, $error, $finished, $compression, $import_file, $local_import_file, $message; $GLOBALS['finished'] = false; $shp = new ShapeFile(1); // If the zip archive has more than one file, // get the correct content to the buffer from .shp file. if ($compression == 'application/zip' && PMA_getNoOfFilesInZip($import_file) > 1) { $zip_content = PMA_getZipContents($import_file, '/^.*\\.shp$/i'); $GLOBALS['import_text'] = $zip_content['data']; } $temp_dbf_file = false; // We need dbase extension to handle .dbf file if (extension_loaded('dbase')) { // If we can extract the zip archive to 'TempDir' // and use the files in it for import if ($compression == 'application/zip' && !empty($GLOBALS['cfg']['TempDir']) && is_writable($GLOBALS['cfg']['TempDir'])) { $dbf_file_name = PMA_findFileFromZipArchive('/^.*\\.dbf$/i', $import_file); // If the corresponding .dbf file is in the zip archive if ($dbf_file_name) { // Extract the .dbf file and point to it. $extracted = PMA_zipExtract($import_file, realpath($GLOBALS['cfg']['TempDir']), array($dbf_file_name)); if ($extracted) { $dbf_file_path = realpath($GLOBALS['cfg']['TempDir']) . (PMA_IS_WINDOWS ? '\\' : '/') . $dbf_file_name; $temp_dbf_file = true; // Replace the .dbf with .*, as required // by the bsShapeFiles library. $file_name = mb_substr($dbf_file_path, 0, mb_strlen($dbf_file_path) - 4) . '.*'; $shp->FileName = $file_name; } } } elseif (!empty($local_import_file) && !empty($GLOBALS['cfg']['UploadDir']) && $compression == 'none') { // If file is in UploadDir, use .dbf file in the same UploadDir // to load extra data. // Replace the .shp with .*, // so the bsShapeFiles library correctly locates .dbf file. $file_name = mb_substr($import_file, 0, mb_strlen($import_file) - 4) . '.*'; $shp->FileName = $file_name; } } // Load data $shp->loadFromFile(''); if ($shp->lastError != "") { $error = true; $message = PMA\libraries\Message::error(__('There was an error importing the ESRI shape file: "%s".')); $message->addParam($shp->lastError); return; } // Delete the .dbf file extracted to 'TempDir' if ($temp_dbf_file && isset($dbf_file_path) && file_exists($dbf_file_path)) { unlink($dbf_file_path); } $esri_types = array(0 => 'Null Shape', 1 => 'Point', 3 => 'PolyLine', 5 => 'Polygon', 8 => 'MultiPoint', 11 => 'PointZ', 13 => 'PolyLineZ', 15 => 'PolygonZ', 18 => 'MultiPointZ', 21 => 'PointM', 23 => 'PolyLineM', 25 => 'PolygonM', 28 => 'MultiPointM', 31 => 'MultiPatch'); switch ($shp->shapeType) { // ESRI Null Shape case 0: break; // ESRI Point // ESRI Point case 1: $gis_type = 'point'; break; // ESRI PolyLine // ESRI PolyLine case 3: $gis_type = 'multilinestring'; break; // ESRI Polygon // ESRI Polygon case 5: $gis_type = 'multipolygon'; break; // ESRI MultiPoint // ESRI MultiPoint case 8: $gis_type = 'multipoint'; break; default: $error = true; if (!isset($esri_types[$shp->shapeType])) { $message = PMA\libraries\Message::error(__('You tried to import an invalid file or the imported file' . ' contains invalid data!')); } else { $message = PMA\libraries\Message::error(__('MySQL Spatial Extension does not support ESRI type "%s".')); $message->addParam($esri_types[$shp->shapeType]); } return; } if (isset($gis_type)) { /** @var GISMultilinestring|\PMA\libraries\gis\GISMultipoint|\PMA\libraries\gis\GISPoint|GISPolygon $gis_obj */ $gis_obj = GISFactory::factory($gis_type); } else { $gis_obj = null; } $num_rows = count($shp->records); // If .dbf file is loaded, the number of extra data columns $num_data_cols = isset($shp->DBFHeader) ? count($shp->DBFHeader) : 0; $rows = array(); $col_names = array(); if ($num_rows != 0) { foreach ($shp->records as $record) { $tempRow = array(); if ($gis_obj == null) { $tempRow[] = null; } else { $tempRow[] = "GeomFromText('" . $gis_obj->getShape($record->SHPData) . "')"; } if (isset($shp->DBFHeader)) { foreach ($shp->DBFHeader as $c) { $cell = trim($record->DBFData[$c[0]]); if (!strcmp($cell, '')) { $cell = 'NULL'; } $tempRow[] = $cell; } } $rows[] = $tempRow; } } if (count($rows) == 0) { $error = true; $message = PMA\libraries\Message::error(__('The imported file does not contain any data!')); return; } // Column names for spatial column and the rest of the columns, // if they are available $col_names[] = 'SPATIAL'; for ($n = 0; $n < $num_data_cols; $n++) { $col_names[] = $shp->DBFHeader[$n][0]; } // Set table name based on the number of tables if (mb_strlen($db)) { $result = $GLOBALS['dbi']->fetchResult('SHOW TABLES'); $table_name = 'TABLE ' . (count($result) + 1); } else { $table_name = 'TBL_NAME'; } $tables = array(array($table_name, $col_names, $rows)); // Use data from shape file to chose best-fit MySQL types for each column $analyses = array(); $analyses[] = PMA_analyzeTable($tables[0]); $table_no = 0; $spatial_col = 0; $analyses[$table_no][TYPES][$spatial_col] = GEOMETRY; $analyses[$table_no][FORMATTEDSQL][$spatial_col] = true; // Set database name to the currently selected one, if applicable if (mb_strlen($db)) { $db_name = $db; $options = array('create_db' => false); } else { $db_name = 'SHP_DB'; $options = null; } // Created and execute necessary SQL statements from data $null_param = null; PMA_buildSQL($db_name, $tables, $analyses, $null_param, $options); unset($tables); unset($analyses); $finished = true; $error = false; // Commit any possible data in buffers PMA_importRunQuery(); }
function running($import_handle) { global $finished; $buffer = $ret = ''; // Defaults for parser $offset = 0; if (isset($_POST['sql_delimiter'])) { $sql_delimiter = $_POST['sql_delimiter']; } else { $sql_delimiter = '/*DELIMITER*/'; //$sql_delimiter = ';/*DELIMITER*/'; // Ruslan - should be without leading ; //$sql_delimiter = ';'; } // Handle compatibility option if (isset($_REQUEST['sql_compatibility'])) { PMA_DBI_try_query('SET SQL_MODE="' . $_REQUEST['sql_compatibility'] . '"'); } while (!$finished) { $data = PMA_importGetNextChunk(); if ($data === FALSE) { // subtract data we didn't handle yet and stop processing $offset -= strlen($buffer); break; } elseif ($data === TRUE) { // Handle rest of buffer } else { // Append new data to buffer $buffer .= $data; // Do not parse string when we're not at the end and don't have ; inside if (strpos($buffer, $sql_delimiter) === FALSE && !$finished) { continue; } $sql_queries = explode($sql_delimiter, $buffer); $c_queries = count($sql_queries); if (!$finished) { $buffer = $sql_queries[$c_queries - 1]; $sql_queries = array_splice($sql_queries, 0, $c_queries - 1); } foreach ($sql_queries as $query) { if (strlen($query) != 0) { $ret .= PMA_importRunQuery($query, ''); } } } } return $ret; }
/** * Handles the whole import logic * * @return void */ public function doImport() { global $db, $error, $timeout_passed, $finished; $i = 0; $len = 0; $buffer = ""; /** * Read in the file via PMA_importGetNextChunk so that * it can process compressed files */ while (!($finished && $i >= $len) && !$error && !$timeout_passed) { $data = PMA_importGetNextChunk(); if ($data === false) { /* subtract data we didn't handle yet and stop processing */ $GLOBALS['offset'] -= strlen($buffer); break; } elseif ($data === true) { /* Handle rest of buffer */ } else { /* Append new data to buffer */ $buffer .= $data; unset($data); } } unset($data); /** * Disable loading of external XML entities. */ libxml_disable_entity_loader(); /** * Load the XML string * * The option LIBXML_COMPACT is specified because it can * result in increased performance without the need to * alter the code in any way. It's basically a freebee. */ $xml = simplexml_load_string($buffer, "SimpleXMLElement", LIBXML_COMPACT); unset($buffer); if ($xml === false) { $sheets = array(); $GLOBALS['message'] = PMA_Message::error(__('The XML file specified was either malformed or incomplete.' . ' Please correct the issue and try again.')); $GLOBALS['error'] = true; } else { $root = $xml->children('office', true)->{'body'}->{'spreadsheet'}; if (empty($root)) { $sheets = array(); $GLOBALS['message'] = PMA_Message::error(__('Could not parse OpenDocument Spreadsheet!')); $GLOBALS['error'] = true; } else { $sheets = $root->children('table', true); } } $tables = array(); $max_cols = 0; $col_count = 0; $col_names = array(); $tempRow = array(); $tempRows = array(); $rows = array(); /* Iterate over tables */ foreach ($sheets as $sheet) { $col_names_in_first_row = isset($_REQUEST['ods_col_names']); /* Iterate over rows */ foreach ($sheet as $row) { $type = $row->getName(); if (strcmp('table-row', $type)) { continue; } /* Iterate over columns */ foreach ($row as $cell) { $text = $cell->children('text', true); $cell_attrs = $cell->attributes('office', true); if (count($text) != 0) { $attr = $cell->attributes('table', true); $num_repeat = (int) $attr['number-columns-repeated']; $num_iterations = $num_repeat ? $num_repeat : 1; for ($k = 0; $k < $num_iterations; $k++) { $value = $this->getValue($cell_attrs, $text); if (!$col_names_in_first_row) { $tempRow[] = $value; } else { // MySQL column names can't end with a space // character. $col_names[] = rtrim($value); } ++$col_count; } continue; } $attr = $cell->attributes('table', true); $num_null = (int) $attr['number-columns-repeated']; if ($num_null) { if (!$col_names_in_first_row) { for ($i = 0; $i < $num_null; ++$i) { $tempRow[] = 'NULL'; ++$col_count; } } else { for ($i = 0; $i < $num_null; ++$i) { $col_names[] = PMA_getColumnAlphaName($col_count + 1); ++$col_count; } } } else { if (!$col_names_in_first_row) { $tempRow[] = 'NULL'; } else { $col_names[] = PMA_getColumnAlphaName($col_count + 1); } ++$col_count; } } //Endforeach /* Find the widest row */ if ($col_count > $max_cols) { $max_cols = $col_count; } /* Don't include a row that is full of NULL values */ if (!$col_names_in_first_row) { if ($_REQUEST['ods_empty_rows']) { foreach ($tempRow as $cell) { if (strcmp('NULL', $cell)) { $tempRows[] = $tempRow; break; } } } else { $tempRows[] = $tempRow; } } $col_count = 0; $col_names_in_first_row = false; $tempRow = array(); } /* Skip over empty sheets */ if (count($tempRows) == 0 || count($tempRows[0]) == 0) { $col_names = array(); $tempRow = array(); $tempRows = array(); continue; } /** * Fill out each row as necessary to make * every one exactly as wide as the widest * row. This included column names. */ /* Fill out column names */ for ($i = count($col_names); $i < $max_cols; ++$i) { $col_names[] = PMA_getColumnAlphaName($i + 1); } /* Fill out all rows */ $num_rows = count($tempRows); for ($i = 0; $i < $num_rows; ++$i) { for ($j = count($tempRows[$i]); $j < $max_cols; ++$j) { $tempRows[$i][] = 'NULL'; } } /* Store the table name so we know where to place the row set */ $tbl_attr = $sheet->attributes('table', true); $tables[] = array((string) $tbl_attr['name']); /* Store the current sheet in the accumulator */ $rows[] = array((string) $tbl_attr['name'], $col_names, $tempRows); $tempRows = array(); $col_names = array(); $max_cols = 0; } unset($tempRow); unset($tempRows); unset($col_names); unset($sheets); unset($xml); /** * Bring accumulated rows into the corresponding table */ $num_tbls = count($tables); for ($i = 0; $i < $num_tbls; ++$i) { for ($j = 0; $j < count($rows); ++$j) { if (strcmp($tables[$i][TBL_NAME], $rows[$j][TBL_NAME])) { continue; } if (!isset($tables[$i][COL_NAMES])) { $tables[$i][] = $rows[$j][COL_NAMES]; } $tables[$i][ROWS] = $rows[$j][ROWS]; } } /* No longer needed */ unset($rows); /* Obtain the best-fit MySQL types for each column */ $analyses = array(); $len = count($tables); for ($i = 0; $i < $len; ++$i) { $analyses[] = PMA_analyzeTable($tables[$i]); } /** * string $db_name (no backquotes) * * array $table = array(table_name, array() column_names, array()() rows) * array $tables = array of "$table"s * * array $analysis = array(array() column_types, array() column_sizes) * array $analyses = array of "$analysis"s * * array $create = array of SQL strings * * array $options = an associative array of options */ /* Set database name to the currently selected one, if applicable */ list($db_name, $options) = $this->getDbnameAndOptions($db, 'ODS_DB'); /* Non-applicable parameters */ $create = null; /* Created and execute necessary SQL statements from data */ PMA_buildSQL($db_name, $tables, $analyses, $create, $options); unset($tables); unset($analyses); /* Commit any possible data in buffers */ PMA_importRunQuery(); }
/** * Handles the whole import logic * * @return void */ public function doImport() { global $error, $timeout_passed, $finished, $db; $i = 0; $len = 0; $buffer = ""; /** * Read in the file via PMA_importGetNextChunk so that * it can process compressed files */ while (!($finished && $i >= $len) && !$error && !$timeout_passed) { $data = PMA_importGetNextChunk(); if ($data === false) { /* subtract data we didn't handle yet and stop processing */ $GLOBALS['offset'] -= strlen($buffer); break; } elseif ($data === true) { /* Handle rest of buffer */ } else { /* Append new data to buffer */ $buffer .= $data; unset($data); } } unset($data); /** * Disable loading of external XML entities. */ libxml_disable_entity_loader(); /** * Load the XML string * * The option LIBXML_COMPACT is specified because it can * result in increased performance without the need to * alter the code in any way. It's basically a freebee. */ $xml = @simplexml_load_string($buffer, "SimpleXMLElement", LIBXML_COMPACT); unset($buffer); /** * The XML was malformed */ if ($xml === false) { PMA\libraries\Message::error(__('The XML file specified was either malformed or incomplete.' . ' Please correct the issue and try again.'))->display(); unset($xml); $GLOBALS['finished'] = false; return; } /** * Table accumulator */ $tables = array(); /** * Row accumulator */ $rows = array(); /** * Temp arrays */ $tempRow = array(); $tempCells = array(); /** * CREATE code included (by default: no) */ $struct_present = false; /** * Analyze the data in each table */ $namespaces = $xml->getNameSpaces(true); /** * Get the database name, collation and charset */ $db_attr = $xml->children($namespaces['pma'])->{'structure_schemas'}->{'database'}; if ($db_attr instanceof SimpleXMLElement) { $db_attr = $db_attr->attributes(); $db_name = (string) $db_attr['name']; $collation = (string) $db_attr['collation']; $charset = (string) $db_attr['charset']; } else { /** * If the structure section is not present * get the database name from the data section */ $db_attr = $xml->children()->attributes(); $db_name = (string) $db_attr['name']; $collation = null; $charset = null; } /** * The XML was malformed */ if ($db_name === null) { PMA\libraries\Message::error(__('The XML file specified was either malformed or incomplete.' . ' Please correct the issue and try again.'))->display(); unset($xml); $GLOBALS['finished'] = false; return; } /** * Retrieve the structure information */ if (isset($namespaces['pma'])) { /** * Get structures for all tables * * @var SimpleXMLElement $struct */ $struct = $xml->children($namespaces['pma']); $create = array(); /** @var SimpleXMLElement $val1 */ foreach ($struct as $val1) { /** @var SimpleXMLElement $val2 */ foreach ($val1 as $val2) { // Need to select the correct database for the creation of // tables, views, triggers, etc. /** * @todo Generating a USE here blocks importing of a table * into another database. */ $attrs = $val2->attributes(); $create[] = "USE " . PMA\libraries\Util::backquote($attrs["name"]); foreach ($val2 as $val3) { /** * Remove the extra cosmetic spacing */ $val3 = str_replace(" ", "", (string) $val3); $create[] = $val3; } } } $struct_present = true; } /** * Move down the XML tree to the actual data */ $xml = $xml->children()->children(); $data_present = false; /** * Only attempt to analyze/collect data if there is data present */ if ($xml && @count($xml->children())) { $data_present = true; /** * Process all database content */ foreach ($xml as $v1) { $tbl_attr = $v1->attributes(); $isInTables = false; $num_tables = count($tables); for ($i = 0; $i < $num_tables; ++$i) { if (!strcmp($tables[$i][TBL_NAME], (string) $tbl_attr['name'])) { $isInTables = true; break; } } if (!$isInTables) { $tables[] = array((string) $tbl_attr['name']); } foreach ($v1 as $v2) { $row_attr = $v2->attributes(); if (!array_search((string) $row_attr['name'], $tempRow)) { $tempRow[] = (string) $row_attr['name']; } $tempCells[] = (string) $v2; } $rows[] = array((string) $tbl_attr['name'], $tempRow, $tempCells); $tempRow = array(); $tempCells = array(); } unset($tempRow); unset($tempCells); unset($xml); /** * Bring accumulated rows into the corresponding table */ $num_tables = count($tables); for ($i = 0; $i < $num_tables; ++$i) { $num_rows = count($rows); for ($j = 0; $j < $num_rows; ++$j) { if (!strcmp($tables[$i][TBL_NAME], $rows[$j][TBL_NAME])) { if (!isset($tables[$i][COL_NAMES])) { $tables[$i][] = $rows[$j][COL_NAMES]; } $tables[$i][ROWS][] = $rows[$j][ROWS]; } } } unset($rows); if (!$struct_present) { $analyses = array(); $len = count($tables); for ($i = 0; $i < $len; ++$i) { $analyses[] = PMA_analyzeTable($tables[$i]); } } } unset($xml); unset($tempCells); unset($rows); /** * Only build SQL from data if there is data present */ if ($data_present) { /** * Set values to NULL if they were not present * to maintain PMA_buildSQL() call integrity */ if (!isset($analyses)) { $analyses = null; if (!$struct_present) { $create = null; } } } /** * string $db_name (no backquotes) * * array $table = array(table_name, array() column_names, array()() rows) * array $tables = array of "$table"s * * array $analysis = array(array() column_types, array() column_sizes) * array $analyses = array of "$analysis"s * * array $create = array of SQL strings * * array $options = an associative array of options */ /* Set database name to the currently selected one, if applicable */ if (strlen($db)) { /* Override the database name in the XML file, if one is selected */ $db_name = $db; $options = array('create_db' => false); } else { if ($db_name === null) { $db_name = 'XML_DB'; } /* Set database collation/charset */ $options = array('db_collation' => $collation, 'db_charset' => $charset); } /* Created and execute necessary SQL statements from data */ PMA_buildSQL($db_name, $tables, $analyses, $create, $options); unset($analyses); unset($tables); unset($create); /* Commit any possible data in buffers */ PMA_importRunQuery(); }
/** * Handles the whole import logic * * @param array &$sql_data 2-element array with sql data * * @return void */ public function doImport(&$sql_data = array()) { global $finished, $import_file, $compression, $charset_conversion, $table; global $ldi_local_option, $ldi_replace, $ldi_ignore, $ldi_terminated, $ldi_enclosed, $ldi_escaped, $ldi_new_line, $skip_queries, $ldi_columns; if ($import_file == 'none' || $compression != 'none' || $charset_conversion) { // We handle only some kind of data! $GLOBALS['message'] = PMA\libraries\Message::error(__('This plugin does not support compressed imports!')); $GLOBALS['error'] = true; return; } $sql = 'LOAD DATA'; if (isset($ldi_local_option)) { $sql .= ' LOCAL'; } $sql .= ' INFILE \'' . $GLOBALS['dbi']->escapeString($import_file) . '\''; if (isset($ldi_replace)) { $sql .= ' REPLACE'; } elseif (isset($ldi_ignore)) { $sql .= ' IGNORE'; } $sql .= ' INTO TABLE ' . PMA\libraries\Util::backquote($table); if (strlen($ldi_terminated) > 0) { $sql .= ' FIELDS TERMINATED BY \'' . $ldi_terminated . '\''; } if (strlen($ldi_enclosed) > 0) { $sql .= ' ENCLOSED BY \'' . $GLOBALS['dbi']->escapeString($ldi_enclosed) . '\''; } if (strlen($ldi_escaped) > 0) { $sql .= ' ESCAPED BY \'' . $GLOBALS['dbi']->escapeString($ldi_escaped) . '\''; } if (strlen($ldi_new_line) > 0) { if ($ldi_new_line == 'auto') { $ldi_new_line = PMA\libraries\Util::whichCrlf() == "\n" ? '\\n' : '\\r\\n'; } $sql .= ' LINES TERMINATED BY \'' . $ldi_new_line . '\''; } if ($skip_queries > 0) { $sql .= ' IGNORE ' . $skip_queries . ' LINES'; $skip_queries = 0; } if (strlen($ldi_columns) > 0) { $sql .= ' ('; $tmp = preg_split('/,( ?)/', $ldi_columns); $cnt_tmp = count($tmp); for ($i = 0; $i < $cnt_tmp; $i++) { if ($i > 0) { $sql .= ', '; } /* Trim also `, if user already included backquoted fields */ $sql .= PMA\libraries\Util::backquote(trim($tmp[$i], " \t\r\n\v`")); } // end for $sql .= ')'; } PMA_importRunQuery($sql, $sql, $sql_data); PMA_importRunQuery('', '', $sql_data); $finished = true; }
/** * Builds and executes SQL statements to create the database and tables * as necessary, as well as insert all the data. * * @param string $db_name Name of the database * @param array &$tables Array of tables for the specified database * @param array &$analyses Analyses of the tables * @param array &$additional_sql Additional SQL statements to be executed * @param array $options Associative array of options * * @return void * @access public * * @link http://wiki.phpmyadmin.net/pma/Import */ function PMA_buildSQL($db_name, &$tables, &$analyses = null, &$additional_sql = null, $options = null) { /* Take care of the options */ if (isset($options['db_collation']) && !is_null($options['db_collation'])) { $collation = $options['db_collation']; } else { $collation = "utf8_general_ci"; } if (isset($options['db_charset']) && !is_null($options['db_charset'])) { $charset = $options['db_charset']; } else { $charset = "utf8"; } if (isset($options['create_db'])) { $create_db = $options['create_db']; } else { $create_db = true; } /* Create SQL code to handle the database */ $sql = array(); if ($create_db) { if (PMA_DRIZZLE) { $sql[] = "CREATE DATABASE IF NOT EXISTS " . PMA_Util::backquote($db_name) . " COLLATE " . $collation; } else { $sql[] = "CREATE DATABASE IF NOT EXISTS " . PMA_Util::backquote($db_name) . " DEFAULT CHARACTER SET " . $charset . " COLLATE " . $collation; } } /** * The calling plug-in should include this statement, * if necessary, in the $additional_sql parameter * * $sql[] = "USE " . backquote($db_name); */ /* Execute the SQL statements create above */ $sql_len = count($sql); for ($i = 0; $i < $sql_len; ++$i) { PMA_importRunQuery($sql[$i], $sql[$i]); } /* No longer needed */ unset($sql); /* Run the $additional_sql statements supplied by the caller plug-in */ if ($additional_sql != null) { /* Clean the SQL first */ $additional_sql_len = count($additional_sql); /** * Only match tables for now, because CREATE IF NOT EXISTS * syntax is lacking or nonexisting for views, triggers, * functions, and procedures. * * See: http://bugs.mysql.com/bug.php?id=15287 * * To the best of my knowledge this is still an issue. * * $pattern = 'CREATE (TABLE|VIEW|TRIGGER|FUNCTION|PROCEDURE)'; */ $pattern = '/CREATE [^`]*(TABLE)/'; $replacement = 'CREATE \\1 IF NOT EXISTS'; /* Change CREATE statements to CREATE IF NOT EXISTS to support * inserting into existing structures */ for ($i = 0; $i < $additional_sql_len; ++$i) { $additional_sql[$i] = preg_replace($pattern, $replacement, $additional_sql[$i]); /* Execute the resulting statements */ PMA_importRunQuery($additional_sql[$i], $additional_sql[$i]); } } if ($analyses != null) { $type_array = array(NONE => "NULL", VARCHAR => "varchar", INT => "int", DECIMAL => "decimal", BIGINT => "bigint", GEOMETRY => 'geometry'); /* TODO: Do more checking here to make sure they really are matched */ if (count($tables) != count($analyses)) { exit; } /* Create SQL code to create the tables */ $num_tables = count($tables); for ($i = 0; $i < $num_tables; ++$i) { $num_cols = count($tables[$i][COL_NAMES]); $tempSQLStr = "CREATE TABLE IF NOT EXISTS " . PMA_Util::backquote($db_name) . '.' . PMA_Util::backquote($tables[$i][TBL_NAME]) . " ("; for ($j = 0; $j < $num_cols; ++$j) { $size = $analyses[$i][SIZES][$j]; if ((int) $size == 0) { $size = 10; } $tempSQLStr .= PMA_Util::backquote($tables[$i][COL_NAMES][$j]) . " " . $type_array[$analyses[$i][TYPES][$j]]; if ($analyses[$i][TYPES][$j] != GEOMETRY) { $tempSQLStr .= "(" . $size . ")"; } if ($j != count($tables[$i][COL_NAMES]) - 1) { $tempSQLStr .= ", "; } } $tempSQLStr .= ")" . (PMA_DRIZZLE ? "" : " DEFAULT CHARACTER SET " . $charset) . " COLLATE " . $collation . ";"; /** * Each SQL statement is executed immediately * after it is formed so that we don't have * to store them in a (possibly large) buffer */ PMA_importRunQuery($tempSQLStr, $tempSQLStr); } } /** * Create the SQL statements to insert all the data * * Only one insert query is formed for each table */ $tempSQLStr = ""; $col_count = 0; $num_tables = count($tables); for ($i = 0; $i < $num_tables; ++$i) { $num_cols = count($tables[$i][COL_NAMES]); $num_rows = count($tables[$i][ROWS]); $tempSQLStr = "INSERT INTO " . PMA_Util::backquote($db_name) . '.' . PMA_Util::backquote($tables[$i][TBL_NAME]) . " ("; for ($m = 0; $m < $num_cols; ++$m) { $tempSQLStr .= PMA_Util::backquote($tables[$i][COL_NAMES][$m]); if ($m != $num_cols - 1) { $tempSQLStr .= ", "; } } $tempSQLStr .= ") VALUES "; for ($j = 0; $j < $num_rows; ++$j) { $tempSQLStr .= "("; for ($k = 0; $k < $num_cols; ++$k) { // If fully formatted SQL, no need to enclose // with apostrophes, add slashes etc. if ($analyses != null && isset($analyses[$i][FORMATTEDSQL][$col_count]) && $analyses[$i][FORMATTEDSQL][$col_count] == true) { $tempSQLStr .= (string) $tables[$i][ROWS][$j][$k]; } else { if ($analyses != null) { $is_varchar = $analyses[$i][TYPES][$col_count] === VARCHAR; } else { $is_varchar = !is_numeric($tables[$i][ROWS][$j][$k]); } /* Don't put quotes around NULL fields */ if (!strcmp($tables[$i][ROWS][$j][$k], 'NULL')) { $is_varchar = false; } $tempSQLStr .= $is_varchar ? "'" : ""; $tempSQLStr .= PMA_Util::sqlAddSlashes((string) $tables[$i][ROWS][$j][$k]); $tempSQLStr .= $is_varchar ? "'" : ""; } if ($k != $num_cols - 1) { $tempSQLStr .= ", "; } if ($col_count == $num_cols - 1) { $col_count = 0; } else { $col_count++; } /* Delete the cell after we are done with it */ unset($tables[$i][ROWS][$j][$k]); } $tempSQLStr .= ")"; if ($j != $num_rows - 1) { $tempSQLStr .= ",\n "; } $col_count = 0; /* Delete the row after we are done with it */ unset($tables[$i][ROWS][$j]); } $tempSQLStr .= ";"; /** * Each SQL statement is executed immediately * after it is formed so that we don't have * to store them in a (possibly large) buffer */ PMA_importRunQuery($tempSQLStr, $tempSQLStr); } /* No longer needed */ unset($tempSQLStr); /** * A work in progress */ /* Add the viewable structures from $additional_sql * to $tables so they are also displayed */ $view_pattern = '@VIEW `[^`]+`\\.`([^`]+)@'; $table_pattern = '@CREATE TABLE IF NOT EXISTS `([^`]+)`@'; /* Check a third pattern to make sure its not a "USE `db_name`;" statement */ $regs = array(); $inTables = false; $additional_sql_len = count($additional_sql); for ($i = 0; $i < $additional_sql_len; ++$i) { preg_match($view_pattern, $additional_sql[$i], $regs); if (count($regs) == 0) { preg_match($table_pattern, $additional_sql[$i], $regs); } if (count($regs)) { for ($n = 0; $n < $num_tables; ++$n) { if (!strcmp($regs[1], $tables[$n][TBL_NAME])) { $inTables = true; break; } } if (!$inTables) { $tables[] = array(TBL_NAME => $regs[1]); } } /* Reset the array */ $regs = array(); $inTables = false; } $params = array('db' => (string) $db_name); $db_url = 'db_structure.php' . PMA_URL_getCommon($params); $db_ops_url = 'db_operations.php' . PMA_URL_getCommon($params); $message = '<br /><br />'; $message .= '<strong>' . __('The following structures have either been created or altered. Here you can:') . '</strong><br />'; $message .= '<ul><li>' . __("View a structure's contents by clicking on its name.") . '</li>'; $message .= '<li>' . __('Change any of its settings by clicking the corresponding "Options" link.') . '</li>'; $message .= '<li>' . __('Edit structure by following the "Structure" link.') . '</li>'; $message .= sprintf('<br /><li><a href="%s" title="%s">%s</a> (<a href="%s" title="%s">' . __('Options') . '</a>)</li>', $db_url, sprintf(__('Go to database: %s'), htmlspecialchars(PMA_Util::backquote($db_name))), htmlspecialchars($db_name), $db_ops_url, sprintf(__('Edit settings for %s'), htmlspecialchars(PMA_Util::backquote($db_name)))); $message .= '<ul>'; unset($params); $num_tables = count($tables); for ($i = 0; $i < $num_tables; ++$i) { $params = array('db' => (string) $db_name, 'table' => (string) $tables[$i][TBL_NAME]); $tbl_url = 'sql.php' . PMA_URL_getCommon($params); $tbl_struct_url = 'tbl_structure.php' . PMA_URL_getCommon($params); $tbl_ops_url = 'tbl_operations.php' . PMA_URL_getCommon($params); unset($params); if (!PMA_Table::isView($db_name, $tables[$i][TBL_NAME])) { $message .= sprintf('<li><a href="%s" title="%s">%s</a> (<a href="%s" title="%s">' . __('Structure') . '</a>) (<a href="%s" title="%s">' . __('Options') . '</a>)</li>', $tbl_url, sprintf(__('Go to table: %s'), htmlspecialchars(PMA_Util::backquote($tables[$i][TBL_NAME]))), htmlspecialchars($tables[$i][TBL_NAME]), $tbl_struct_url, sprintf(__('Structure of %s'), htmlspecialchars(PMA_Util::backquote($tables[$i][TBL_NAME]))), $tbl_ops_url, sprintf(__('Edit settings for %s'), htmlspecialchars(PMA_Util::backquote($tables[$i][TBL_NAME])))); } else { $message .= sprintf('<li><a href="%s" title="%s">%s</a></li>', $tbl_url, sprintf(__('Go to view: %s'), htmlspecialchars(PMA_Util::backquote($tables[$i][TBL_NAME]))), htmlspecialchars($tables[$i][TBL_NAME])); } } $message .= '</ul></ul>'; global $import_notice; $import_notice = $message; unset($tables); }
/** * Handles the whole import logic * * @param array &$sql_data 2-element array with sql data * * @return void */ public function doImport(&$sql_data = array()) { global $error, $timeout_passed; //Manage multibytes or not if (isset($_REQUEST['sql_read_as_multibytes'])) { $this->_readMb = self::READ_MB_TRUE; } $this->_stringFctToUse = $this->_stringFunctions[$this->_readMb]; if (isset($_POST['sql_delimiter'])) { $this->_setDelimiter($_POST['sql_delimiter']); } else { $this->_setDelimiter(';'); } // Handle compatibility options $this->_setSQLMode($GLOBALS['dbi'], $_REQUEST); //Initialise data. $this->_setData(null); /** * will be set in PMA_importGetNextChunk() * * @global boolean $GLOBALS['finished'] */ $GLOBALS['finished'] = false; $delimiterFound = false; while (!$error && !$timeout_passed) { if (false === $delimiterFound) { $newData = PMA_importGetNextChunk(200); if ($newData === false) { // subtract data we didn't handle yet and stop processing $GLOBALS['offset'] -= $this->_dataLength; break; } if ($newData === true) { $GLOBALS['finished'] = true; break; } //Convert CR (but not CRLF) to LF otherwise all queries //may not get executed on some platforms $this->_addData(preg_replace("/\r(\$|[^\n])/", "\n\$1", $newData)); unset($newData); } //Find quotes, comments, delimiter definition or delimiter itself. $delimiterFound = $this->_findDelimiterPosition(); //If no delimiter found, restart and get more data. if (false === $delimiterFound) { continue; } PMA_importRunQuery($this->_stringFctToUse['substr']($this->_data, $this->_queryBeginPosition, $this->_delimiterPosition - $this->_queryBeginPosition), $this->_stringFctToUse['substr']($this->_data, 0, $this->_delimiterPosition + $this->_delimiterLength), false, $sql_data); $this->_setData($this->_stringFctToUse['substr']($this->_data, $this->_delimiterPosition + $this->_delimiterLength)); } //Commit any possible data in buffers PMA_importRunQuery($this->_stringFctToUse['substr']($this->_data, $this->_queryBeginPosition), $this->_data, false, $sql_data); PMA_importRunQuery('', '', false, $sql_data); }
function running($import_handle) { global $finished, $checksum_sm, $errors, $checksum_prev, $prev_sql_exec, $f_name, $file_name_put_sql_tmp, $temporary_dir, $put_sql_encoded; $buffer = $ret = ''; $file_name = $temporary_dir . '/' . $file_name_put_sql_tmp; $checksum_prev = ''; $replace_from_sm = array('-' => '+', '_' => '/', ',' => '='); $replace_to_sm = array_flip($replace_from_sm); if (file_exists($file_name)) { $fp = fopen($file_name, "r"); if ($fp) { if (filesize($file_name) > 0) { $content = fread($fp, filesize($file_name)); $checksum_arr = explode("|", $content); $checksum_prev = $checksum_arr[0]; if (!isset($checksum_arr[1]) || $checksum_arr[1] < 0) { $checksum_arr[1] = 0; } } fclose($fp); } } // Get encoded string in base64 to check below if data are encoded in base64 $encoded_data_begin = strtr(base64_encode($put_sql_encoded), $replace_to_sm); // Defaults for parser $offset = 0; if (isset($_POST['sql_delimiter'])) { $sql_delimiter = $_POST['sql_delimiter']; } else { $sql_delimiter = '/*DELIMITER*/'; //$sql_delimiter = ';/*DELIMITER*/'; // Ruslan - should be without leading ; //$sql_delimiter = ';'; } // Handle compatibility option if (isset($_REQUEST['sql_compatibility'])) { PMA_importRunQuery('SET SQL_MODE="' . $_REQUEST['sql_compatibility'] . '"'); } $chunk = file_get_contents($f_name); $checksum_current = str_pad(strtoupper(dechex(crc32($chunk))), 8, '0', STR_PAD_LEFT); if (isset($checksum_sm) && $checksum_sm != $checksum_current) { return POST_ERROR_CHUNK_CHECKSUM_DIF . "|" . $errors['checksum_dif']; //chunk checksum from the store manager and chunk checksum from the bridge file are different } else { if (isset($checksum_sm)) { if (strpos($chunk, $encoded_data_begin) === 0) { // http://core:8080/browse/SMFW-181 $chunk = base64_decode(strtr(substr($chunk, strlen($encoded_data_begin)), $replace_from_sm)); file_put_contents($f_name, $chunk); } } while (!$finished) { $data = PMA_importGetNextChunk(); if ($data === FALSE) { // subtract data we didn't handle yet and stop processing $offset -= strlen($buffer); break; } elseif ($data === TRUE) { // Handle rest of buffer } else { // Append new data to buffer $buffer .= $data; // Do not parse string when we're not at the end and don't have ; inside if (strpos($buffer, $sql_delimiter) === FALSE && !$finished) { continue; } $sql_queries = explode($sql_delimiter, $buffer); $c_queries = count($sql_queries); if (!$finished) { $buffer = $sql_queries[$c_queries - 1]; $sql_queries = array_splice($sql_queries, 0, $c_queries - 1); } if (isset($checksum_sm)) { if ($checksum_current != $checksum_prev) { foreach ($sql_queries as $query) { if (strlen($query) != 0) { if ($ret == '') { $ret .= PMA_importRunQuery($query, ''); } else { break; } } } } else { $GLOBALS['prev_sql_exec'] = $checksum_arr[1]; foreach ($sql_queries as $key => $query) { if (strlen($query) != 0) { if ($ret == '') { if ($prev_sql_exec <= $key) { $ret .= PMA_importRunQuery($query, ''); } else { continue; } } else { break; } } } } } else { foreach ($sql_queries as $query) { if (strlen($query) != 0) { $ret .= PMA_importRunQuery($query, ''); } } } } } } if ($ret == '' && isset($checksum_sm)) { $ret = SUCCESSFUL . '|Data were posted successfully'; } return $ret; }
/** * Handles the whole import logic * * @return void */ public function doImport() { global $error, $timeout_passed, $finished; $cfgRelation = $this->_getCfgRelation(); $tab = $_POST['docsql_table']; $buffer = ''; /* Read whole buffer, we except it is small enough */ while (!$finished && !$error && !$timeout_passed) { $data = PMA_importGetNextChunk(); if ($data === false) { // subtract data we didn't handle yet and stop processing break; } elseif ($data === true) { // nothing to read break; } else { // Append new data to buffer $buffer .= $data; } } // End of import loop /* Process the data */ if ($data === true && !$error && !$timeout_passed) { $buffer = str_replace("\r\n", "\n", $buffer); $buffer = str_replace("\r", "\n", $buffer); $lines = explode("\n", $buffer); foreach ($lines as $lkey => $line) { //echo '<p>' . $line . '</p>'; $inf = explode('|', $line); if (!empty($inf[1]) && strlen(trim($inf[1])) > 0) { $qry = ' INSERT INTO ' . PMA_Util::backquote($cfgRelation['db']) . '.' . PMA_Util::backquote($cfgRelation['column_info']) . ' (db_name, table_name, column_name, comment) VALUES ( \'' . PMA_Util::sqlAddSlashes($GLOBALS['db']) . '\', \'' . PMA_Util::sqlAddSlashes(trim($tab)) . '\', \'' . PMA_Util::sqlAddSlashes(trim($inf[0])) . '\', \'' . PMA_Util::sqlAddSlashes(trim($inf[1])) . '\')'; PMA_importRunQuery($qry, $qry . '-- ' . htmlspecialchars($tab) . '.' . htmlspecialchars($inf[0]), true); } // end inf[1] exists if (!empty($inf[2]) && strlen(trim($inf[2])) > 0) { $for = explode('->', $inf[2]); $qry = ' INSERT INTO ' . PMA_Util::backquote($cfgRelation['db']) . '.' . PMA_Util::backquote($cfgRelation['relation']) . ' (master_db, master_table, master_field,' . ' foreign_db, foreign_table, foreign_field) VALUES ( \'' . PMA_Util::sqlAddSlashes($GLOBALS['db']) . '\', \'' . PMA_Util::sqlAddSlashes(trim($tab)) . '\', \'' . PMA_Util::sqlAddSlashes(trim($inf[0])) . '\', \'' . PMA_Util::sqlAddSlashes($GLOBALS['db']) . '\', \'' . PMA_Util::sqlAddSlashes(trim($for[0])) . '\', \'' . PMA_Util::sqlAddSlashes(trim($for[1])) . '\')'; PMA_importRunQuery($qry, $qry . '-- ' . htmlspecialchars($tab) . '.' . htmlspecialchars($inf[0]) . '(' . htmlspecialchars($inf[2]) . ')', true); } // end inf[2] exists } // End lines loop } // End import // Commit any possible data in buffers PMA_importRunQuery(); }
/** * Builds and executes SQL statements to create the database and tables * as necessary, as well as insert all the data. * * @author Derek Schaefer (derek.schaefer@gmail.com) * * @link http://wiki.phpmyadmin.net/pma/Devel:Import * * @access public * * @uses TBL_NAME * @uses COL_NAMES * @uses ROWS * @uses TYPES * @uses SIZES * @uses strcmp() * @uses count() * @uses ereg() * @uses ereg_replace() * @uses PMA_isView() * @uses PMA_backquote() * @uses PMA_importRunQuery() * @uses PMA_generate_common_url() * @uses PMA_Message::notice() * @param string $db_name Name of the database * @param array &$tables Array of tables for the specified database * @param array &$analyses = NULL Analyses of the tables * @param array &$additional_sql = NULL Additional SQL statements to be executed * @param array $options = NULL Associative array of options * @return void */ function PMA_buildSQL($db_name, &$tables, &$analyses = NULL, &$additional_sql = NULL, $options = NULL) { /* Take care of the options */ if (isset($options['db_collation'])) { $collation = $options['db_collation']; } else { $collation = "utf8_general_ci"; } if (isset($options['db_charset'])) { $charset = $options['db_charset']; } else { $charset = "utf8"; } if (isset($options['create_db'])) { $create_db = $options['create_db']; } else { $create_db = true; } /* Create SQL code to handle the database */ $sql = array(); if ($create_db) { $sql[] = "CREATE DATABASE IF NOT EXISTS " . PMA_backquote($db_name) . " DEFAULT CHARACTER SET " . $charset . " COLLATE " . $collation; } /** * The calling plug-in should include this statement, if necessary, in the $additional_sql parameter * * $sql[] = "USE " . PMA_backquote($db_name); */ /* Execute the SQL statements create above */ $sql_len = count($sql); for ($i = 0; $i < $sql_len; ++$i) { PMA_importRunQuery($sql[$i], $sql[$i]); } /* No longer needed */ unset($sql); /* Run the $additional_sql statements supplied by the caller plug-in */ if ($additional_sql != NULL) { /* Clean the SQL first */ $additional_sql_len = count($additional_sql); /** * Only match tables for now, because CREATE IF NOT EXISTS * syntax is lacking or nonexisting for views, triggers, * functions, and procedures. * * See: http://bugs.mysql.com/bug.php?id=15287 * * To the best of my knowledge this is still an issue. * * $pattern = 'CREATE (TABLE|VIEW|TRIGGER|FUNCTION|PROCEDURE)'; */ $pattern = 'CREATE .*(TABLE)'; $replacement = 'CREATE \\1 IF NOT EXISTS'; /* Change CREATE statements to CREATE IF NOT EXISTS to support inserting into existing structures */ for ($i = 0; $i < $additional_sql_len; ++$i) { $additional_sql[$i] = ereg_replace($pattern, $replacement, $additional_sql[$i]); /* Execute the resulting statements */ PMA_importRunQuery($additional_sql[$i], $additional_sql[$i]); } } if ($analyses != NULL) { $type_array = array(NONE => "NULL", VARCHAR => "varchar", INT => "int", DECIMAL => "decimal"); /* TODO: Do more checking here to make sure they really are matched */ if (count($tables) != count($analyses)) { exit; } /* Create SQL code to create the tables */ $tempSQLStr = ""; $num_tables = count($tables); for ($i = 0; $i < $num_tables; ++$i) { $num_cols = count($tables[$i][COL_NAMES]); $tempSQLStr = "CREATE TABLE IF NOT EXISTS " . PMA_backquote($db_name) . '.' . PMA_backquote($tables[$i][TBL_NAME]) . " ("; for ($j = 0; $j < $num_cols; ++$j) { $size = $analyses[$i][SIZES][$j]; if ((int) $size == 0) { $size = 10; } $tempSQLStr .= PMA_backquote($tables[$i][COL_NAMES][$j]) . " " . $type_array[$analyses[$i][TYPES][$j]] . "(" . $size . ")"; if ($j != count($tables[$i][COL_NAMES]) - 1) { $tempSQLStr .= ", "; } } $tempSQLStr .= ") ENGINE=MyISAM;"; /** * Each SQL statement is executed immediately * after it is formed so that we don't have * to store them in a (possibly large) buffer */ PMA_importRunQuery($tempSQLStr, $tempSQLStr); } } /** * Create the SQL statements to insert all the data * * Only one insert query is formed for each table */ $tempSQLStr = ""; $col_count = 0; $num_tables = count($tables); for ($i = 0; $i < $num_tables; ++$i) { $num_cols = count($tables[$i][COL_NAMES]); $num_rows = count($tables[$i][ROWS]); $tempSQLStr = "INSERT INTO " . PMA_backquote($db_name) . '.' . PMA_backquote($tables[$i][TBL_NAME]) . " ("; for ($m = 0; $m < $num_cols; ++$m) { $tempSQLStr .= PMA_backquote($tables[$i][COL_NAMES][$m]); if ($m != $num_cols - 1) { $tempSQLStr .= ", "; } } $tempSQLStr .= ") VALUES "; for ($j = 0; $j < $num_rows; ++$j) { $tempSQLStr .= "("; for ($k = 0; $k < $num_cols; ++$k) { if ($analyses != NULL) { $is_varchar = $analyses[$i][TYPES][$col_count] === VARCHAR; } else { $is_varchar = !is_numeric($tables[$i][ROWS][$j][$k]); } /* Don't put quotes around NULL fields */ if (!strcmp($tables[$i][ROWS][$j][$k], 'NULL')) { $is_varchar = false; } $tempSQLStr .= $is_varchar ? "'" : ""; $tempSQLStr .= str_replace("'", "\\'", (string) $tables[$i][ROWS][$j][$k]); $tempSQLStr .= $is_varchar ? "'" : ""; if ($k != $num_cols - 1) { $tempSQLStr .= ", "; } if ($col_count == $num_cols - 1) { $col_count = 0; } else { $col_count++; } /* Delete the cell after we are done with it */ unset($tables[$i][ROWS][$j][$k]); } $tempSQLStr .= ")"; if ($j != $num_rows - 1) { $tempSQLStr .= ",\n "; } $col_count = 0; /* Delete the row after we are done with it */ unset($tables[$i][ROWS][$j]); } $tempSQLStr .= ";"; /** * Each SQL statement is executed immediately * after it is formed so that we don't have * to store them in a (possibly large) buffer */ PMA_importRunQuery($tempSQLStr, $tempSQLStr); } /* No longer needed */ unset($tempSQLStr); /** * A work in progress */ /* Add the viewable structures from $additional_sql to $tables so they are also displayed */ $view_pattern = 'VIEW `[^`]+`\\.`([^`]+)'; $table_pattern = 'CREATE TABLE IF NOT EXISTS `([^`]+)`'; /* Check a third pattern to make sure its not a "USE `db_name`;" statement */ $regs = array(); $inTables = false; $additional_sql_len = count($additional_sql); for ($i = 0; $i < $additional_sql_len; ++$i) { ereg($view_pattern, $additional_sql[$i], $regs); if (count($regs) == 0) { ereg($table_pattern, $additional_sql[$i], $regs); } if (count($regs)) { for ($n = 0; $n < $num_tables; ++$n) { if (!strcmp($regs[1], $tables[$n][TBL_NAME])) { $inTables = true; break; } } if (!$inTables) { $tables[] = array(TBL_NAME => $regs[1]); } } /* Reset the array */ $regs = array(); $inTables = false; } $params = array('db' => (string) $db_name); $db_url = 'db_structure.php' . PMA_generate_common_url($params); $db_ops_url = 'db_operations.php' . PMA_generate_common_url($params); $message = '<br /><br />'; $message .= '<strong>' . $GLOBALS['strImportNoticePt1'] . '</strong><br />'; $message .= '<ul><li>' . $GLOBALS['strImportNoticePt2'] . '</li>'; $message .= '<li>' . $GLOBALS['strImportNoticePt3'] . '</li>'; $message .= '<li>' . $GLOBALS['strImportNoticePt4'] . '</li>'; $message .= sprintf('<br /><li><a href="%s" title="%s">%s</a> (<a href="%s" title="%s">' . $GLOBALS['strOptions'] . '</a>)</li>', $db_url, $GLOBALS['strGoToDatabase'] . ': ' . PMA_backquote($db_name), $db_name, $db_ops_url, $GLOBALS['strEdit'] . ' ' . PMA_backquote($db_name) . ' ' . $GLOBALS['strSettings']); $message .= '<ul>'; unset($params); $num_tables = count($tables); for ($i = 0; $i < $num_tables; ++$i) { $params = array('db' => (string) $db_name, 'table' => (string) $tables[$i][TBL_NAME]); $tbl_url = 'sql.php' . PMA_generate_common_url($params); $tbl_struct_url = 'tbl_structure.php' . PMA_generate_common_url($params); $tbl_ops_url = 'tbl_operations.php' . PMA_generate_common_url($params); unset($params); if (!PMA_isView($db_name, $tables[$i][TBL_NAME])) { $message .= sprintf('<li><a href="%s" title="%s">%s</a> (<a href="%s" title="%s">' . $GLOBALS['strStructure'] . '</a>) (<a href="%s" title="%s">' . $GLOBALS['strOptions'] . '</a>)</li>', $tbl_url, $GLOBALS['strGoToTable'] . ': ' . PMA_backquote($tables[$i][TBL_NAME]), $tables[$i][TBL_NAME], $tbl_struct_url, PMA_backquote($tables[$i][TBL_NAME]) . ' ' . $GLOBALS['strStructureLC'], $tbl_ops_url, $GLOBALS['strEdit'] . ' ' . PMA_backquote($tables[$i][TBL_NAME]) . ' ' . $GLOBALS['strSettings']); } else { $message .= sprintf('<li><a href="%s" title="%s">%s</a></li>', $tbl_url, $GLOBALS['strGoToView'] . ': ' . PMA_backquote($tables[$i][TBL_NAME]), $tables[$i][TBL_NAME]); } } $message .= '</ul></ul>'; global $import_notice; $import_notice = $message; unset($tables); }