back_content .= "\r\nSET SQL_MODE='NO_AUTO_VALUE_ON_ZERO';\r\n\r\n"; $_SESSION['db_backup']['table_name'] = $_SESSION['db_backup']['backup_tables'][0]; } $this->step = $step; if (!empty($_SESSION['db_backup']['table_name'])){ $key = array_search($_SESSION['db_backup']['table_name'],$table_list); if ($key > 0){ for ($i=0; $i<$key; $i++){ unset($table_list[$i]); } } } /** * 创建表sql */ if ($_SESSION['db_backup']['op'] == 'create'){ foreach ($table_list as $k => $v){ /** * 写入session */ $_SESSION['db_backup']['table_name'] = $v; $result = $this->getCreateContent($v); /** * 跳出 */ if ($result === false){ return true; } /** * 判断是否最后结束 */ if (empty($table_list[$k+1])){ /** * 写入文件 */ $this->writeBackFile(); /** * 写入session op */ $_SESSION['db_backup']['op'] = 'insert'; $_SESSION['db_backup']['table_name'] = $_SESSION['db_backup']['backup_tables'][0]; return true; } } } /** * 表信息sql */ if ($_SESSION['db_backup']['op'] == 'insert'){ foreach ($table_list as $k => $v){ /** * 写入session */ $_SESSION['db_backup']['table_name'] = $v; while (true) { $result = $this->getInsertContent($v); if ($result === 'succ'){ break; } /** * 跳出 */ if ($result === false){ return true; } } /** * 判断是否最后结束 */ if (empty($table_list[$k+1]) && $_SESSION['db_backup']['limit'] == 0){ /** * 写入文件 */ $this->writeBackFile(); return true; } } } return true; } /** * 表名列表 * * @param string $type all/self 取表列表范围,all为整个数据库全部表,self为产品自己的表 * @return array $rs_row 返回数组形式的查询结果 */ public function getTableList($type = 'self'){ $table_list = array(); $tmp = Db::showTables(); $count = strlen(DBPRE); $table = "Tables_in_" . DBNAME; if ($type == 'all') { if (is_array($tmp)) { foreach ($tmp as $k => $v) { $table_list[] = $v[$table]; } } } if ($type == 'self') { if (is_array($tmp)) { foreach ($tmp as $k => $v) { $table_list[] = $v[$table]; } } } return $table_list; } /** * create表语句内容 * * @param * @return string 字符串类型的返回结果 */ private function getCreateContent($table){ /** * 构造语句 */ $tmp_create = "DROP TABLE IF EXISTS `". $table ."`;\r\n"; $tmp_create .= Db::showCreateTable(substr($table,strlen(DBPRE),strlen($table)-1)); $tmp_create .= ";\r\n\r\n"; /** * 判断长度 */ if (strlen($this->back_content.$tmp_create) >= $_SESSION['db_backup']['size']){ /** * 写入文件,跳出 */ $this->writeBackFile(); /** * 停止备份 */ return false; }else { /** * 增加备份语句 */ $this->back_content .= $tmp_create; /** * 继续备份 */ return true; } } /** * 转换特殊符号 * * @param * @return string 字符串类型的返回结果 */ private function sqlAddslashes($a_string = '', $is_like = false, $crlf = false, $php_code = false){ if ($is_like) { $a_string = str_replace('\\', '\\\\\\\\', $a_string); } else { $a_string = str_replace('\\', '\\\\', $a_string); } if ($crlf) { $a_string = str_replace("\n", '\n', $a_string); $a_string = str_replace("\r", '\r', $a_string); $a_string = str_replace("\t", '\t', $a_string); } if ($php_code) { $a_string = str_replace('\'', '\\\'', $a_string); } else { $a_string = str_replace('\'', '\'\'', $a_string); } return $a_string; } /** * insert表语句内容 * * @param * @return string 字符串类型的返回结果 */ private function getInsertContent($table){ /** * 开始条数 */ $limit = $_SESSION['db_backup']['limit']?$_SESSION['db_backup']['limit']:0; /** * 当前语句大小 */ $now_size = strlen($this->back_content); /** * 取信息 */ $param = array(); $param['table'] = substr($table,strlen(DBPRE),strlen($table)-1); $param['limit'] = $limit.',300'; $param['cache'] = false; $list = Db::select($param); /** * 没有信息 */ if (empty($list)){ /** * limit数据归0 */ $_SESSION['db_backup']['limit'] = 0; /** * 继续back循环 */ return 'succ'; } /** * 字段信息 */ $columns_array = Db::showColumns(substr($table,strlen(DBPRE),strlen($table)-1)); /** * 生成sql语句 */ $result = ''; foreach ($list as $k => $v){ $tmp_sql = ''; $tmp_columns = ''; $tmp_value = ''; /** * 字段信息 */ foreach ($columns_array as $k_col => $v_col){ /** * 字段 */ $tmp_columns .= "`". $k_col ."`,"; /** * 值 */ if ($v_col['null'] == 'YES'){ if (empty($v[$k_col])){ $tmp_value .= "NULL,"; }else { $tmp_value .= "'". $this->sqlAddslashes($v[$k_col]) ."',"; } }else { $tmp_value .= "'". $this->sqlAddslashes($v[$k_col]) ."',"; } } /** * 构造语句 */ $tmp_sql .= "INSERT INTO `".$table."` "; $tmp_sql .= "("; $tmp_sql .= trim($tmp_columns,','); $tmp_sql .= ") VALUES("; $tmp_sql .= trim($tmp_value,','); $tmp_sql .= ")"; $tmp_sql .= ";\r\n"; /** * 判断字符串大小限制 */ if (strlen($this->back_content.$tmp_sql) >= $_SESSION['db_backup']['size']){ /** * 备份文件 */ $this->writeBackFile(); /** * 超过限制,跳出讯号 */ return false; }else { /** * 增加session中的limit计数 */ $_SESSION['db_backup']['limit']++; $this->back_content .= $tmp_sql; } } /** * 结束该表的读取,limit归0 */ if (count($list) < 10){ $_SESSION['db_backup']['limit'] = 0; $this->back_content .= "\r\n"; return 'succ'; } /** * 继续back循环 */ return true; } /** * 获取目录 * * @param * @return */ public function getBackDir(){ /** * 按照日期进行生成 */ $dir_list = readDirList(BASE_ROOT_PATH.DS.'sql_back'); $tmp = date('Ymd'); $check_array = array(); if (is_array($dir_list)){ foreach ($dir_list as $k => $v){ if (substr($v,0,strlen($tmp)) == $tmp){ $check_array[] = substr($v,strlen($tmp)+1,strlen($v)); } } } $return = $tmp.'_'.($check_array[count($check_array)-1]+1); return $return; } /** * 写入文件 * * @param int $id 记录ID * @return array $rs_row 返回数组形式的查询结果 */ public function writeBackFile(){ Language::read('model_lang_index'); $lang = Language::getLangContent(); $step = $this->step; try { if (!is_dir(BASE_ROOT_PATH.DS.'sql_back'.DS.$_SESSION['db_backup']['back_file'])){ if (!$this->mkdirs(BASE_ROOT_PATH.DS.'sql_back'.DS.$_SESSION['db_backup']['back_file'],0755)){ $error = $lang['db_backup_mkdir_fail']; throw new Exception($error); }else { $fp = @fopen(BASE_ROOT_PATH.DS.'sql_back'.DS.$_SESSION['db_backup']['back_file'].DS.'index.html','w+'); @fclose($fp); } } $file_name = BASE_ROOT_PATH.DS.'sql_back'.DS.$_SESSION['db_backup']['back_file'].DS.$_SESSION['db_backup']['back_file'].'_'.$step.'_'.$_SESSION['db_backup']['md5'].'.sql'; $fp = @fopen($file_name,'w+'); if (@fwrite($fp,$this->back_content) === false){ $error = $lang['db_backup_vi_file_fail']; throw new Exception($error); } @fclose($fp); }catch (Exception $e){ showMessage($e->getMessage(),'','exception'); } return true; } /** * 建立多级目录 * * @param string $dir 目录 * @return true */ public function mkdirs($dir){ if (!is_dir($dir)) { if (!$this->mkdirs(dirname($dir))) { return false; } if (!mkdir($dir, 0777)) { return false; } } return true; } /** * 数据库备份导入 * * @param string $path 目录 * @param int $step 步骤,也是第几个文件 * @return array $rs_row 返回数组形式的查询结果 */ public function import($path,$step=1){ $dir = BASE_ROOT_PATH.DS.'sql_back'.DS.$path; $file_list = array(); readFileList($dir,$file_list); /** * 过滤文件 */ if (!empty($file_list) && is_array($file_list)){ foreach ($file_list as $key=>$file_name){ if (strtolower(substr($file_name,-4)) == '.sql'){ $tmp_list[] = $file_name; } } $file_list = $tmp_list; } foreach($file_list as $k=>$v){ $varr = explode('_',$v); $file_list[$k] = $varr['0'].'_'.$varr['1'].'_'.$varr['2'].'_'.$varr['3'].'_'.($k+1).'_'.$varr['5']; } $file_name = $file_list[$step-1]; //此处使用is_file来判断该sql文件是否存在,不使用file_exists if (is_file($file_name)){ $handle = @fopen($file_name, "r"); $tmp_sql = ''; if ($handle) { while (!feof($handle)) { $buffer = fgets($handle); if (trim($buffer) != ''){ $tmp_sql .= $buffer; if (substr(rtrim($buffer),-1) == ';'){ if (preg_match('/^(CREATE|ALTER|DROP)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i', ltrim($tmp_sql))){ //标准的SQL语句,将被执行 }else if (preg_match('/^(INSERT)\s+(INTO)\s+/i', ltrim($tmp_sql)) && substr(rtrim($buffer),-2) == ');'){ //标准的SQL语句,将被执行 }else if (preg_match('/^(SET)\s+SQL_MODE=/i', ltrim($tmp_sql))){ //SET SQL_MODE 设置,将被执行 }else{ //不能组成标准的SQL语句,继续向下一行取内容,直到组成合法的SQL为止 continue; } if (!empty($tmp_sql)){ /** * 销毁当前用户Session信息 */ if (strpos($tmp_sql,cookie('sess_id')) !== false){ unset($tmp_sql); continue; } Db::query($tmp_sql,'slave'); unset($tmp_sql); } } } } @fclose($handle); } /** * 判断是否还有下个文件 */ if (empty($file_list[$step])){ return 'succ'; }else { return 'continue'; } }else { return false; } } }