Пример #1
0
 /**
  * Pack file stream
  * @internal
  *
  * @param  int   $compr compression type
  * @param  array $file  file data
  * @return array array(handle, path)
  */
 protected function _pack_stream($compr, $file)
 {
     // get stream
     $stream = new KZipStream($file[0] === self::FILE_REAL ? $this->handle : null, $file);
     // create temporary file
     $tmp = _tmpFile();
     // read
     while (!$stream->eof()) {
         // load chunk
         if ($compr === self::COMPR_NONE) {
             $read = $stream->read();
         } else {
             // compress
             $read = $stream->read(self::STREAM_CBUFFER);
             switch ($compr) {
                 case self::COMPR_DEFLATE:
                     $read = gzdeflate($read, $this->compr_level);
                     break;
             }
             $read = pack('V', strlen($read)) . $read;
         }
         // write to temporary file
         fwrite($tmp[0], $read);
         $read = '';
     }
     // free stream, reset and return tmpfile
     $stream->free();
     fseek($tmp[0], 0);
     return $tmp;
 }
Пример #2
0
 /**
  * Import data to the database
  * @param  KZipStream|string $stream KZipStream instance or file path
  * @return array             array(true, skipped_tables) on success, array(false, err_msg) on failure
  */
 public function importData($stream)
 {
     // prepare
     global $_lang;
     $err = null;
     $this->_import_tmap = array();
     // rather ugly hack to use existing file path as KZipStream
     if (is_string($stream)) {
         $file = $stream;
         $stream = new KZipStream(null, array(KZip::FILE_TOADD, $file, null));
         unset($file);
     }
     // vars
     $null = chr(0);
     $nullv = chr(1);
     $version = '';
     // import process
     do {
         // read header
         $offset = 0;
         while (true) {
             ++$offset;
             $byte = $stream->read(1);
             if ($byte === $null) {
                 // header read
                 break;
             } else {
                 $version .= $byte;
             }
             if ($offset > 32) {
                 $err = $_lang['dbdump']['dataerror'];
                 break 2;
             }
         }
         // check version
         if (!_checkVersion('database', $version)) {
             $err = $_lang['dbdump']['badversion'];
             break;
         }
         // find local tables
         $tables = array();
         $q = DB::query('SHOW TABLES LIKE \'' . _mysql_prefix . '-%\'');
         while ($r = DB::rown($q)) {
             $tables[$r[0]] = true;
         }
         DB::free($q);
         unset($r);
         // determine maximum query size
         $max_size = DB::query('SHOW VARIABLES LIKE \'max_allowed_packet\'');
         if (DB::size($max_size) !== 1) {
             $err = $_lang['dbdump']['maxpacket'];
             break;
         }
         $max_size = DB::result($max_size, 0, 1);
         $max_size -= 128;
         $max_size = floor(($max_size - 128) * 0.9);
         // adjust maximum query size to available memory
         $memlimit = _phpIniLimit('memory_limit');
         if (isset($memlimit)) {
             $avail_mem = $memlimit - memory_get_usage() - 131072;
             if ($max_size > $avail_mem) {
                 $max_size = $avail_mem;
             }
             unset($avail_mem);
         }
         if ($max_size < 32768) {
             $err = $_lang['dbdump']['memory'];
             break;
         }
         // turn off auto_increment for zero values
         DB::query('SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"');
         // prepare
         $reset = true;
         $skipped_tables = array();
         $stream_buffer = '';
         $stream_buffer_i = 0;
         // import data
         while (true) {
             // reset?
             if ($reset) {
                 $phase = 0;
                 $table = '';
                 $column = '';
                 $columns = array();
                 $columns_size = 0;
                 $values = array();
                 $value = '';
                 $value_counter = 0;
                 $sql = '';
                 $sql_len = 0;
                 $sql_buffer = '';
                 $sql_buffer_len = 0;
                 $skipping_table = false;
                 $reset = false;
             }
             // get 1 byte
             if (!isset($stream_buffer[$stream_buffer_i])) {
                 if ($stream->eof()) {
                     break;
                 }
                 $stream_buffer = $stream->read();
                 $stream_buffer_i = 0;
                 if ($stream_buffer === '') {
                     break;
                 }
             }
             $byte = $stream_buffer[$stream_buffer_i];
             ++$stream_buffer_i;
             // phase
             switch ($phase) {
                 /* --  reading table name  -- */
                 case 0:
                     // end of table name?
                     if ($byte === $null) {
                         // read column list
                         $phase = 1;
                         if (!isset($tables[_mysql_prefix . '-' . $table])) {
                             $skipping_table = true;
                             $skipped_tables[] = $table;
                         }
                         break;
                     }
                     // znak nazvu tabulky
                     $table .= $byte;
                     break;
                     /* --  reading column list  -- */
                 /* --  reading column list  -- */
                 case 1:
                     // end of column
                     if ($byte === $null) {
                         if ($column === '') {
                             // end of list, process columns
                             if (!$skipping_table) {
                                 $columns = '`' . implode('`,`', $columns) . '`';
                             }
                             // begin to read rows
                             $phase = 2;
                         } else {
                             // end of column
                             if (!$skipping_table) {
                                 $columns[] = $column;
                             }
                             ++$columns_size;
                             $column = '';
                         }
                         break;
                     }
                     // column name char
                     $column .= $byte;
                     break;
                     /* --  reading row data  -- */
                 /* --  reading row data  -- */
                 case 2:
                     // end of value?
                     if ($byte === $null) {
                         if ($value_counter === 0 && $value === '') {
                             // end of all rows, reset
                             $reset = true;
                             // import remaining data
                             if ($sql_buffer !== '' && !$skipping_table) {
                                 $import = $this->_db_import($table, $columns, $sql_buffer, $sql_buffer_len);
                                 if (isset($import)) {
                                     $err = _htmlStr($import);
                                     break 3;
                                 }
                             }
                         } else {
                             // end of value
                             ++$value_counter;
                             $values[] = $value;
                             $value = '';
                             // end of one row?
                             if ($value_counter === $columns_size) {
                                 if (!$skipping_table) {
                                     // build part of the SQL query
                                     $sql = '(';
                                     for ($i = 0, $lastcol = $columns_size - 1; isset($values[$i]); ++$i) {
                                         if ($values[$i] === $nullv) {
                                             $sql .= 'NULL';
                                         } else {
                                             $sql .= '\'' . $values[$i] . '\'';
                                         }
                                         if ($i !== $lastcol) {
                                             $sql .= ',';
                                         }
                                     }
                                     $sql .= ')';
                                     // execute query or use buffer
                                     $sql_len = strlen($sql);
                                     if ($sql_buffer_len + $sql_len + 1 >= $max_size) {
                                         $this->_db_import($table, $columns, $sql_buffer, $sql_buffer_len);
                                         if (isset($import)) {
                                             $err = _htmlStr($import);
                                             break 3;
                                         }
                                     } else {
                                         // separate
                                         if ($sql_buffer !== '') {
                                             $sql_buffer .= ',';
                                             ++$sql_buffer_len;
                                         }
                                         // add query to buffer
                                         $sql_buffer .= $sql;
                                         $sql_buffer_len += $sql_len;
                                     }
                                     // clean up
                                     $sql = '';
                                     $sql_len = 0;
                                 }
                                 $value_counter = 0;
                                 $values = array();
                             }
                         }
                         break;
                     }
                     // value char
                     $value .= $byte;
                     break;
             }
         }
         // restore sql_mode
         DB::query('SET SQL_MODE=""');
     } while (false);
     // void truncate map
     $this->_import_tmap = null;
     // return
     if (!isset($err)) {
         return array(true, $skipped_tables);
     }
     return array(false, $err);
 }