diff --git a/lib/zdb/zdb.class.php b/lib/zdb/zdb.class.php index a7f27633b0..06173ca4e0 100644 --- a/lib/zdb/zdb.class.php +++ b/lib/zdb/zdb.class.php @@ -246,36 +246,38 @@ class zdb fwrite($fp, $backupSql); if($tableType != 'table') continue; + $desc = $this->dbh->query("desc `$table`")->fetchAll(); + $nullFields = array(); + foreach($desc as $field) $nullFields[$field->Field] = $field->Null == 'YES'; + + /* Create key sql for insert. */ + $fields = "`" . join('`,`', array_map('addslashes', array_keys($nullFields))) . "`"; $rows = $this->dbh->query("select * from `$table`"); - $count = 0; $values = array(); - $batchNum = 100; + $batchNum = 200; while($row = $rows->fetch(PDO::FETCH_ASSOC)) { /* Create a value sql. */ - $value = array_values($row); - $value = array_map('addslashes', $value); - $value = join("','", $value); - $value = "'" . $value . "'"; - - $count += 1; - $values[] = "({$value})"; - - if($count % $batchNum == 0) + $row = array_map('addslashes', $row); + $value = array(); + foreach($row as $fieldName => $fieldValue) { - /* Create key sql for insert. */ - $keys = array_keys($row); - $keys = array_map('addslashes', $keys); - $keys = join('`,`', $keys); - $keys = "`" . $keys . "`"; + $length = strlen($fieldValue); + $fieldValue = "'{$fieldValue}'"; + if($length == 0 and $nullFields[$fieldName]) $fieldValue = 'null'; - $sql = "INSERT INTO `$table`($keys) VALUES " . implode(",\n", $values) . ";\n"; + $value[] = $fieldValue; + } + $values[] = '(' . join(',', $value) . ')'; + if(count($values) == $batchNum) + { /* Write sql code. */ - fwrite($fp, $sql); + fwrite($fp, "INSERT INTO `$table`($fields) VALUES " . implode(",\n", $values) . ";\n"); $values = array(); } } + if($values) fwrite($fp, "INSERT INTO `$table`($fields) VALUES " . implode(",\n", $values) . ";\n"); } fclose($fp); return $return; @@ -301,41 +303,46 @@ class zdb return $return; } - $fp = fopen($fileName, 'r'); - $sqlEnd = 0; - while(($buffer = fgets($fp)) !== false) + $fp = fopen($fileName, 'r'); + $sql = ''; + $startTags = '^DROP TABLE|^CREATE TABLE|^INSERT INTO|^SET'; + $isInsert = false; + while(!feof($fp)) { - $line = trim($buffer); + $line = fgets($fp); if(empty($line)) continue; - if($sqlEnd == 0) $sql = ''; - $quotNum = substr_count($line, "'") - substr_count($line, "\'"); - if(substr($line, -1) == ';' and $quotNum % 2 == 0 and $sqlEnd == 0) + $sqlStart = false; + $sqlEnd = false; + $execSQL = false; + if(empty($sql) and preg_match("/{$startTags}/", $line)) $sqlStart = true; + if(!$isInsert and $sqlStart and strpos($line, 'INSERT INTO') === 0) $isInsert = true; + + $endTag = $isInsert ? "[^\\\]\'\);$" : ";$"; + if(preg_match("/{$endTag}/", $line)) $sqlEnd = true; + + if($sqlStart && $sqlEnd) // Only one line sql. e.g. DROP TABLE IF EXISTS `blog`; { - $sql .= $buffer; + $sql = $line; + $execSQL = true; } - elseif($quotNum % 2 == 1 and $sqlEnd == 0) + elseif($sqlStart && !$sqlEnd) // Start sql line. e.g. CREATE TABLE `zt_account` ( { - $sql .= $buffer; - $sqlEnd = 1; + $sql = $line; + $execSQL = false; } - elseif(substr($line, -1) == ';' and $quotNum % 2 == 1 and $sqlEnd == 1) + elseif(!$sqlStart && !$sqlEnd) // Not start and not end. e.g. `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, { - $sql .= $buffer; - $sqlEnd = 0; + $sql .= $line; + $execSQL = false; } - elseif(substr($line, -1) == ';' and $quotNum % 2 == 0 and $sqlEnd == 2) + elseif($sqlEnd) // More line sql, and end line. e.g. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; { - $sql .= $buffer; - $sqlEnd = 0; - } - else - { - $sql .= $buffer; - $sqlEnd = $sqlEnd == 0 ? 2 : $sqlEnd; + $sql .= $line; + $execSQL = true; } - if($sqlEnd == 0) + if($execSQL) { try { @@ -343,9 +350,13 @@ class zdb } catch(PDOException $e) { + a($sql); + exit; $return->result = false; $return->error .= $e->getMessage() . "\n"; } + $sql = ''; + $isInsert = false; } } return $return; diff --git a/module/backup/config/action.php b/module/backup/config/action.php index 08ebd2072e..f4703bc6ec 100644 --- a/module/backup/config/action.php +++ b/module/backup/config/action.php @@ -14,9 +14,7 @@ $config->backup->actionList['rmPHPHeader']['className'] = 'ajax-submit rmPHPHead $config->backup->actionList['restore']['icon'] = 'restart'; $config->backup->actionList['restore']['text'] = $lang->backup->restore; $config->backup->actionList['restore']['hint'] = $lang->backup->restore; -$config->backup->actionList['restore']['url'] = array('module' => 'backup', 'method' => 'restore', 'params' => 'file={name}'); -$config->backup->actionList['restore']['className'] = 'ajax-submit restore'; -$config->backup->actionList['restore']['data-confirm'] = $lang->backup->confirmRestore; +$config->backup->actionList['restore']['url'] = "javascript:restore('{name}')"; $config->backup->actionList['delete']['icon'] = 'trash'; $config->backup->actionList['delete']['text'] = $lang->delete; diff --git a/module/backup/control.php b/module/backup/control.php index 9907fe9f9b..44259d82a8 100644 --- a/module/backup/control.php +++ b/module/backup/control.php @@ -116,7 +116,7 @@ class backup extends control $result = $this->backupZen->restoreFile($fileName); if($result['result'] == 'fail') return $this->send($result); - return $this->send(array('result' => 'success', 'callback' => "zui.Modal.alert('{$this->lang->backup->success->restore}')")); + return $this->send(array('result' => 'success', 'closeModal' => true, 'callback' => "zui.Modal.alert('{$this->lang->backup->success->restore}').then(() => {loadCurrentPage()})")); } /** diff --git a/module/backup/js/index.ui.js b/module/backup/js/index.ui.js index 08f34a5383..a6c69310eb 100644 --- a/module/backup/js/index.ui.js +++ b/module/backup/js/index.ui.js @@ -27,7 +27,7 @@ window.backup = function(e) $('#waiting .modal-content #message').html(data); }); }, 1000); -} +}; window.getCellSpan = function(cell) { @@ -35,20 +35,30 @@ window.getCellSpan = function(cell) { return {rowSpan: cell.row.data.rowspan}; } -} +}; + +window.restore = function(name) +{ + zui.Modal.confirm({message: confirmDeleteLang, icon:'icon-info-sign', iconClass: 'warning-pale rounded-full icon-2x'}).then((res) => + { + if(res) + { + $.ajaxSubmit({url: $.createLink('backup', 'restore', 'file=' + name)}); + + zui.Modal.open({id: 'waiting', size: 'sm', backdrop: false}); + $('#waiting').addClass('show'); + $('#waiting .modal-body #backupType').html(restoreLang); + $('#waiting .modal-body #message').empty(); + } + }); +}; $(document).off('click', '.rmPHPHeader').on('click', '.rmPHPHeader', function(data) { + if($(this).hasClass('disabled')) return false; + zui.Modal.open({id: 'waiting', size: 'sm', backdrop: false}); $('#waiting').addClass('show'); $('#waiting .modal-body #backupType').html(rmPHPHeaderLang); $('#waiting .modal-body #message').empty(); -}) - -$(document).off('click', '.restore').on('click', '.restore', function(data) -{ - zui.Modal.open({id: 'waiting', size: 'sm', backdrop: false}); - $('#waiting').addClass('show'); - $('#waiting .modal-body #backupType').html(restoreLang); - $('#waiting .modal-body #message').empty(); }); diff --git a/module/backup/ui/index.html.php b/module/backup/ui/index.html.php index ff9702fe61..204107bd2e 100644 --- a/module/backup/ui/index.html.php +++ b/module/backup/ui/index.html.php @@ -13,6 +13,7 @@ namespace zin; jsvar('backupLang', $lang->backup->common); jsvar('rmPHPHeaderLang', $lang->backup->rmPHPHeader); jsvar('restoreLang', $lang->backup->restore); +jsvar('confirmDeleteLang', $lang->backup->confirmDelete); featureBar (