} $tables[] = array($sheet_names[$s], $col_names, $rows); $col_names = array(); $rows = array(); } } unset($objPHPExcel); unset($objReader); unset($rows); unset($tempRow); unset($col_names); /* 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 */
/** * 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 * * @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(); }
/** * 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, $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(); }