Example #1
0
 function readFromBuffer($length)
 {
     global $buffer, $eof;
     if (strlen($buffer) < $length) {
         if ($GLOBALS['finished']) {
             $eof = true;
         } else {
             $buffer .= PMA_importGetNextChunk();
         }
     }
     $result = substr($buffer, 0, $length);
     $buffer = substr($buffer, $length);
     return $result;
 }
Example #2
0
 /**
  * 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);
 }
 /**
  * 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);
 }
Example #4
0
// Convert the file's charset if necessary
if ($GLOBALS['PMA_recoding_engine'] != PMA_CHARSET_NONE && isset($charset_of_file)) {
    if ($charset_of_file != $charset) {
        $charset_conversion = TRUE;
    }
} elseif (isset($charset_of_file) && $charset_of_file != 'utf8') {
    PMA_DBI_query('SET NAMES \'' . $charset_of_file . '\'');
    // We can not show query in this case, it is in different charset
    $sql_query_disabled = TRUE;
    $reset_charset = TRUE;
}
// Something to skip?
if (!$error && isset($skip)) {
    $original_skip = $skip;
    while ($skip > 0) {
        PMA_importGetNextChunk($skip < $read_limit ? $skip : $read_limit);
        $read_multiply = 1;
        // Disable read progresivity, otherwise we eat all memory!
        $skip -= $read_limit;
    }
    unset($skip);
}
if (!$error) {
    // Check for file existance
    if (!file_exists('./libraries/import/' . $format . '.php')) {
        $error = TRUE;
        $message = PMA_Message::error(__('Could not load import plugins, please check your installation!'));
    } else {
        // Do the real import
        $plugin_param = $import_type;
        require './libraries/import/' . $format . '.php';
Example #5
0
 /**
  * Handles the whole import logic
  *
  * @return void
  */
 public function doImport()
 {
     global $error, $timeout_passed, $finished;
     // Defaults for parser
     // The buffer that will be used to store chunks read from the imported file
     $buffer = '';
     // Used as storage for the last part of the current chunk data
     // Will be appended to the first line of the next chunk, if there is one
     $last_chunk_line = '';
     // Remembers whether the current buffer line is part of a comment
     $inside_comment = false;
     // Remembers whether the current buffer line is part of a data comment
     $inside_data_comment = false;
     // Remembers whether the current buffer line is part of a structure comment
     $inside_structure_comment = false;
     // MediaWiki only accepts "\n" as row terminator
     $mediawiki_new_line = "\n";
     // Initialize the name of the current table
     $cur_table_name = "";
     while (!$finished && !$error && !$timeout_passed) {
         $data = PMA_importGetNextChunk();
         if ($data === false) {
             // Subtract data we didn't handle yet and stop processing
             $GLOBALS['offset'] -= mb_strlen($buffer);
             break;
         } elseif ($data === true) {
             // Handle rest of buffer
         } else {
             // Append new data to buffer
             $buffer = $data;
             unset($data);
             // Don't parse string if we're not at the end
             // and don't have a new line inside
             if (mb_strpos($buffer, $mediawiki_new_line) === false) {
                 continue;
             }
         }
         // Because of reading chunk by chunk, the first line from the buffer
         // contains only a portion of an actual line from the imported file.
         // Therefore, we have to append it to the last line from the previous
         // chunk. If we are at the first chunk, $last_chunk_line should be empty.
         $buffer = $last_chunk_line . $buffer;
         // Process the buffer line by line
         $buffer_lines = explode($mediawiki_new_line, $buffer);
         $full_buffer_lines_count = count($buffer_lines);
         // If the reading is not finalised, the final line of the current chunk
         // will not be complete
         if (!$finished) {
             $last_chunk_line = $buffer_lines[--$full_buffer_lines_count];
         }
         for ($line_nr = 0; $line_nr < $full_buffer_lines_count; ++$line_nr) {
             $cur_buffer_line = trim($buffer_lines[$line_nr]);
             // If the line is empty, go to the next one
             if ($cur_buffer_line === '') {
                 continue;
             }
             $first_character = $cur_buffer_line[0];
             $matches = array();
             // Check beginning of comment
             if (!strcmp(mb_substr($cur_buffer_line, 0, 4), "<!--")) {
                 $inside_comment = true;
                 continue;
             } elseif ($inside_comment) {
                 // Check end of comment
                 if (!strcmp(mb_substr($cur_buffer_line, 0, 4), "-->")) {
                     // Only data comments are closed. The structure comments
                     // will be closed when a data comment begins (in order to
                     // skip structure tables)
                     if ($inside_data_comment) {
                         $inside_data_comment = false;
                     }
                     // End comments that are not related to table structure
                     if (!$inside_structure_comment) {
                         $inside_comment = false;
                     }
                 } else {
                     // Check table name
                     $match_table_name = array();
                     if (preg_match("/^Table data for `(.*)`\$/", $cur_buffer_line, $match_table_name)) {
                         $cur_table_name = $match_table_name[1];
                         $inside_data_comment = true;
                         $inside_structure_comment = $this->_mngInsideStructComm($inside_structure_comment);
                     } elseif (preg_match("/^Table structure for `(.*)`\$/", $cur_buffer_line, $match_table_name)) {
                         // The structure comments will be ignored
                         $inside_structure_comment = true;
                     }
                 }
                 continue;
             } elseif (preg_match('/^\\{\\|(.*)$/', $cur_buffer_line, $matches)) {
                 // Check start of table
                 // This will store all the column info on all rows from
                 // the current table read from the buffer
                 $cur_temp_table = array();
                 // Will be used as storage for the current row in the buffer
                 // Once all its columns are read, it will be added to
                 // $cur_temp_table and then it will be emptied
                 $cur_temp_line = array();
                 // Helps us differentiate the header columns
                 // from the normal columns
                 $in_table_header = false;
                 // End processing because the current line does not
                 // contain any column information
             } elseif (mb_substr($cur_buffer_line, 0, 2) === '|-' || mb_substr($cur_buffer_line, 0, 2) === '|+' || mb_substr($cur_buffer_line, 0, 2) === '|}') {
                 // Check begin row or end table
                 // Add current line to the values storage
                 if (!empty($cur_temp_line)) {
                     // If the current line contains header cells
                     // ( marked with '!' ),
                     // it will be marked as table header
                     if ($in_table_header) {
                         // Set the header columns
                         $cur_temp_table_headers = $cur_temp_line;
                     } else {
                         // Normal line, add it to the table
                         $cur_temp_table[] = $cur_temp_line;
                     }
                 }
                 // Empty the temporary buffer
                 $cur_temp_line = array();
                 // No more processing required at the end of the table
                 if (mb_substr($cur_buffer_line, 0, 2) === '|}') {
                     $current_table = array($cur_table_name, $cur_temp_table_headers, $cur_temp_table);
                     // Import the current table data into the database
                     $this->_importDataOneTable($current_table);
                     // Reset table name
                     $cur_table_name = "";
                 }
                 // What's after the row tag is now only attributes
             } elseif ($first_character === '|' || $first_character === '!') {
                 // Check cell elements
                 // Header cells
                 if ($first_character === '!') {
                     // Mark as table header, but treat as normal row
                     $cur_buffer_line = str_replace('!!', '||', $cur_buffer_line);
                     // Will be used to set $cur_temp_line as table header
                     $in_table_header = true;
                 } else {
                     $in_table_header = false;
                 }
                 // Loop through each table cell
                 $cells = $this->_explodeMarkup($cur_buffer_line);
                 foreach ($cells as $cell) {
                     $cell = $this->_getCellData($cell);
                     // Delete the beginning of the column, if there is one
                     $cell = trim($cell);
                     $col_start_chars = array("|", "!");
                     foreach ($col_start_chars as $col_start_char) {
                         $cell = $this->_getCellContent($cell, $col_start_char);
                     }
                     // Add the cell to the row
                     $cur_temp_line[] = $cell;
                 }
                 // foreach $cells
             } else {
                 // If it's none of the above, then the current line has a bad
                 // format
                 $message = PMA\libraries\Message::error(__('Invalid format of mediawiki input on line: <br />%s.'));
                 $message->addParam($cur_buffer_line);
                 $error = true;
             }
         }
         // End treating full buffer lines
     }
     // while - finished parsing buffer
 }
Example #6
0
if (isset($plugin_list)) {
    $plugin_list['ods'] = array('text' => __('Open Document Spreadsheet'), 'extension' => 'ods', 'options' => array(array('type' => 'begin_group', 'name' => 'general_opts'), array('type' => 'bool', 'name' => 'col_names', 'text' => __('The first line of the file contains the table column names <i>(if this is unchecked, the first line will become part of the data)</i>')), array('type' => 'bool', 'name' => 'empty_rows', 'text' => __('Do not import empty rows')), array('type' => 'bool', 'name' => 'recognize_percentages', 'text' => __('Import percentages as proper decimals <i>(ex. 12.00% to .12)</i>')), array('type' => 'bool', 'name' => 'recognize_currency', 'text' => __('Import currencies <i>(ex. $5.00 to 5.00)</i>')), array('type' => 'end_group')), 'options_text' => __('Options'));
    /* We do not define function when plugin is just queried for information above */
    return;
}
ini_set('memory_limit', '128M');
set_time_limit(120);
$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 */
        $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.
Example #7
0
 /**
  * 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();
 }
Example #9
0
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;
}
Example #10
0
 /**
  * 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 $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);
 }
Example #12
0
/**
 * This function will import the huge database files (.sql) into database.
 *
 * @package      restore
 * @author       Chirag Nagda
 * @param        string $import_file Name of the file with full path
 * @param        resource $conn It is resouceID of the database connection
 * @return       bool true/false On success TRUE otherwise FALSE
 * @since     	 4.1.5
 */
function soft_import($import_file, $conn)
{
    global $import_handle, $read_limit, $error, $offset, $finished;
    $buffer = '';
    // Defaults for parser
    $offset = 0;
    $sql = '';
    $start_pos = 0;
    $i = 0;
    $len = 0;
    $big_value = 2147483647;
    $delimiter_keyword = 'DELIMITER ';
    // include the space because it's mandatory
    $sql_delimiter = ';';
    $import_handle = @fopen($import_file, 'r');
    // We can not read all at once, otherwise we can run out of memory
    $memory_limit = trim(@ini_get('memory_limit'));
    // 2 MB as default
    if (empty($memory_limit)) {
        $memory_limit = 2 * 1024 * 1024;
    }
    // In case no memory limit we work on 10MB chunks
    if ($memory_limit == -1) {
        $memory_limit = 10 * 1024 * 1024;
    }
    // Calculate value of the limit
    if (strtolower(substr($memory_limit, -1)) == 'm') {
        $memory_limit = (int) substr($memory_limit, 0, -1) * 1024 * 1024;
    } elseif (strtolower(substr($memory_limit, -1)) == 'k') {
        $memory_limit = (int) substr($memory_limit, 0, -1) * 1024;
    } elseif (strtolower(substr($memory_limit, -1)) == 'g') {
        $memory_limit = (int) substr($memory_limit, 0, -1) * 1024 * 1024 * 1024;
    } else {
        $memory_limit = (int) $memory_limit;
    }
    $read_limit = $memory_limit / 8;
    // Just to be sure, there might be lot of memory needed for uncompression
    $finished = false;
    //will be set in PMA_importGetNextChunk()
    while (!($finished && $i >= $len)) {
        $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;
            // 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 && !$finished) {
                continue;
            }
        }
        // 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()
            if (preg_match('/(\'|"|#|-- |\\/\\*|`|(?i)(?<![A-Z0-9_])' . $delimiter_keyword . ')/', $buffer, $matches, PREG_OFFSET_CAPTURE, $i)) {
                // 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 (!$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;
                        // No quote? Too short string
                    } elseif ($pos === false) {
                        // We hit end of string => unclosed quote, but we handle it as end of query
                        if ($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 ($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] == '*')) && !$finished) {
                break;
            }
            // Comments
            if ($ch == '#' || $i < $len - 1 && $ch == '-' && $buffer[$i + 1] == '-' && ($i < $len - 2 && $buffer[$i + 2] <= ' ' || $i == $len - 1 && $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 ($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 (strtoupper(substr($buffer, $i, 10)) == $delimiter_keyword && $i + 10 < $len) {
                // look for EOL on the character immediately after 'DELIMITER '
                // (see previous comment about PHP_EOL)
                $new_line_pos = strpos($buffer, "\n", $i + 10);
                // it might happen that there is no EOL
                if (false === $new_line_pos) {
                    $new_line_pos = $len;
                }
                $sql_delimiter = substr($buffer, $i + 10, $new_line_pos - $i - 10);
                $i = $new_line_pos + 1;
                // Next query part will start here
                $start_pos = $i;
                continue;
            }
            // End of SQL
            if ($found_delimiter || $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;
                    $res = mysql_query($sql, $conn);
                    if (!$res) {
                        $error[] = mysql_error($conn);
                        //r_print($error);
                        return false;
                    }
                    //PMA_importRunQuery($sql, substr($buffer, 0, $i + strlen($sql_delimiter)));
                    $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) && !$finished) {
                    if (strpos($buffer, $sql_delimiter) === false && !$finished) {
                        break;
                    }
                } else {
                    $i++;
                    $start_pos = $i;
                }
            }
        }
        // End of parser loop
    }
    // End of import loop
    return true;
}
Example #13
0
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;
}
Example #14
0
 /**
  * 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();
 }