/** * try to restore db backup file */ public function ajaxProcessRestoreDb() { $skip_ignore_tables = false; $ignore_stats_table = array(_DB_PREFIX_ . 'connections', _DB_PREFIX_ . 'connections_page', _DB_PREFIX_ . 'connections_source', _DB_PREFIX_ . 'guest', _DB_PREFIX_ . 'statssearch'); $this->nextParams['dbStep'] = $this->currentParams['dbStep']; $start_time = time(); $db = $this->db; $listQuery = array(); $errors = array(); // deal with running backup rest if exist if (file_exists($this->autoupgradePath . DIRECTORY_SEPARATOR . $this->toRestoreQueryList)) { $listQuery = unserialize(base64_decode(file_get_contents($this->autoupgradePath . DIRECTORY_SEPARATOR . $this->toRestoreQueryList))); } // deal with the next files stored in restoreDbFilenames if (empty($listQuery) && is_array($this->restoreDbFilenames) && count($this->restoreDbFilenames) > 0) { $currentDbFilename = array_shift($this->restoreDbFilenames); if (!preg_match('#auto-backupdb_([0-9]{6})_#', $currentDbFilename, $match)) { $this->next = 'error'; $this->error = 1; $this->nextQuickInfo[] = $this->next_desc = $this->l(sprintf('%s : File format does not match', $currentDbFilename)); return false; } $this->nextParams['dbStep'] = $match[1]; $backupdb_path = $this->backupPath . DIRECTORY_SEPARATOR . $this->restoreName; $dot_pos = strrpos($currentDbFilename, '.'); $fileext = substr($currentDbFilename, $dot_pos + 1); $requests = array(); $content = ''; $this->nextQuickInfo[] = $this->l(sprintf('Opening backup db %1s in %2s mode', $currentDbFilename, $fileext)); switch ($fileext) { case 'bz': case 'bz2': if ($fp = bzopen($backupdb_path . DIRECTORY_SEPARATOR . $currentDbFilename, 'r')) { while (!feof($fp)) { $content .= bzread($fp, 4096); } } else { die("error when trying to open in bzmode"); } // @todo : handle error break; case 'gz': if ($fp = gzopen($backupdb_path . DIRECTORY_SEPARATOR . $currentDbFilename, 'r')) { while (!feof($fp)) { $content .= gzread($fp, 4096); } } gzclose($fp); break; default: if ($fp = fopen($backupdb_path . DIRECTORY_SEPARATOR . $currentDbFilename, 'r')) { while (!feof($fp)) { $content .= fread($fp, 4096); } } fclose($fp); } $currentDbFilename = ''; if (empty($content)) { $this->nextErrors[] = $this->l('database backup is empty'); $this->nextQuickInfo[] = $this->l('database backup is empty'); $this->next = 'rollback'; return false; } // preg_match_all is better than preg_split (what is used in do Upgrade.php) // This way we avoid extra blank lines // option s (PCRE_DOTALL) added $listQuery = preg_split('/;[\\n\\r]+/Usm', $content); unset($content); // @TODO : drop all old tables (created in upgrade) // This part has to be executed only onces (if dbStep=0) if ($this->nextParams['dbStep'] == '1') { $all_tables = $this->db->executeS('SHOW TABLES LIKE "' . _DB_PREFIX_ . '%"', true, false); $drops = array(); foreach ($all_tables as $k => $v) { $table = array_shift($v); $drops['drop table ' . $k] = 'DROP TABLE IF EXISTS `' . bqSql($table) . '`'; $drops['drop view ' . $k] = 'DROP VIEW IF EXISTS `' . bqSql($table) . '`'; } unset($all_tables); $listQuery = array_merge($drops, $listQuery); } file_put_contents($this->autoupgradePath . DIRECTORY_SEPARATOR . $this->toRestoreQueryList, base64_encode(serialize($listQuery))); } // @todo : error if listQuery is not an array (that can happen if toRestoreQueryList is empty for example) $time_elapsed = time() - $start_time; if (is_array($listQuery) && count($listQuery) > 0) { do { if (count($listQuery) == 0) { if (file_exists($this->autoupgradePath . DIRECTORY_SEPARATOR . $this->toRestoreQueryList)) { unlink($this->autoupgradePath . DIRECTORY_SEPARATOR . $this->toRestoreQueryList); } if (count($this->restoreDbFilenames)) { $this->next_desc = sprintf($this->l('Database restoration file %1$s done. %2$s left ...'), $this->nextParams['dbStep'], count($this->restoreDbFilenames)); } else { $this->next_desc = sprintf($this->l('Database restoration file %1$s done.'), $this->nextParams['dbStep']); } $this->nextQuickInfo[] = $this->next_desc; $this->stepDone = true; $this->status = 'ok'; $this->next = 'restoreDb'; if (count($this->restoreDbFilenames) == 0) { $this->next = 'rollbackComplete'; $this->nextQuickInfo[] = $this->next_desc = $this->l('Database has been restored.'); } return true; } // filesForBackup already contains all the correct files if (count($listQuery) == 0) { continue; } $query = array_shift($listQuery); if (!empty($query)) { if (!$this->db->execute($query, false)) { if (is_array($listQuery)) { $listQuery = array_unshift($listQuery, $query); } $this->nextErrors[] = '[SQL ERROR] ' . $query . ' - ' . $this->db->getMsgError(); $this->nextQuickInfo[] = '[SQL ERROR] ' . $query . ' - ' . $this->db->getMsgError(); $this->next = 'error'; $this->error = 1; $this->next_desc = $this->l('Error during database restoration'); return false; } } // note : theses queries can be too big and can cause issues for display // else // $this->nextQuickInfo[] = '[OK] '.$query; $time_elapsed = time() - $start_time; } while ($time_elapsed < self::$loopRestoreQueryTime); $queries_left = count($listQuery); if ($queries_left > 0) { file_put_contents($this->autoupgradePath . DIRECTORY_SEPARATOR . $this->toRestoreQueryList, base64_encode(serialize($listQuery))); } elseif (file_exists($this->autoupgradePath . DIRECTORY_SEPARATOR . $this->toRestoreQueryList)) { unlink($this->autoupgradePath . DIRECTORY_SEPARATOR . $this->toRestoreQueryList); } $this->stepDone = false; $this->next = 'restoreDb'; $this->nextQuickInfo[] = $this->next_desc = sprintf($this->l('%1$s queries left for file %2$s...'), $queries_left, $this->nextParams['dbStep']); unset($query); unset($listQuery); } else { $this->stepDone = true; $this->status = 'ok'; $this->next = 'rollbackComplete'; $this->nextQuickInfo[] = $this->next_desc = $this->l('Database restoration done.'); } return true; }
private function cleanTablesAfterBackup() { // If no more query in list, clean table. (created by user after) if (file_exists($this->autoupgradePath . DIRECTORY_SEPARATOR . $this->toCleanTable)) { $tablesToClean = unserialize(base64_decode(file_get_contents($this->autoupgradePath . DIRECTORY_SEPARATOR . $this->toCleanTable))); if (!empty($tablesToClean)) { foreach ($tablesToClean as $table) { $this->db->execute('DROP TABLE IF EXISTS `' . bqSql($table) . '`'); $this->db->execute('DROP VIEW IF EXISTS `' . bqSql($table) . '`'); } } @unlink($this->autoupgradePath . DIRECTORY_SEPARATOR . $this->toCleanTable); } }
/** * try to restore db backup file * @return type : hey , what you expect ? well mysql errors array ..... * @TODO : maybe this could be in the Backup class */ public function ajaxProcessRestoreDb() { $this->nextParams['dbStep'] = $this->currentParams['dbStep']; $start_time = time(); $db = $this->db(); // deal with the next files stored in restoreDbFilenames if (is_array($this->restoreDbFilenames) && count($this->restoreDbFilenames) > 0) { $currentDbFilename = array_shift($this->restoreDbFilenames); if (!preg_match('#auto-backupdb_([0-9]{6})_#', $currentDbFilename, $match)) { $this->next = 'error'; $this->nextDesc = $this->l(sprintf('%s : File format does not match', $currentDbFilename)); return false; } $this->nextParams['dbStep'] = $match[1]; $backupdb_path = $this->autoupgradePath . DIRECTORY_SEPARATOR . $this->restoreName; $dot_pos = strrpos($currentDbFilename, '.'); $fileext = substr($currentDbFilename, $dot_pos + 1); $requests = array(); $errors = array(); $content = ''; switch ($fileext) { case 'bz': case 'bz2': $this->nextQuickInfo[] = 'opening backup db in bz mode'; if ($fp = bzopen($backupdb_path . DIRECTORY_SEPARATOR . $currentDbFilename, 'r')) { while (!feof($fp)) { $content .= bzread($fp, 4096); } } else { die("error when trying to open in bzmode"); } break; case 'gz': $this->nextQuickInfo[] = 'opening backup db in gz mode'; if ($fp = gzopen($backupdb_path . DIRECTORY_SEPARATOR . $currentDbFilename, 'r')) { while (!feof($fp)) { $content .= gzread($fp, 4096); } gzclose($fp); } break; // default means sql ? // default means sql ? default: $this->nextQuickInfo[] = 'opening backup db in txt mode'; if ($fp = fopen($backupdb_path . DIRECTORY_SEPARATOR . $currentDbFilename, 'r')) { while (!feof($fp)) { $content .= fread($fp, 4096); } fclose($fp); } } $currentDbFilename = ''; if ($content == '') { $this->nextQuickInfo[] = $this->l('database backup is empty'); $this->next = 'rollback'; return false; } // preg_match_all is better than preg_split (what is used in do Upgrade.php) // This way we avoid extra blank lines // option s (PCRE_DOTALL) added $listQuery = preg_split('/;[\\n\\r]+/Usm', $content); unset($content); // @TODO : drop all old tables (created in upgrade) $all_tables = $db->executeS('SHOW TABLES LIKE "' . _DB_PREFIX_ . '%"'); $ignore_stats_table = array(_DB_PREFIX_ . 'connections', _DB_PREFIX_ . 'connections_page', _DB_PREFIX_ . 'connections_source', _DB_PREFIX_ . 'guest', _DB_PREFIX_ . 'statssearch'); $drops = array(); foreach ($all_tables as $k => $v) { $table = array_shift($v); if (!in_array($table, $ignore_stats_table)) { $drops['drop table ' . $k] = 'DROP TABLE IF EXISTS `' . bqSql($table) . '`'; $drops['drop view ' . $k] = 'DROP VIEW IF EXISTS `' . bqSql($table) . '`'; } } unset($all_tables); $listQuery = array_merge($drops, $listQuery); file_put_contents($this->autoupgradePath . DIRECTORY_SEPARATOR . $this->toRestoreQueryList, serialize($listQuery)); } // handle current backup file if (!isset($listQuery)) { $listQuery = unserialize(file_get_contents($this->autoupgradePath . DIRECTORY_SEPARATOR . $this->toRestoreQueryList)); } $time_elapsed = time() - $start_time; if (sizeof($listQuery) > 0) { do { if (sizeof($listQuery) <= 0) { unlink($this->autoupgradePath . DIRECTORY_SEPARATOR . $this->toRestoreQueryList); $currentDbFilename = ''; if (count($this->restoreDbFilenames) > 0) { $this->stepDone = true; $this->status = 'ok'; $this->next = 'restoreDb'; $this->nextDesc = sprintf($this->l('Database restoration step %s done. %s left) ...'), $this->nextParams['dbStep'], count($this->restoreDbFilenames)); $this->nextQuickInfo[] = sprintf('Database restoration step %s done. %s left) ...', $this->nextParams['dbStep'], count($this->restoreDbFilenames)); return true; } else { $this->stepDone = true; $this->status = 'ok'; $this->next = 'rollbackComplete'; $this->nextDesc = $this->l('Database restoration done.'); $this->nextQuickInfo[] = $this->l('database has been restored.'); return true; } } // filesForBackup already contains all the correct files $query = array_shift($listQuery); if (!empty($query)) { if (!$db->execute($query)) { $listQuery = array_unshift($listQuery, $query); $this->nextQuickInfo[] = '[SQL ERROR] ' . $query . ' - ' . $db->getMsgError(); $this->next = 'error'; $this->nextDesc = $this->l('error during database restoration'); return false; } else { $this->nextQuickInfo[] = '[OK] ' . $query; } } $time_elapsed = time() - $start_time; } while ($time_elapsed < self::$loopRestoreQueryTime); unset($query); $queries_left = count($listQuery); file_put_contents($this->autoupgradePath . DIRECTORY_SEPARATOR . $this->toRestoreQueryList, serialize($listQuery)); unset($listQuery); $this->next = 'restoreDb'; $this->nextDesc = sprintf($this->l('%s queries left for %s...'), $queries_left, $this->nextParams['dbStep']); } return true; }