<?php
@header("Expires: -1");
@header("Cache-Control: no-store, private, post-check=0, pre-check=0, max-age=0", FALSE);
@header("Pragma: no-cache");
/**
  *	Dvbbs.php  - Version: 2.0.0
  *	Web: http://www.dvbbs.net
  *	Copyright: 2000-2006 Dvbbs.Net
  *	script file:user.php
  *	Script Written by lfow(Xiao Du)
  *	Function of the Page:数据库表服务、数据库备份、恢复
  */
ini_set('display_errors','1');
define('THIS_SCRIPT', 'db_maintance');

//add by hj@dv 200712225
define('ERROR_FILE_CANNOT_OPEN_FOR_READ',0x01);
define('ERROR_FILE_CANNOT_OPEN_FOR_WRITE',0x02);
define('ERROR_FILE_CANNOT_OPEN_FOR_APPEND',0x04);
define('ERROR_FILE_NOEXISTS',0x08);
define('ERROR_TABLE_EXISTS',0x08);
define('DATA_BACKUP_ADDHEAD','<?php exit; ?>');//附加的文件头，防止备份文件被下载
define('RESTORE_CREATE_IFNOEXITS',0x1);
define('RESTORE_CREATE_ALWAY',0x2);
//END add by hj@dv 200712225

set_magic_quotes_runtime(0);
//define('DATABASE_DEBUG', true);//调试标志
require_once 'global.php';
defined('MAIN_DOMAIN_NAME') AND exit('Access denied');
require INC_PATH.'filehandle.misc.php';
require INC_PATH.'FileHandler.class.php';
if(!isset($_SESSION['admin_login']))
checklogin();
$_SESSION['admin_login']= 1;
head($lang['PageTitle']);
if ( strpos($sysinfo['flag'],'30,') === false ){
	show_msg($lang['readme_tit'],$lang['error.str1'],0,'','','','');
	exit;
}
$lang=load_lang($lang, 'db_maintance' );

$doaction = trim($doaction);
if( $doaction === '' ){
	$doaction = 'table_service';
}
$outputDir = './data_backup';
$_arr_backurl = array(0=>'./db_maintance.php?doaction=table_service', 1=>'./db_maintance.php?doaction=dump_data', 2=>'./db_maintance.php?doaction=import_data');
if( $doaction === 'table_service' ){
	if( $sub_action === 'do_submit' ){
		ExecuteTableService();
		footer();
		exit;
	}
} elseif( $doaction === 'dump_data' ){
	if( $sub_action === 'do_submit' ){
		clearstatcache();
		if (!FileHandler::_dir_is_writable($outputDir)) {
			unset($_SESSION['DataDump_Opts']);
			show_msg($lang['Error.strings3'],str_replace('{$TPL_destdir}', $outputDir, $lang['Error.strings10']),$execSuccessed,'','',$_arr_backurl[1],$lang['cmdback']);
			exit;
		}
		DumpData();
		footer();
		exit;
	} else{
		$arrDataPath = array(
		'output_dir' => $outputDir
		,'output_file_noextension' => strtolower(substr(base64_encode(uniqid(gmdate('Ymd'),true)),20,8))
		,'output_file_extension' => '.sql'
		);
	}
} elseif( $doaction === 'import_data' ){
	if( $sub_action === 'do_submit' ){
		clearstatcache();
		ImportData();
		footer();
		exit;
	} elseif( $sub_action === 'delete_server_files' ){
		$deletedCount = 0;
		$count= 0;
		if( !empty($server_files) && is_array($server_files) ){
			foreach( $server_files as $currFile ){
				$arrDumpedFiles =& GetDumpedFiles();
				if( is_array($arrDumpedFiles) && !empty($arrDumpedFiles) ){
					foreach( $arrDumpedFiles as $key => $val ){
						if($currFile == ($val['path'].'/'.$val['entry'])){
							$currVolNum = $val['identify']['curr_volume_num'];
							break;
						}
					}
				}
				if(isset($currVolNum)){
					if( is_array($arrDumpedFiles) && !empty($arrDumpedFiles) ){
						foreach( $arrDumpedFiles as $key => $val ){
							$currUrlEncodeFile = $val['path'].'/'.$val['entry'];
							if( is_file($currUrlEncodeFile) ){
								$temp = preg_replace("/-(?:{$val['identify']['curr_volume_num']})(\..+)$/","-{$currVolNum}\\1",$currUrlEncodeFile);
								if($temp == $currFile){
									$count++;
									if(unlink($currUrlEncodeFile))
									$deletedCount++;
								}
							}
						}
					}
				}

			}
		}
		if($count == 0){
			show_msg($lang['template.strings10'],$lang['Error.strings16'],0,'','',$_arr_backurl[2],$lang['cmdback']);
		}
		if( $deletedCount > 0 ){
			if( $deletedCount === $count ){
				show_msg($lang['template.strings10'],str_replace('{$Num}',$deletedCount,$lang['template.strings11']),1,'','',$_arr_backurl[2],$lang['cmdback']);
			} else{
				$execResult = str_replace('{$Num1}',($count-$deletedCount),str_replace('{$Num1}',$deletedCount,$lang['template.strings12']));
				show_msg($lang['template.strings10'],$execResult,1,'','',$_arr_backurl[2],$lang['cmdback']);
			}
		} else{
			show_msg($lang['template.strings10'],$lang['Error.strings16'],0,'','',$_arr_backurl[2],$lang['cmdback']);
		}
		footer();
		exit;
	}
}
require printout('db_maintance');


footer();

function &GetTableStatus(){
	global $db,$dv;
	return $db->getResultSet("SHOW TABLE STATUS");
}

function &ExecuteTableService(){
	global $lang,$db,$dv,$table_name,$table_service,$_arr_backurl;
	$tableNameList = implode(',', $table_name);
	$strResult = '';
	if( is_array($table_service) && !empty($table_service) ){
		$iswin = (false !== strpos(strtolower(PHP_OS), 'win'));
		foreach( $table_service as $key => $val ){
			if ('repair' === $key AND true === $iswin) {
				$usequickrepair = ' QUICK ';
			} else {
				$usequickrepair = '';
			}
			if( $query = $db->query("{$key} TABLE {$tableNameList} {$usequickrepair}") ){
				while( $dbResult = $db->fetch_array($query) ){
					$result = $dbResult['Msg_text'];
					$TableName = $dbResult['Table'];
					eval('$strResult .= "'.addslashes($lang["TableService"][$key]).'";');
				}
			}
		}
	}
	show_msg($lang['template.strings3'],( $strResult === '' ? $lang['Error.strings2'] : $strResult ),1,'','',$_arr_backurl[0],$lang['cmdback']);
}

function DumpData(){
	global $HTTP_SESSION_VARS,$_POST,$arrDataPath,$curr_volume_num,$lang,$db,$dbhost,$dbname,$dbuser,$dbpw,$dbport,$_arr_backurl;
	session_start();
	if( PHP_VERSION < '4.1.0' ){
		$_SESSION =& $HTTP_SESSION_VARS;
	}
	if( $curr_volume_num === '-1' ){
		if( isset($_SESSION['DataDump_Opts']) ){
			$MultiVolumeList = '';
			foreach( $_SESSION['DataDump_Opts']['dumped_files'] as $currFileName ){
				$MultiVolumeList .= '<li><a href="'.$currFileName.'" onclick="alert(\''.$lang['maintance.info55'].'\');return false;">'.$currFileName.'</a></li>';
			}
			$FileCount = count($_SESSION['DataDump_Opts']['dumped_files']);
			unset($_SESSION['DataDump_Opts']);
			eval('$execResult="'.addslashes($lang['template.strings5']).'";');
			show_msg($lang['template.strings3'],$execResult,1,'','',$_arr_backurl[1],$lang['cmdback']);
			return true;
		} else{
			show_msg($lang['template.strings3'],$lang['Error.strings8'],0,'','',$_arr_backurl[1],$lang['cmdback']);
			return false;
		}
	}
	if( !is_numeric($curr_volume_num) || $curr_volume_num < 0 ){
		$curr_volume_num = 0;
	}
	if( $curr_volume_num === 0 &&$_GET['callback']!='ajaxcallback'){
		unset($_SESSION['DataDump_Opts']);
	}
	if( !isset($_SESSION['DataDump_Opts']) ){
		$_SESSION['DataDump_Opts'] = array(
		'dump_file' => $_POST['base_dir'].'/'.$_POST['dump_file']
		,'dump_base_dir' => $_POST['base_dir']
		,'dump_method' => $_POST['dump_method']
		,'dump_volume_size' => (is_numeric($_POST['dump_volume_size'])&&$_POST['dump_volume_size']>0?$_POST['dump_volume_size']:2048)
		,'add_drop_table' => $_POST['add_drop_table']
		,'delayed_insert' => $_POST['delayed_insert']
		,'insert_ignore' => $_POST['insert_ignore']
		,'add_locks' => $_POST['add_locks']
		,'extended_insert' => $_POST['extended_insert']
		,'default_character_set' => $_POST['default_character_set']
		,'disable_keys' => $_POST['disable_keys']
		,'dump_tables' => $_POST['dump_tables']
		,'row_offset_point' => 0
		,'table_name_point' => $_POST['dump_tables'][0]
		,'dumped_files' => array()
		);
	}
	$_dumpOpts =& $_SESSION['DataDump_Opts'];
	if( !is_array($_dumpOpts['dump_tables']) || empty($_dumpOpts['dump_tables']) ){
		show_msg($lang['Error.strings3'],$lang['Error.strings4'],$execSuccessed);
		return false;
	}
	if( $_dumpOpts['dump_method'] === 'shell' ){
		if( TestShellExec() === true ){
			$execSuccessed = 0;
			if( !$_dumpOpts['dump_file'] ){
				show_msg($lang['template.strings3'],$lang['Error.strings5'],$execSuccessed,'','',$_arr_backurl[1],$lang['cmdback']);
				return false;
			}
			$shellCmd = '';
			if ($query = $db->query("SHOW TABLE STATUS")) {
				while ($dbinfo =& $db->fetch_array($query)) {
					$engine = ($dbinfo['Engine'] ? $dbinfo['Engine'] : $dbinfo['Type']);
					if (1 == preg_match('/MRG_MyISAM|MERGE/i', $engine)) {
						$_dumpOpts['dump_tables'][] = $dbinfo['Name'];
					}
				}//end while
			}
			if ($fp = fopen($_dumpOpts['dump_file'], 'w')) {
				fwrite($fp, "-- <?php exit(); ?> <% Response.Write(\"Access denied!\") %> <% Response.End() %> \r\n");

				fclose($fp);
				$shellCmd = GetMysqlBaseDir()."mysqldump --force --add-drop-table".($_dumpOpts['add_drop_table']=='1'?'':'=no')." --extended-insert".($_dumpOpts['extended_insert']=='1'?'':'=no')." --delayed-insert".($_dumpOpts['delayed_insert']=='1'?'':'=no')." --insert-ignore".($_dumpOpts['insert_ignore']=='1'?'':'=no')." --add-locks".($_dumpOpts['add_locks']=='1'?'':'=no')." --disable-keys".($_dumpOpts['disable_keys']==='1'?'':'=no')." ".( $db->version()>='4.1'?' --compatible=mysql40 ':'')."  -h {$dbhost} ".($dbport?(is_numeric($dbport)?" -P {$dbport} ":" -S {$dbport}"):'').' --user='.$dbuser.' --password='.$dbpw.' --default-character-set=gbk '.$dbname.' '.implode(' ',$_dumpOpts['dump_tables']).' >> '.$_dumpOpts['dump_file'];
			}
			if(!empty($shellCmd) AND !@shell_exec($shellCmd) ){
				$_dumpOpts['dumped_files'][] = $_dumpOpts['dump_file'];
				$UrlRedirect = '<script>setTimeout("window.location.href=\''.getRawUrl()."?doaction=dump_data&sub_action=do_submit&curr_volume_num=-1".'\';",1250)</script>';
				$execResult = str_replace('{$BackupFileName}',$_dumpOpts['dump_file'],$lang['template.strings1']).$UrlRedirect;
				$execSuccessed = 1;
			} else{
			}
		} else{
			$execResult = $lang['Error.strings3'];
		}
	} elseif( $_dumpOpts['dump_method'] === 'symlink' ){
		$strDumpSql = '';
		$arrDumpSql = array();
		if( TestSymLink() !== true ){
			show_msg($lang['Error.strings3'],$lang['Error.strings9'],$execSuccessed,'','',$_arr_backurl[1],$lang['cmdback']);
			return false;
		}
		$dumpDir = realpath("{$_dumpOpts['dump_base_dir']}/{$_dumpOpts['dump_output_dir']}/");
		if( is_array($_dumpOpts['dump_tables']) && !empty($_dumpOpts['dump_tables']) ){
			if ($query = $db->query("SHOW TABLE STATUS")) {
				while ($dbinfo =& $db->fetch_array($query)) {
					$engine = ($dbinfo['Engine'] ? $dbinfo['Engine'] : $dbinfo['Type']);
					if (1 == preg_match('/MRG_MyISAM|MERGE/i', $engine)) {
						$_dumpOpts['dump_tables'][] = $dbinfo['Name'];
					}
				}//end while
			}
			foreach( $_dumpOpts['dump_tables'] as $currTableName ){
				$destTableName = "__{$currTableName}";
				$destDataFile = $dumpDir.'/'.$destTableName.'.MYD';
				$renameDestDataFile = $dumpDir.'/__dv_symlink'.$destTableName.'.MYD';
				if( is_file($renameDestDataFile) ){
					unlink($renameDestDataFile);
				}
				$query = $db->query("DROP /*! TEMPORARY */ TABLE /*! IF EXISTS */ {$destTableName}");
				if( $query = $db->query("CREATE /*! TEMPORARY */ TABLE {$destTableName} DATA DIRECTORY='{$dumpDir}/' SELECT * FROM {$currTableName}") ){
					if( is_file($destDataFile) && rename($destDataFile,$renameDestDataFile) ){
						if( touch($destDataFile) && chmod($destDataFile,0666) ){
							$arrDumpSql["{$destTableName}"]['DropStmt'] = "DROP TABLE /*! IF EXISTS */ {$currTableName}";
							$query = $db->query("SHOW CREATE TABLE {$currTableName}");
							list(,$currTableCreateStmt) = $db->fetch_row($query);
							$arrDumpSql["{$destTableName}"]['CreateStmt'] = str_replace('`', '', preg_replace('/( +DEFAULT +CHARSET=[^ ]+)/i','/*!40101 $1*/',$currTableCreateStmt));
							$query = $db->query("SHOW CREATE TABLE {$destTableName}");
							list(,$currTableCreateStmt) = $db->fetch_row($query);
							$arrDumpSql["{$destTableName}"]['CreateTmpStmt'] = str_replace('`','',preg_replace(array('/( +DEFAULT +CHARSET=[^ ]+)/i', '/(data +directory=[^ ]+)/i'), array('/*!40101 $1 */', '/*!40000 $1*/'), $currTableCreateStmt));
							$query = $db->query("DROP /*! TEMPORARY */ TABLE /*! IF EXISTS */ {$destTableName}");
							$arrDumpSql["{$destTableName}"]['tableNamePoint'] = '__dv_symlink'.$destTableName;
						}
					}
				}
			}
			if( !empty($arrDumpSql) ){
				$currDumpFile = $_dumpOpts['dump_file'];
				if( $fp = fopen($currDumpFile,'wb') ){
					@flock($fp,2);
					$strDumpSql = "\r\n/*\r\n".base64_encode(serialize($arrDumpSql))."\r\n*/\r\n";
					$dumpHeader = GetDumpHeader(array('data_format'=>'SymLink','dumped_tables'=>$_dumpOpts['dump_tables']));
					$fwrited = @fwrite($fp,$dumpHeader.$strDumpSql,strlen($strDumpSql)+strlen($dumpHeader));
					@fclose($fp);
					chmod($currDumpFile,0666);
					$_dumpOpts['dumped_files'][] = $currDumpFile;
				}
				if( count($_dumpOpts['dumped_files']) > 0 ){
					$execSuccessed = 1;
					$UrlRedirect = '<script>setTimeout("window.location.href=\''.getRawUrl()."?doaction=dump_data&sub_action=do_submit&curr_volume_num=-1".'\';",1250)</script>';
					$execResult = str_replace('{$BackupFileName}',$_dumpOpts['dump_file'],$lang['template.strings1']).$UrlRedirect;
				} else{
					$execResult = $lang['Error.strings7'];
				}
			}
		} else{
			$execResult = $lang['Error.strings4'];
		}
	}elseif( $_dumpOpts['dump_method'] === 'multivol' ){
		if( !empty($_dumpOpts['table_name_point']) && is_array($_dumpOpts['dump_tables']) && !empty($_dumpOpts['dump_tables']) ){
			$sizeLimit_kb = $_dumpOpts['dump_volume_size'] * 1000;
			$pageSize = 500;
			//数据字符集支持
			$strDumpSql  = "/*!40101 SET NAMES '{$_dumpOpts['default_character_set']}' */;\r\n";
			$strDumpSql .= "/*!40014 SET UNIQUE_CHECKS=0 */;\r\n";
			$strDumpSql .= "/*!40014 SET FOREIGN_KEY_CHECKS=0 */;\r\n";
			$dataLength = 0;
			$strStmt_InsertIgnore = '';
			if( $_dumpOpts['insert_ignore'] === '1' ){
				$strStmt_InsertIgnore = '/*! IGNORE */';
			}
			$strStmt_DelayedInsert = '';
			if( $_dumpOpts['delayed_insert'] === '1' ){
				$strStmt_DelayedInsert = '/*! DELAYED */';
			}
			foreach( $_dumpOpts['dump_tables'] as $index => $currTableName ){
				if( $dataLength >= $sizeLimit_kb ){
					break;
				}
				if( $currTableName !== $_dumpOpts['table_name_point'] ){
					continue;
				}
				$query = $db->query("SHOW TABLE STATUS LIKE '{$currTableName}'");
				$currTableStatus = $db->fetch_array($query);
				if( $_dumpOpts['row_offset_point'] <= 0 ){
					if( $_dumpOpts['add_drop_table'] === '1' ){
						$strDumpSql .= "DROP TABLE /*! IF EXISTS */ {$currTableName};\r\n";
					}
					$query = $db->query("SHOW CREATE TABLE {$currTableName}");
					list(,$currTableCreateStmt) = $db->fetch_row($query);
					$strDumpSql .= preg_replace(array('/( +DEFAULT +CHARSET=.+?$)/i','/`/i','/\r|\n/i'),array('/*!40101 $1*/','',''),$currTableCreateStmt).";\r\n";
					if( $_dumpOpts['add_locks'] === '1' ){//锁定表
						$strDumpSql .= "/*! LOCK TABLES {$currTableName} WRITE */;\r\n";
					}
					if( $_dumpOpts['disable_keys'] === '1' ){//插入前禁用键
						$strDumpSql .= "/*!40000 ALTER TABLE {$currTableName} DISABLE KEYS */;\r\n";
					}
				}
				for( $i = $_dumpOpts['row_offset_point'] ; $dataLength < $sizeLimit_kb && $i < $currTableStatus['Rows'] ; $i += $pageSize ){
					if( $query = $db->query("SELECT * FROM {$currTableName}",array('rowOffset'=>$i,'pageSize'=>$pageSize)) ){
						$comma1 = '';
						if( $_dumpOpts['extended_insert'] === '1' ){
							$strDumpSql .= "INSERT{$strStmt_DelayedInsert}{$strStmt_InsertIgnore} INTO {$currTableName} VALUES ";
							while( $dataLength < $sizeLimit_kb && ($result = $db->fetch_array($query)) ){
								$strDumpSql .= $comma1.'(';
								$comma1 = ',';
								$comma2 = '';
								foreach( $result as $val ){
									if (is_null($val)) {
										$strDumpSql .= $comma2.'NULL';
									} elseif (is_int($val)) {
										$strDumpSql .= $comma2.$val;
									} else {
										$strDumpSql .= $comma2."'".$db->escape_string($val)."'";
									}
									$comma2 = ',';
								}
								$strDumpSql .= ")";
								$dataLength = strlen($strDumpSql);
								$_dumpOpts['row_offset_point']++;
							}
							$strDumpSql .= ";\r\n";
							$dataLength += 3;
						} else{
							while( $dataLength < $sizeLimit_kb && ($result = $db->fetch_array($query)) ){
								$strDumpSql .= "INSERT{$strStmt_DelayedInsert}{$strStmt_InsertIgnore} INTO {$currTableName} VALUES(";
								$comma2 = '';
								foreach( $result as $val ){
									if (is_null($val)) {
										$strDumpSql .= $comma2.'NULL';
									} elseif (is_int($val)) {
										$strDumpSql .= $comma2.$val;
									} else {
										$strDumpSql .= $comma2."'".$db->escape_string($val)."'";
									}
									$comma2 = ',';
								}
								$strDumpSql .= ");\r\n";
								$dataLength = strlen($strDumpSql);
								$_dumpOpts['row_offset_point']++;
							}
						}
					}
				}
				if( $_dumpOpts['row_offset_point'] >= $currTableStatus['Rows'] ){//一个表处理结束
					$_dumpOpts['row_offset_point'] = 0;
					$_dumpOpts['table_name_point'] = $_dumpOpts['dump_tables'][$index+1];
					if( $_dumpOpts['disable_keys'] === '1' ){//插入前禁用键
						$tmpStmt = "/*!40000 ALTER TABLE {$currTableName} ENABLE KEYS */;\r\n";
						$strDumpSql .= $tmpStmt;
						$dataLength += strlen($tmpStmt);
					}
					if( $_dumpOpts['add_locks'] === '1' ){
						$tmpStmt = "/*! UNLOCK TABLES */;\r\n";
						$strDumpSql .= $tmpStmt;
						$dataLength += strlen($tmpStmt);
					}
				}
			}
			$fwrited = false;
			$UrlRedirect = '';
			$NextDumpDesc = '';
			$currDumpFile = $_dumpOpts['dump_file'];
			if( $strDumpSql !== '' && $dataLength > 0 ){
				if( $_dumpOpts['row_offset_point'] > 0 || $curr_volume_num > 0 ){
					$curr_volume_num++;
					$tmpStr = substr($currDumpFile, 0, strrpos($currDumpFile, '.'))."-%s".strrchr($currDumpFile, '.');
					$currDumpFile = sprintf($tmpStr,$curr_volume_num);
					if( !empty($_dumpOpts['table_name_point']) ){
						$NextDumpDesc = sprintf($tmpStr,$curr_volume_num+1);
					}
				}
				if( $fp = fopen($currDumpFile,'wb') ){
					@flock($fp,2);
					$dumpHeader = GetDumpHeader(array('data_format'=>'MultiVolume','curr_volume_num'=>$curr_volume_num,'next_volume_num'=>($_dumpOpts['table_name_point']?$curr_volume_num+1:0)));
					$fwrite_data = $dumpHeader.$strDumpSql;
					$fwrited = @fwrite($fp, $fwrite_data, strlen($fwrite_data));
					@fclose($fp);
					@chmod($currDumpFile,0777);
				}
			}
			if( $fwrited !== false ){
				$_dumpOpts['dumped_files'][] = $currDumpFile;
				if( $_dumpOpts['row_offset_point'] > 0 && $_dumpOpts['table_name_point'] ){
					$UrlRedirect = '<script>setTimeout("window.location.href=\''.getRawUrl()."?doaction=dump_data&sub_action=do_submit&curr_volume_num={$curr_volume_num}".'\';",1250)</script>';
				} else{
					if ($fp = fopen($currDumpFile, 'ab')) {
						$footer_data = GetDumpCommonFooter();
						fwrite($fp, $footer_data, strlen($footer_data));
						fclose($fp);
					}
					$UrlRedirect = '<script>setTimeout("window.location.href=\''.getRawUrl()."?doaction=dump_data&sub_action=do_submit&curr_volume_num=-1".'\';",1250)</script>';
				}
				if( $NextDumpDesc !== '' ){
					$NextDumpDesc = str_replace('{$NextDumpFile}',$NextDumpDesc,$lang['template.strings4_1']);
				}
				$execResult = str_replace('{$NextDumpDesc}',$NextDumpDesc,str_replace('{$DumpFile}',$currDumpFile,$lang['template.strings4'])).$UrlRedirect;
				$execSuccessed = 1;
			} else{
				$execResult = $lang['Error.strings7'];
			}
		} else{
			$execResult = $lang['Error.strings6'];
		}

	}elseif( $_dumpOpts['dump_method'] === 'pack' ) {

		if($_GET['callback']=='ajaxcallback'){
			$backlimit=intval($_GET['backlimit']);
			if($backlimit==0)$backlimit=3000;
			$tablelist=trim($_GET['tablelist']);
			$dump_base_dir=trim($_GET['dump_base_dir']);
			$tablename=trim($_GET['tablename']);
			if($tablename){
				$totalnums=intval($db->scalar("select count(1) from $tablename",array('type'=>'SILENT')));
				if($totalnums==0){
					$totalnums=1;
					$backnums=1;
				}else{
					$backnums=backuptable($tablename,true,$dump_base_dir,$backlimit);
				}
			}else{
				echo "@@@@@@@@@";
				echo "alert('{$lang['maintance.err.noselecttable']}')";
				exit("@@@");
			}
			$statusbarwidth=($backnums===false||$totalnums==0)?intval($_GET['backnums']):ceil(($backnums/$totalnums)*700);
			if($backnums===false) {
				$backup_status="table error";
				$percent_statu=false;
			}elseif($backnums>=$totalnums){
				$backup_status=$lang['maintance.info67'];
				$percent_statu="100%";
			}else{
				$backup_status="{$backnums}/{$totalnums}";
				$percent_statu=ceil($backnums*100/$totalnums)."%";
			}
			//js start
			echo "@@@@@@@@@";
			echo "tablename='$tablename';
			      backup_status='$backup_status';
                  statusbarwidth='$statusbarwidth';";
			if($percent_statu!==false)echo "percent_statu='$percent_statu'";

			if($backnums>=$totalnums||$backnums===false||$backnums===intval($_GET['backnums'])){
				//backup a table finish

				$arrtablelist=explode(',',$tablelist);
				foreach ($arrtablelist as $k=>$v){
					if($v==''||$v==$tablename)unset($arrtablelist[$k]);
				}
				if($tablename=array_shift($arrtablelist)){
					$tablelist=join(',',$arrtablelist);
				}else{
					//All table backup finish
					echo "
					   alert(\"{$lang['maintance.info66']}\");
					";
					exit('@@@');
				}
			}

			$tablename=urlencode($tablename);
			$tablelist=urlencode($tablelist);
			$url = getRawUrl()."?_dumpOpts[dump_method]=pack&doaction=dump_data&sub_action=do_submit&tablename=$tablename&dump_base_dir={$dump_base_dir}&tablelist={$tablelist}&callback=ajaxcallback&backlimit=$backlimit&backnums=$backnums&d=".time();
			echo "
				     var cmd=new servercmd('$url',backup_table_callback,true);
                     cmd.execute();
				";

			//js end
			echo "@@@";
			exit;
		}else{
			printjs();
			$tablename=urlencode($_dumpOpts['table_name_point']);
			$dump_base_dir=urlencode($_dumpOpts['dump_base_dir']);
			$tablelist=join(',',$_dumpOpts[dump_tables]);
			$tablelist=urlencode($tablelist);
			$packinc=intval($_POST['pack_inc']);
			echo '<br><table class="tableborder" align="center" cellspacing="0" cellpadding="1"><tr><td colspan=3 height="40">正在进行数据库备份。。。<h5>'.$lang['maintance.61'].'</h5></td></tr><tr><td width="80"></td><td height="20" style="text-align:center;" class="tit1"><input type="submit" name="Submit" value="注意事项！" style="color: #FF0000;width:80px;height:50px;border:1px outset;"></td><td height="20" align="left" class="tit1">'.$lang['maintance.backuptip'].'</td></tr><tr><td height="20"></td></tr>';
			foreach ($_dumpOpts['dump_tables'] as $table){
				if(!$packinc){
					if(file_exists($_dumpOpts['dump_base_dir']."/".$table.".rec.php"))@unlink($_dumpOpts['dump_base_dir']."/".$table.".rec.php");
					if(file_exists($_dumpOpts['dump_base_dir']."/".$table.".data.php"))@unlink($_dumpOpts['dump_base_dir']."/".$table.".data.php");
				}
				echo '<tr><td width="20"></td><td width="150" align="left"><B>'.$table.':</B><BR>'.$lang['maintance.info64'].'：<span id="'.$table.'_backupstatus">'.$lang['maintance.info65'].'</span></td><td width="700" algin="left"><div align="left" style="width:700px;height:26px;background-color:#FFFFFF;overflow:hidden;border:solid 1px #488100;"><div style="position:absolute; width:700px;margin-left:auto; margin-left:auto;color:#0A6F00;text-align:center;" id="'.$table.'_percent">0%</div><div id="'.$table.'_statusbar" style="background:#f90 url(images/linebg.gif);width:0px;height:26px;margin:1px 1px;text-align;"></div></div></td></tr>';
			};
			echo '</table>';
			$url = getRawUrl()."?_dumpOpts[dump_method]=pack&doaction=dump_data&sub_action=do_submit&tablename=$tablename&dump_base_dir={$dump_base_dir}&tablelist={$tablelist}&callback=ajaxcallback&backlimit=$backlimit";
			echo '
			<script language="javascript">
			var cmd=new servercmd("'.$url.'",backup_table_callback,true);
			cmd.execute();
			</script>
			';
		}
		return ;
	}
	show_msg($lang['template.strings3'],$execResult,$execSuccessed,'','',$_arr_backurl[1],$lang['cmdback']);
}

function ImportData(){
	global $_FILES,$lang,$db,$import_from,$server_data_file,$dbhost,$dbname,$dbuser,$dbpw,$dbport,$all_recovery,$_arr_backurl,$outputDir;
	if( $all_recovery === 'yes' ){
		show_msg($lang['template.strings3_1'],$lang['template.strings7'],1,'','',$_arr_backurl[2],$lang['cmdback']);
		return true;
	}
	if( defined('DATABASE_DEBUG') && DATABASE_DEBUG === true ){//调试期使用
		$dbname = 'test';
	}
	$execSuccessed = 0;
	if( $import_from === 'local' ){
		if( FileHandler::is_uploaded_file($_FILES['local_data_file']['tmp_name']) ){
			$server_data_file = $_FILES['local_data_file']['tmp_name'];
		} else{
			show_msg($lang['template.strings3_1'],$lang['Error.strings12'],$execSuccessed,'','',$_arr_backurl[2],$lang['cmdback']);
			return false;
		}
	} elseif( $import_from === 'server' ){
		if( !is_file($server_data_file) || !is_readable($server_data_file) ){
			show_msg($lang['template.strings3_1'],$lang['Error.strings11'],$execSuccessed,'','',$_arr_backurl[2],$lang['cmdback']);
			return false;
		}
	}elseif( $import_from === 'pack'){


		if($_GET['callback']=='ajaxcallback'){
			$backlimit=intval($_GET['backlimit']);
			if($backlimit==0)$backlimit=1000;
			$drop_table=intval($_GET['drop_table']);
			$start=intval($_GET['start']);
			$tablelist=trim($_GET['tablelist']);
			$dump_base_dir=trim($_GET['dump_base_dir']);
			$tablename=trim($_GET['tablename']);
			$pack_rec_file=$outputDir."/".$tablename.".rec.php";
			if(is_readable($pack_rec_file)&&($packinfo=get_backup_info($pack_rec_file))){
				$totalnums=intval($packinfo['recnums']);
				if($drop_table==1&&$start==0){
					$restorenums=restore_table($pack_rec_file,'',RESTORE_CREATE_ALWAY,$start,$backlimit,true);
				}else{
					$restorenums=restore_table($pack_rec_file,'',RESTORE_CREATE_IFNOEXITS,$start,$backlimit,true);
				}
				$start+=$restorenums;
			}else{
				//备份文件不存在或者格式错误
				exit;
			}

			$statusbarwidth=$totalnums?ceil(($start/$totalnums)*700):700;
			$percent_statu=$totalnums?ceil(($start/$totalnums)*100)."%":"100%";
			$backup_status=($restorenums===false)?"pack file error":"{$start}/{$totalnums}";

			//js start
			echo "@@@@@@@@@";
			echo "tablename='$tablename';
                        backup_status='$backup_status';
                        statusbarwidth='$statusbarwidth';";
			if($percent_statu!==false)echo "percent_statu='$percent_statu'";
			if($restorenums==$totalnums||$restorenums==false){
				//单表还原完成
				$start=0;

				$arrtablelist=explode(',',$tablelist);

				foreach ($arrtablelist as $k=>$v){
					if($v==''||$v==$tablename)unset($arrtablelist[$k]);
				}

				if($tablename=array_shift($arrtablelist)){
					$tablelist=join(',',$arrtablelist);
				}else{
					echo "\nalert('所有表已经还原完成')";
					exit('@@@');
				}
			}
			$tablename=urlencode($tablename);
			$tablelist=urlencode($tablelist);
			$url = getRawUrl()."?doaction=import_data&sub_action=do_submit&import_from=pack&tablename=$tablename&start=$start&tablelist={$tablelist}&callback=ajaxcallback&backlimit=$backlimit";
			echo "
				     var cmd=new servercmd('$url',backup_table_callback,true);
                     cmd.execute();
				";

			//js end
			echo "@@@";
			exit;
		}else{
			printjs();
			$tablelist=join(',',$_POST['tablename']);
			if(count($_POST['tablename'])==0){
				exit();
			}
			$tablelist=urlencode($tablelist);
			echo '<br><table class="tableborder" align="center" cellspacing="1" cellpadding="1"><tr><td colspan=3 height="20">正在进行数据库还原。。。</td></tr>';
			foreach ($_POST['tablename'] as $table){
				echo '<tr><td width="20"></td><td width="150" align="right"><B>'.$table.':</B><BR>'.$lang['maintance.info64'].'：<span id="'.$table.'_backupstatus">'.$lang['maintance.info65'].'</span></td><td width="700" algin="left">
				<div align="left" style="width:700px;height:26px;background-color:#FFFFFF;overflow:hidden;border:solid 1px #488100;"><div style="position:absolute; width:700px;margin-left:auto; margin-left:auto;color:#0A6F00;text-align:center;" id="'.$table.'_percent">0%</div><div id="'.$table.'_statusbar" style="background:#f90 url(images/linebg.gif);width:0px;height:26px;margin:1px 1px;text-align;"></div></div>
				</td></tr>';

			};
			echo '</table>';
			$tablename=array_shift($_POST['tablename']);
			$drop_table=intval($_POST['drop_table']);
			$url = getRawUrl()."?doaction=import_data&sub_action=do_submit&import_from=pack&tablename=$tablename&start=0&tablelist={$tablelist}&callback=ajaxcallback&drop_table={$drop_table}&backlimit=$backlimit";
			echo '
			<script language="javascript">
			var cmd=new servercmd("'.$url.'",backup_table_callback,true);
			cmd.execute();
			</script>
			';
		}
		return ;


	}else{
		show_msg($lang['template.strings3_1'],$lang['Error.strings8'],$execSuccessed,'','',$_arr_backurl[2],$lang['cmdback']);
		return false;
	}
	$identify = array();
	if( $fp = @fopen($server_data_file,'rb') ){
		@flock($fp,2);
		if( !feof($fp) ){
			$identify = GetDumpFileIdentify(fgets($fp));
		}
		if( !empty($identify) && $identify['data_format'] === 'SymLink' ){
			while( !feof($fp) ){
				$str = fgets($fp);
				if( strpos($str,'/*') !== false ){
					$identify['codes'] = unserialize(base64_decode(fgets($fp)));
					break;
				}
			}
		}
		@fclose($fp);
	}
	if( !empty($identify) ){
		if( $identify['data_format'] === 'SymLink' ){
			if( is_array($identify['codes']) && !empty($identify['codes']) ){
				if( defined('DATABASE_DEBUG') && DATABASE_DEBUG === true ){//调试期使用
					$db->query('USE test;');
				}
				global $outputDir;
				foreach( $identify['codes'] as $tmpTblName => $currArr ){
					$destDataFile = $outputDir.'/'.$currArr['tableNamePoint'].'.MYD';
					$currTmpDataFile = $outputDir.'/'.$tmpTblName.'.MYD';
					if( is_file($destDataFile) ) {
						$db->query("DROP TABLE /*! IF EXISTS*/ {$tmpTblName}");
						if( $query = $db->query(str_replace('TEMPORARY','',$currArr['CreateTmpStmt'])) ){
							if( rename($destDataFile,$currTmpDataFile) ){
								$currDestTable = str_replace('__','',$tmpTblName);
								$db->query("REPAIR TABLE {$tmpTblName} QUICK");
								$db->query($currArr['DropStmt']);
								$db->query($currArr['CreateStmt']);
								$db->query("ALTER TABLE {$currDestTable} DISABLE KEYS");
								$db->query("INSERT /*! DELAYED */ INTO {$currDestTable} SELECT * FROM {$tmpTblName}");
								$db->query("ALTER TABLE {$currDestTable} ENABLE KEYS");
								if( $currArr['RebuildKey'] ){
								}
								rename($currTmpDataFile,$destDataFile);
								touch($currTmpDataFile);
								chmod($currTmpDataFile,0777);
							}
							$db->query("DROP TABLE /*! IF EXISTS*/ {$tmpTblName}");
						}
					}
				}
				show_msg($lang['template.strings3_1'],$lang['template.strings6'],$execSuccessed,'','',$_arr_backurl[2],$lang['cmdback']);
				return true;
			}
		} elseif( $identify['data_format'] === 'MysqlDump' || $identify['data_format'] === 'MultiVolume' ){
			$execSuccessed = 0;
			$execResult = '';
			if(@is_readable(GetMysqlBaseDir().'mysql') AND true === TestShellExec()){
				$shellCmd = GetMysqlBaseDir().'mysql -h '.$dbhost.' '.($dbport?(is_numeric($dbport)?" -P {$dbport} ":" -S {$dbport}"):"").' --user='.$dbuser.' --password='.$dbpw.' '.($GLOBALS['charset']?"--default-character-set={$GLOBALS['charset']}":'').' '.$dbname.' < "'.$server_data_file.'"';
				if( !@shell_exec($shellCmd) ){
					$execSuccessed = 1;
					$execResult = $lang['template.strings7'];
				} else{
					show_msg($lang['template.strings3_1'],$lang['Error.strings14'],0,'','',$_arr_backurl[2],$lang['cmdback']);
					return false;
				}
			} else{
				$arrQuery = array();
				if( $fp = @fopen($server_data_file,'rb') ){
					@flock($fp,2);
					$fileSize = filesize($server_data_file);
					$strSqlDumped = '';
					do{
						$strCurr = fgets($fp,$fileSize);
						if( strlen($strCurr) > 0 ){
							if( $strCurr{0} === '#' || $strCurr{0}.$strCurr{1}.$strCurr{2} === '-- ' ){
								continue;
							}
							$strSqlDumped .= $strCurr;
							if( preg_match('/;[\r\n]*$/im',$strSqlDumped) === 1 ){
								$arrQuery[] = $strSqlDumped;
								$strSqlDumped = '';
							}
						}
					} while( !feof($fp) || ( @fclose($fp) && ($fp = false) ) );
					if( $fp && feof($fp) ){
						fclose($fp);
					}
					if( !empty($arrQuery) ){
						if( defined('DATABASE_DEBUG') && DATABASE_DEBUG === true ){//调试期使用
							$db->query('USE test;');
						}
						foreach( $arrQuery as $currQuery ){
							$db->query($currQuery);
						}
						$execSuccessed = 1;
						$execResult = str_replace('{$File}',$server_data_file,$lang['template.strings8']);
						$next_file = '';
						if( $identify['data_format'] === 'MultiVolume' ){
							if( $identify['next_volume_num'] > 0 ){
								$next_file = preg_replace("/-(?:{$identify['curr_volume_num']})(\..+)$/","-{$identify['next_volume_num']}\\1",$server_data_file);
								if( $next_file !== $server_data_file && is_file($next_file) ){
									$execResult .=  str_replace('{$NextFile}',$next_file,$lang['template.strings9'])."<script>setTimeout('window.location.href=\"".getRawUrl()."?doaction=import_data&sub_action=do_submit&import_from={$import_from}&server_data_file={$next_file}\"',1250)</script>";
								} else{
									$next_file = '';
								}
							}
						}
						if( $next_file === '' ){
							$execResult .= "<script>setTimeout('window.location.href=\"".getRawUrl()."?doaction=import_data&sub_action=do_submit&all_recovery=yes\"',1250)</script>";
						}
					} else{
						$execResult = $lang['Error.strings15'];
					}
				}
			}
		} else{
			$execResult = $lang['Error.strings13'];
		}
		show_msg($lang['template.strings3_1'],$execResult,$execSuccessed,'','',$_arr_backurl[2],$lang['cmdback']);
	} else {
		show_msg($lang['template.strings3_1'], $lang['Error.strings13'], 0, '', '', $_arr_backurl[2], $lang['cmdback']);
	}
	(1 === $execSuccessed) AND rebuild_all_cache();
	return ($execSuccessed===0?false:true);
}

function rebuild_all_cache()
{
	static $is_included = false;
	if (false === $is_included) {
		$is_included = true;
		require_once ROOT_PATH.'inc/BoardCache.class.php';
	}
	$obj_cache =& new BoardCache($db);
	$obj_cache->createForumSetting();
	$obj_cache->createAll();
	$obj_cache->createforumlink();
	$obj_cache->createmailconfig();
	$obj_cache->createstylecss();
	$obj_cache->createusergroup();
	$obj_cache->createboardgroup();
	$obj_cache->createuserpermission();
	$obj_cache->createforumface();
	$obj_cache->createforumpic();
	$obj_cache->createspaceConfig();
}//end function rebuild_all_cache

function GetTableDescription($tblComment,$tblName=''){
	global $lang, $dv, $db;
	static $tablelist;
	if (!isset($tablelist)) {
		if ($query = $db->query("SELECT tablename FROM {$dv}tablelist")) {
			while ($dbinfo =& $db->fetch_array($query)) {
				$nonepre = str_replace($dv,'',$dbinfo['tablename']);
				if (!isset($lang['TableComment'][$nonepre])) {
					$lang['TableComment'][$nonepre] = $lang['TableComment_bbs'];
				}
			}//end while
		}
	}
	if( $tblComment.'' !== '' ){
		$strReturn = $tblComment;
	} elseif( $tblName.'' !== '' ){
		$strReturn = $lang['TableComment'][str_replace($dv,'',$tblName)];
	}
	return (!$strReturn?false:$strReturn);
}

function TestSymLink(){
	global $db;
	$haveSymlink = '';
	if( strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN' ){
		if( $db->version() >= '4.0' ){
			if( $query = $db->query("SHOW VARIABLES LIKE 'have_symlink'") ){
				list(,$haveSymlink) = $db->fetch_row($query);
			}
		}
	}
	if( $haveSymlink !== '' && strtolower(trim($haveSymlink)) === 'yes' ){
		return true;
	} else{
		return false;
	}
}
function TestShellExec($cmd=''){
	if( ((int)ini_get('safe_mode')) === 0 && function_exists('shell_exec') ){
		if( $cmd == '' ){
			$cmd = 'echo ok';
		}
		if( trim(@shell_exec($cmd)) === 'ok' ){
			return true;
		}
	}
	return false;
}

function GetMysqlBaseDir(){
	global $db;
	$query = $db->query("SHOW VARIABLES LIKE 'basedir'");
	list(, $mysqlBaseDir) = $db->fetch_array($query, MYSQL_NUM);
	return ( $mysqlBaseDir === '/' ? '' : "{$mysqlBaseDir}bin/" );
}

function GetDumpHeader($opts=array()){
	if( $opts['data_format'] === 'MultiVolume' ){
		if( !is_numeric($opts['curr_volume_num']) || $opts['curr_volume_num'] < 0 ){
			$opts['curr_volume_num'] = 0;
		}
		if( !is_numeric($opts['next_volume_num']) || $opts['next_volume_num'] < 0 ){
			$opts['next_volume_num'] = 0;
		}
	}
	$opts['version'] = '2.0.0';
	$identify = ",{$currVersionNum},{$opts['data_format']},{$opts['curr_volume_num']},{$opts['next_volume_num']},";
	$identify = base64_encode(serialize($opts));
	$str = <<<EOT
# Identify: {$identify}
# Dvbbs! {$opts['data_format']} Data Dump For Mysql
# Version: Dvbbs! {$opts['version']}

EOT;
	$str .= "-- <?php exit('Access denied!'); ?> <% Response.Write(\"Access denied!\") %> <% Response.End() %> \r\n";
	global $db, $dv;
	if ($query = $db->query("SHOW TABLE STATUS")) {
		while ($dbinfo1 =& $db->fetch_array($query)) {
			$tableengine = ($dbinfo1['Engine'] ? $dbinfo1['Engine'] : $dbinfo1['Type']);
			$tablename = $dbinfo1['Name'];
			if (1 == preg_match('/MRG_MyISAM|MERGE/i', $tableengine)) {
				if (($query2 = $db->query("SHOW CREATE TABLE {$tablename}")) AND ($dbinfo2 =& $db->fetch_row($query2))) {
					$str .= "\r\nDROP TABLE IF EXISTS {$tablename};\r\n";
				}
			}
		}//end while
	}

	return $str;
}

function GetDumpCommonFooter()
{
	$returnval = '';
	global $db, $dv;
	if ($query = $db->query("SHOW TABLE STATUS")) {
		while ($dbinfo1 =& $db->fetch_array($query)) {
			$tableengine = ($dbinfo1['Engine'] ? $dbinfo1['Engine'] : $dbinfo1['Type']);
			$tablename = $dbinfo1['Name'];
			if (1 == preg_match('/MRG_MyISAM|MERGE/i', $tableengine)) {
				if (($query2 = $db->query("SHOW CREATE TABLE {$tablename}")) AND ($dbinfo2 =& $db->fetch_row($query2))) {
					$returnval .= "\r\n".str_replace('`', '', preg_replace('/( +DEFAULT +CHARSET=[^ ]+)/i','/*!40101 $1*/', $dbinfo2[1])).";\r\n";
				}
			}
		}//end while
	}
	return $returnval;
}//end function GetDumpFooter

function GetDumpFileIdentify($strIdentify){
	if( !$strIdentify ){
		return false;
	}
	if( $strIdentify{0} !== '#' ){
		$lower_identify = strtolower($strIdentify);
		if (strpos($lower_identify,'mysql') !== false && strpos($lower_identify,'dump') !== false) {
			return array('data_format'=>'MysqlDump');
		} else{
			return false;
		}
	}
	$arr = explode(':',$strIdentify);
	if( is_array($arr) ){
		return unserialize(base64_decode(trim($arr[1])));
	}
	return false;
}

function GetDefaultCharacterSet(){
	global $db;
	$defaultCharacterSet = 'gbk';
	if( $query = $db->query("SHOW VARIABLES LIKE 'character_set%'") ){
		while( $result = $db->fetch_array($query) ){
			if( isset($result['character_set']) ){
				$defaultCharacterSet = $result['character_set'];
				break;
			} elseif( isset($result['character_set_connection']) ){
				$defaultCharacterSet = $result['character_set_connection'];
				break;
			}
		}
		$db->free_result($query);
	}
	return $defaultCharacterSet;
}

function &GetDumpedFiles($base_dir='./data_backup',$depth=0){
	if( !is_dir($base_dir) ){
		return false;
	}
	static $arrDumpedFiles = array();
	if( empty($arrDumpedFiles) ){
		clearstatcache();
	}
	if( $obj = dir($base_dir) ){
		while( ( $entry = $obj->read() ) !== false ){
			if( $entry === '.' || $entry === '..' ){
				continue;
			}
			if( strpos(strtolower($entry),'.sql') === false ){
				continue;
			}
			$currFullEntry = $obj->path.'/'.$entry;
			if( is_dir($currFullEntry) ){
				GetDumpedFiles($currFullEntry,1);
			} else{
				$currFile = $obj->path.'/'.$entry;
				if( $fp = @fopen($currFile,'rb') ){
					$currIdentify = GetDumpFileIdentify(fgets($fp));
					@fclose($fp);
				}
				$arrDumpedFiles[] = array(
				'identify' => $currIdentify
				,'path' => $obj->path
				,'entry' => $entry
				,'file_size' => number_format((float)filesize($currFile) / 1000,2).' KB'
				,'inode' => fileinode ($currFile)
				,'create_time' => gmdate('Y-m-d H:i:s',filectime($currFile))
				);
			}
		}
		$obj->close();
		if( $depth === 0 ){
			return ( empty($arrDumpedFiles) ? false : $arrDumpedFiles );
		}
	}
	return false;
}

function GetRebuildKeyBy($tableName){
	global $db;
	$strRebuildKey = '';
	$arr = array();
	if( $query = $db->query("SHOW INDEX FROM {$tableName}") ){
		while( $result = $db->fetch_array($query) ){
			$arr[$result['Key_name']]['Non_unique'] = $result['Non_unique'];
			$arr[$result['Key_name']]['Index_type'] = $result['Index_type'];
			$arr[$result['Key_name']]['Column_name'][] = $result['Column_name'];
		}
	}
	if( !empty($arr) ){
		$strRebuildKey = '';
		$comma = '';
		foreach( $arr as $Key_name => $val ){
			$fldList = implode(',',$val['Column_name']);
			if( $Key_name == 'PRIMARY' ){
				$strRebuildKey .= $comma." ADD PRIMARY KEY ({$fldList})";
			} elseif( $val['Non_unique'] == '0' ) {
				$strRebuildKey .= $comma." ADD UNIQUE {$Key_name}({$fldList})";
			} elseif( $val['Index_type'] == 'FULLTEXT' ){
				$strRebuildKey .= $comma." ADD FULLTEXT {$Key_name}({$fldList})";
			} else{
				$strRebuildKey .= $comma." ADD INDEX {$Key_name}({$fldList})";
			}
			$comma = ',';
		}
		if( $strRebuildKey !== '' ){
			return "ALTER TABLE {$tableName} ".$strRebuildKey;
		}
	}
	return false;
}


//add by hj@dv 20071225
//pack 备份函数
/*
函数:
backuptable
作用:
pack方式备份表
说明:
本函数将记录用pack函数压缩后备份
备份后产生两个文件:
1、$tablename.rec.php 保存定长型字段数据和变长型字段在.data.php的起始位置、数据长度
变长型数据使用两个长整型数 (8bytes)保存于rec.php中,field_pos 保存数据在.data.php文件中的开始位置,field_len 保存数据长度
2、$tablename.data.php   data.php保存变长型数据
以.php后缀是为了安全考虑,防止数据库被外部下载

参数：
@$tablename  要备份的表名
@$increment 是否增量备份,默认是
增量备份从上一次备份点开始备份,备份点依据ID升序获取
@$savedir   保存目录,如为空,将保存到当前目录

返回值：
成功将返回备份的记录数,失败返回false
*/
function backuptable($tablename,$increment=true,$savedir='',$limit=0){
	global $db;
	if(substr($savedir,-1,1)!='/')$savedir.='/';
	$back_rec_file=$savedir.$tablename.".rec.php";
	$back_data_file=$savedir.$tablename.".data.php";
	$pack_format=get_pack_format($tablename);
	$pack_format_fields=get_pack_field_format($tablename);
	$reclen=get_pack_format_len($pack_format);
	$autofield=get_table_autoincremet($tablename);

	if(!$increment||!file_exists($back_rec_file)||!file_exists($back_data_file)){
		$creattable=get_create_table($tablename);
		$sql="select *from $tablename";
		if($autofield)$sql.=" order by $autofield asc";
		if(!$fprec=fopen($back_rec_file,'wb'))return false;
		if(!$fpdata=fopen($back_data_file,'wb'))return false;

		rewind($fprec);
		rewind($fpdata);

		fwrite($fprec,pack('L',strlen(DATA_BACKUP_ADDHEAD)));//附加文件头长度
		fwrite($fprec,DATA_BACKUP_ADDHEAD,strlen(DATA_BACKUP_ADDHEAD));//附加文件头


		fwrite($fprec,pack('L',$reclen));//每记录占用的字节数

		$unpack_format=get_unpack_format($tablename);//unpack函数中要用到的format
		fwrite($fprec,pack('L',strlen($unpack_format)));//unpack format 长度
		fwrite($fprec,$unpack_format);

		fwrite($fprec,pack('C',strlen($tablename)));//备份的表名长度
		fwrite($fprec,$tablename,strlen($tablename));//备份的表名

		fwrite($fprec,pack('L',strlen($creattable)));//创建表所用到的SQL长度
		fwrite($fprec,$creattable,strlen($creattable));//创建表所用到的SQL

		fwrite($fpdata,pack('L',strlen(DATA_BACKUP_ADDHEAD)));//附加文件头长度
		fwrite($fpdata,DATA_BACKUP_ADDHEAD);//附加文件头

	}else{
		$backup_info=get_backup_info($back_rec_file);
		$backnums=$backup_info?intval($backup_info['recnums']):0;
		$last_backup_rec=$backup_info['last_backup_rec'];
		$sql="select *from $tablename";
		if($autofield!=''){
			$id=$last_backup_rec?intval($last_backup_rec[$autofield]):0;
			$sql.=" where $autofield>$id order by $autofield asc";
		}
		if(!$fprec=fopen($back_rec_file,'ab+'))return false;
		if(!$fpdata=fopen($back_data_file,'ab+'))return false;
		fseek($fpdata,filesize($back_data_file),SEEK_SET);
	}
	if(intval($limit)){
		$sql.=" limit $limit";
	}
	$query=@$db->query($sql,array('type'=>'SILENT'));
	if($db->errno()!=0)return false;
	($limit<-1)&&($limit=-1);
	while(($limit==-1||$limit--)&&($rs=$db->fetch_array($query))){
		$datastartpos=0;
		$datalen=0;
		$recdata='';
		$i=0;

		foreach ($rs as $k=>$v){
			if($pack_format_fields[$k]=='LL'){
				$datastartpos=ftell($fpdata);
				$recdata.=pack('L',$datastartpos);
				$i++;
				$datalen=fwrite($fpdata,$v,strlen($v));
				$recdata.=pack('L',$datalen);
				$i++;
			}else{
				$recdata.=pack($pack_format_fields[$k],intval($v));
				$i++;
			}
		}
		$wsize=fwrite($fprec,$recdata);
		$backnums++;
	}
	$db->free_result($query);
	return $backnums;
}


function get_table_fields($tablename){
	global $db;
	static $CACHE_TABLES_FIELDS;
	if(isset($CACHE_TABLES_FIELDS[$tablename]))return $CACHE_TABLES_FIELDS[$tablename];
	$sql="SHOW COLUMNS FROM $tablename";
	if($query=$db->query($sql,array('type'=>'SILENT'))){
		while($rs=$db->fetch_array($query))$ret[]=$rs;
		$CACHE_TABLES_FIELDS[$tablename]=$ret;
		$db->free_result($query);
		return $ret;
	}else{
		return false;
	}
}

//获取表中自动增量字段
function get_table_autoincremet($tablename){
	$fields=get_table_fields($tablename);
	foreach ($fields as $k=>$field){
		if(strtolower($field['Key'])=='pri'){
			return $field['Field'];
		}
	}
	return false;
}

function get_create_table($tablename){
	global $db;
	$sql="show create table $tablename";
	$query=$db->query($sql);
	if($rs=$db->fetch_array($query)){
		$db->free_result($query);
		return $rs['Create Table'];
	}else{
		return false;
	}
}

//获取字段的pack格式，便于pack函数压缩记录
//@$fields 表字段信息数组或者表名

function get_pack_format($tablename){
	if(!$fields=get_pack_field_format($tablename))return false;
	$packformat='';
	foreach ($fields as $field){
		$packformat.=$field;
	}
	return $packformat;
}

function get_unpack_format($tablename){
	if(!$fields=get_pack_field_format($tablename))return false;
	$unackformat='';
	foreach ($fields as $k=>$field){
		if($field=='LL'){
			$unackformat.="L{$k}_pos/L{$k}_len/";
		}else{
			$unackformat.="$field{$k}/";
		}
	}
	$unackformat=substr($unackformat,0,-1);
	return $unackformat;
}

//获取每个字段对应的pack format
function get_pack_field_format($fields){
	if(is_string($fields)&&!($fields=get_table_fields($fields)))return false;
	$ret=false;
	foreach ($fields as $field){
		$arrfielddefined=explode(' ',$field['Type']);
		$arrfieldtype=explode('(',$arrfielddefined[0]);
		$fieldtype=strtolower($arrfieldtype[0]);
		$unsigned=(isset($arrfielddefined[1])&&strtolower($arrfielddefined[1]=='unsigned'));
		switch ($fieldtype){
			case 'year':
			case 'bit':
				$ret[$field['Field']]='C';
				break;
			case 'tinyint':
				$ret[$field['Field']]=$unsigned?'C':'c';
				break;
			case 'smallint':
				$ret[$field['Field']]=$unsigned?'S':'s';
				break;
			case 'mediumint':
			case 'int':
				$ret[$field['Field']]=$unsigned?'L':'l';
				break;
			case 'decimal':
			case 'float':
				$ret[$field['Field']]='f';
				break;
			case 'datetime':
			case 'bigint':
				//不支持大整数
			case 'double':
				$ret[$field['Field']]='d';
				break;
			case 'date':
			case 'timestamp':
			case 'time':
				$ret[$field['Field']]='L';
				break;
			default:
				$ret[$field['Field']]='LL';
				break;
		}
	}
	return $ret;
}


function get_pack_format_len($pack_format){
	if(!$pack_format)return false;
	$pack_format=strtolower($pack_format);
	$len=0;
	for ($i=0;$i<strlen($pack_format);$i++){
		if($pack_format{$i}=='c'){
			$len++;
		}elseif($pack_format{$i}=='s'){
			$len+=2;
		}elseif($pack_format{$i}=='l'){
			$len+=4;
		}elseif($pack_format{$i}=='f'||$pack_format{$i}=='d'){
			$len+=4;//PHP pack Can't support float  
		}
	}
	return $len;
}

/*函数：restore_table
说明：还原pack方式备份的表
参数：
@$backup_rec_file 备份表记录文件
@$backup_data_file 备份表数据文件,如为空，则根据$backup_rec_file获取同名文件
@$createtableoptions  创建表选项 define('RESTORE_CREATE_IFNOEXITS',0x1);当表不存在时创建
define('RESTORE_CREATE_ALWAY',0x2);如果表存在，则删除原表后重新创建
@$start 开始记录

@$limit 限制还原记录数  -1=无限制
成功返回还原的记录数,失败返回false
*/
function restore_table($backup_rec_file,$backup_data_file='',$createtableoptions=1,$start=0,$limit=-1,$increment=true){
	global $db;

	if(!file_exists($backup_rec_file))return false;
	if(!$backup_data_file)$backup_data_file=str_replace('.rec.','.data.',$backup_rec_file);
	if(!file_exists($backup_data_file))return false;
	if(($fp=fopen($backup_rec_file,'rb'))&&($fpdata=fopen($backup_data_file,'rb'))){

		$data=unpack('Laddheadlen',fread($fp,4));
		fseek($fp,intval($data['addheadlen']),SEEK_CUR);
		$data=unpack('Lreclen/Lunpackheadlen',fread($fp,8));
		$reclen=intval($data['reclen']);
		$unpackheadlen=$data['unpackheadlen'];
		$unpack_format=fread($fp,$unpackheadlen);
		$data=unpack('Ctablenamelen',fread($fp,1));
		$tablenamelen=intval($data['tablenamelen']);
		$tablename=fread($fp,$tablenamelen);
		$data=unpack('Lcreatetablelen',fread($fp,4));
		$createtablelen=intval($data['createtablelen']);
		$createtable=fread($fp,$createtablelen);
		
		if($createtableoptions&RESTORE_CREATE_ALWAY){
			$db->query("DROP TABLE IF EXISTS `{$tablename}`",array('type'=>'SILENT'));
			$db->query($createtable,array('type='>'SILENT'));
			if($db->errno()!=0){
				return false;
			}
		}else{
			$db->query("select count(*) from $tablename",array('type'=>'SILENT'));
			if($db->errno()!=0){
				$db->query($createtable,array('type'=>'SILENT'));
			}
		}

		if($start==0&&$increment){
			$start=intval($db->scalar("select count(1) from $tablename"));
			$restorenums=$start;
		}else{
			$restorenums=0;
		}
		if($start>0)fseek($fp,$reclen*$start,SEEK_CUR);
	}else{
		return false;
	}



	$fields=get_pack_field_format($tablename);
	$sqlfield='';
	foreach ($fields as $k=>$v){
		$sqlfield.="`$k`,";
	}
	if($sqlfield=='')return false;
	$sqlfield="(".substr($sqlfield,0,-1).")";
	($limit<-1)&&($limit=0);


	while(($strrec=fread($fp,$reclen))&&($limit==-1||$limit--)){
		$sqlvalue='';
		if(strlen($strrec)!=$reclen){
			$a=2;
		}
		if(!$rec=unpack($unpack_format,$strrec))continue;
		$debug=false;
		if($rec['topicid']==1024){
			$debug=true;
		}
		foreach ($fields as $k=>$v){
			if($v=='LL'){
				fseek($fpdata,$rec["{$k}_pos"],SEEK_SET);
				$fielddata=addslashes(fread($fpdata,intval($rec["{$k}_len"])));
				$sqlvalue.="'$fielddata',";
			}else{
				if(!isset($rec[$k])||$rec[$k]==''){
					$sqlvalue.="'',";
				}else{
					$sqlvalue.="{$rec[$k]},";
				}
			}
		}
		$sqlvalue="(".substr($sqlvalue,0,-1).")";
		$db->query("insert into `$tablename` $sqlfield values $sqlvalue",array('type'=>'SILENT'));
		$restorenums++;
	}
	fclose($fp);
	return $restorenums;
}

function get_backup_info($backup_rec_file){
	if(!file_exists($backup_rec_file))return false;
	$ret=false;
	if($fp=fopen($backup_rec_file,'rb')){
		$data=unpack('Laddheadlen',fread($fp,4));
		$addheadlen=intval($data['addheadlen']);
		$ret['addhead']=fread($fp,$addheadlen);
		$data=unpack('Lreclen/Lunpackheadlen',fread($fp,8));
		$ret['reclen']=intval($data['reclen']);
		$unpackheadlen=intval($data['unpackheadlen']);
		$ret['unpack_format']=fread($fp,$unpackheadlen);
		$data=unpack('Ctablenamelen',fread($fp,1));
		$ret['tablename']=fread($fp,intval($data['tablenamelen']));
		$data=unpack('Lcreatetablelen',fread($fp,4));
		$createtablelen=intval($data['createtablelen']);
		$ret['createtable']=fread($fp,$createtablelen);
		$ret['rec_offset']=ftell($fp);
		$ret['recnums']=ceil((filesize($backup_rec_file)-$ret['rec_offset'])/$ret['reclen']);
		if($ret['recnums']>0){
			$strlastrec=fread($fp,$ret['reclen']);
			$ret['first_backup_rec']=@unpack($ret['unpack_format'],$strlastrec);
			fseek($fp,0-$ret['reclen'],SEEK_END);
			$strlastrec=fread($fp,$ret['reclen']);
			$ret['last_backup_rec']=@unpack($ret['unpack_format'],$strlastrec);
		}else{
			$ret['first_backup_rec']=false;
			$ret['last_backup_rec']=false;
		}
		fclose($fp);
	}
	return $ret;
}

function printjs(){
	print <<<EOT
<script language="javascript">
function backup_table_callback(sussess,retmsg){
   if(sussess){
	   if(false!==(arrRet=parseServerResult(retmsg))){
	       if(arrRet["js"]!==""){
	         eval(arrRet["js"]);
	         document.getElementById(tablename+"_backupstatus").innerHTML=backup_status;
	         document.getElementById(tablename+"_statusbar").style.width=parseInt(statusbarwidth);
	         document.getElementById(tablename+"_percent").innerHTML=percent_statu;
	       }
	   }
   }
}

</script>
EOT;

}
//end by hj 20071225
?>
