<?php
define('THIS_SCRIPT', 'upgrade');
include_once 'global.php';
include_once 'inc/ftpFileHandle.class.php';
include_once INC_PATH.'zip.class.php';
include_once INC_PATH.'FileHandler.class.php';
include_once 'inc/httpdown.class.php';
include_once INC_PATH.'general_funcs.php';
define('UPGRADECONFIGPATH', CACHE_PATH.'upgrade.config.php');
define('UPGRADEUPDATEFILES', CACHE_PATH.'updatefiles.config.php');
set_magic_quotes_runtime(0);
if (defined('MAIN_DOMAIN_NAME')) {
	exit('@@@1@@@Access denied!@@@@@@');
}
$lang = load_lang($lang,'upgrade');
head();
checklogin();
if ( strpos($sysinfo['flag'],'49,') === false ){
	show_msg($lang['readme_tit'],$lang['upgrade.err1'],0,'','','','');
	exit;
}
if(is_readable(UPGRADECONFIGPATH)){
	include(UPGRADECONFIGPATH);
	if(!$foruminfo&&!($foruminfo=createupgradeconfig())){
		show_msg($lang['readme_tit'],$lang['upgrade.err2'],0,'','','','');
		exit;
	}
}elseif(!($foruminfo=createupgradeconfig())){
	show_msg($lang['readme_tit'],$lang['upgrade.err2'],0,'','','','');
	exit;
}

if(is_readable(UPGRADEUPDATEFILES))include(UPGRADEUPDATEFILES);

$fupgradeserver=str_replace("\\","/",$foruminfo["upgradeserver"]);
@substr($fupgradeserver,-1,1)!="/" AND $fupgradeserver.="/";
define('UPGRADE_DOWN', "{$fupgradeserver}down.php?");
define("UPGRADE_FILELIST","{$fupgradeserver}getupdatelist.php?");
$url=str_replace("\\","/",getThisPageUrl());
$pos=strrpos($url,"/");
$baseurl=$url;
if(false!==$pos&&$pos!=strlen($str)-1){
	$baseurl=substr($url,0,$pos)."/";
}

PageLoad();
function Pageload(){
	global $lang,$reaction,$db,$foruminfo,$ftpserver,$ftpport,$ftpuser,$ftppass,$ftproot,$updatefiles;
	global $autoupgrade,$interval,$upgradeserver,$auth,$autorun,$dfid,$fileid,$doaction;
	global $dv,$_DCACHE,$page_size,$page,$total,$page_count,$offset,$p;
	switch ($reaction){
		case "upgrade":
			$lm=$foruminfo["lastupdate"];
			if(empty($lm))$lm=$db->scalar("SELECT MAX(lastupdate) as lastupdate FROM `{$dv}sysfiles`");
			if(empty($lm))$lm=0;
			$updatefiles=getupdatelist(UPGRADE_FILELIST."s={$foruminfo["script"]}&v={$foruminfo["version"]}&d={$foruminfo["database"]}&c={$foruminfo["charset"]}&e={$foruminfo["encode"]}&l={$lm}");
			if($updatefiles){
				if(!$fp=fopen(UPGRADEUPDATEFILES,"wb")){
					show_msg("{$lang["upgrade.save"]}","{$lang["upgrade.save"]}".str_replace('{filename}',UPGRADEUPDATEFILES,$lang["upgrade.fail_createcache"]),0,'','',"?reaction=upgrade","{$lang["upgrade.back"]}");
					exit;
				}else{
					@chmod(UPGRADEUPDATEFILES,0777);
					$content="<?php\n".varstoscript('updatefiles',$updatefiles).";\n?>";
					fputs($fp,$content);
					@fclose($fp);
				}

			}
			break;
		case "forum":
			break;
		case "setting":
			if($_GET["doaction"]=="save"){
				$query=@$db->query("update {$dv}sysupgrade set autoupgrade={$autoupgrade},query_interval=".intval($interval*3600).",upgradeserver='{$upgradeserver}',auth={$auth},autorun={$autorun},ftpserver='{$ftpserver}',ftpport={$ftpport},ftpuser='{$ftpuser}',ftppass='{$ftppass}',ftproot='{$ftproot}'");
				if(@$db->errno()==0&&createupgradeconfig()){
					head();
					show_msg("{$lang["upgrade.save"]}","{$lang["upgrade.save"]}{$lang["upgrade.ok"]}",1,'','',"?reaction=setting","{$lang["upgrade.back"]}");
					exit;
				}else{
					head();
					show_msg("{$lang["upgrade.save"]}","{$lang["upgrade.save"]}{$lang["upgrade.fail"]}",0,'','',"?reaction=setting","{$lang["upgrade.back"]}");
					exit;
				}
			}
			break;
		case "ftptest":
			head();
			ftptest($ftpserver,$ftpport,$ftpuser,$ftppass,$ftproot,true,10);
			exit;
			break;
		case "log":
			if(isset($fileid)&&is_array($fileid)){
				foreach ($fileid as $k=>$v){
					$fileid[$k]=intval($v);
				}
				$fids=join(",",$fileid);
			}
			if($doaction=="restore"&&$fids!=""){
				restore($fids);
			}elseif($doaction=="update"&&$fids!=""){
				exec_upgrade($fids,1);
			}elseif($doaction=="delete"&&$fids!=""){
				$query=$db->query("select filepath from {$dv}sysfiles where id in ($fids)");
				while ($rs=$db->fetch_array($query)){
					$rs['filepath']=str_replace("\\","/",$rs['filepath']);
					$arrfilepath=explode("/",$rs['filepath']);
					foreach ($arrfilepath as $k=>$v){
						if($v=='')unset($arrfilepath[$k]);
					}
					$rs['filepath']=join("/",$arrfilepath);
					$rs['filepath']=str_replace("/","__",$rs['filepath']);
					@unlink(ROOT_PATH."admin/sysupgrade/".$rs['filepath']);
					@unlink(ROOT_PATH."admin/sysupgrade/".$rs['filepath'].".bak");
				}
				$db->free_result($query);
				$db->query("delete from {$dv}sysfiles where id in ($fids)");
			}
			$total=$db->scalar("select count(1) from {$dv}sysfiles");
			page_info(20);
			$query=$db->query("SELECT id,filepath,filesize,securitylevel,securityalert,isdone,lastupdate,lastmodified from {$dv}sysfiles order by lastupdate DESC",array('absolutePage'=>$offset, 'pageSize'=>$page_size));
			break;

		case "down":
			$fid=intval($_GET["i"]);
			if(!empty($fid)){
				if(false!==($dresult=downfile2db($fid))){
					echo "@@@0@@@{$lang["upgrade.info5"]}{$dresult}......<font color=green>{$lang["upgrade.info6"]}</font>@@@@@@";
				}else{
					echo "@@@8@@@<font color=red>{$lang["upgrade.info7"]}<BR>{$dresult}</font>@@@@@@";
				}
			}
			exit;
			break;
		default:
	}
	header("content-Type: text/html; charset=".$charset);
	head();
	include printout('upgrade');
	footer();
}

function getupdatelist($s){
	$files=array();
	$flist=geturlcontent($s);
	if(is_array($flist)){
		foreach ($flist as $k=>$f) {
			$files[]=explode("@@@",$f);
		}
	}
	return $files;
}
function geturlcontent($url){
	$strhtml="";
	if(function_exists("fsockgeturlfile")&&function_exists("fsockopen")){
		if(false==$strhtml=@getfileurl($url))return false;
		if(substr($strhtml,-2)=="\r\n")$strhtml=substr($strhtml,0,-2);
		$lines=@explode("\r\n",$strhtml);
	}elseif(function_exists("file")){
		$lines=@file($url);
	}
	return $lines;
}

function getfile($f){
	if (function_exists("file_get_contents")){
		$strfile=file_get_contents($f);
	}elseif(function_exists("fopen")&&$fp=fopen($f,"rb")){
		while($buf=fread($fp,4096))$strfile.=$buf;
	}
	return $strfile;
}
function downfile2db($id=0){
	global $db,$dv,$forum_setting,$forum_adminfolder,$foruminfo,$updatefiles;
	if($file=search_subarrary($updatefiles,0,$id)){
		$ext=strtolower(($file[3]));
		$url=$ext=='zip'?$file[4]:UPGRADE_DOWN."i={$id}";
		$name=addslashes(str_replace("\\","/",$file[1]));
		$path=str_replace("\\","/",$file[2]);
		$fldupfiles=str_replace("\\","/",$forum_setting[76]);
		$fldadmin=str_replace("\\","/",$forum_adminfolder);
		if(substr($fldupfiles,strlen($fldupfiles)-1,1)!="/")$fldupfiles.="/";
		if(substr($fldadmin,strlen($fldadmin)-1,1)!="/")$fldadmin.="/";
		$path=preg_replace('/admin\//i',$fldadmin,$path);
		$path=preg_replace('/uploadfile\//i',$fldupfiles,$path);
		$size=intval($file[6]);
		$securitylevel=intval($file[8]);
		$securityalert=addslashes($file[9]);
		$lastupdate=intval($file[7]);
		$filebinary=getfileurl($url);
		if(strlen($filebinary)!=$size)return false;
		$lastmodified=intval($db->scalar("select lastmodified from {$dv}sysfiles where filepath='{$path}'"));
		empty($lastmodified) AND $lastmodified=0;
		$savefile=trimmultichar($path,'/');
		$savefile="./sysupgrade/".str_replace('/','__',$savefile);
		if($fp=fopen($savefile,'wb')){
			if($wsize=fwrite($fp,$filebinary)!==$size){
				return false;
			}
			fclose($fp);
		}else{
			return false;
		}
		$path=addslashes($path);
		$sql="replace into {$dv}sysfiles set `script`='{$foruminfo['script']}',`version`={$foruminfo['version']},`database`='{$foruminfo['database']}',`charset`='{$foruminfo['charset']}',`encode`='{$foruminfo['encode']}',filename='{$name}',fileext='{$ext}',filepath='{$path}',filesize={$size},filebinary='{$strfile}',securitylevel={$securitylevel},securityalert='{$securityalert}',lastupdate={$lastupdate},lastmodified={$lastmodified},isdone=0";
		$db->query($sql);
		if($db->affected_rows()>0){
			//执行成功
			$sql="update {$dv}sysupgrade set `lastupdate`=$lastupdate";
			$db->query($sql);
			$foruminfo=createupgradeconfig();
			return $name.exec_upgrade();
		}
		$db->free_result($query);
	}
	return false;
}

function exec_upgrade($idlist="",$isdone=0){
	global $db,$lang,$dv,$foruminfo;
	createftp();
	empty($isdone) AND ($isdone=0);
	if($isdone==0){
		$sql="SELECT id,filename,filepath,filebinary,lastupdate,lastmodified FROM {$dv}sysfiles where isdone=0";
	}else{
		if(empty($idlist))return false;
		$sql="SELECT * FROM {$dv}sysfiles where isdone!=1 and id in ({$idlist})";
	}
	$sql.=" order by lastupdate ASC";
	$query=$db->query($sql);
	$i_ok=0;
	$i_fail=0;
	$resultmsg="";
	$syslastmodified=time()-1;

	while($file=$db->fetch_array($query)){
		$filepath=$file["filepath"];
		$fileextname=strtolower((false===($dpos=strrpos($filepath,'.')))?'':substr($filepath,$dpos+1));
		$rfilepath=trimmultichar($filepath,'/');
		$rfilepath="./sysupgrade/".str_replace('/','__',$rfilepath);
		if(!file_exists($rfilepath)){
			$resultmsg.=$lang['upgrade.filenoexists'];
			continue;
		}
		if($fileextname=='zip'){
			$zip=new zip();
			$filelist=$zip->get_list($rfilepath);
			$backup=true;
			if($fp=fopen($rfilepath.".bak",'wb')){
				foreach ($filelist as $k=>$ufile){
					if(!$ufile['folder']){
						$dfilepath=$ufile['filename'];
						$ufilepath=trimmultichar(ROOT_PATH.$dfilepath,'/');
						if(file_exists($ufilepath)&&is_readable($ufilepath)){
							$zip->add_from_file($ufilepath,$dfilepath);
						}
					}
				}

				if(!@fputs($fp,$zip->get_file())){
					//无法写入备份文件;
					return false;
				}
				fclose($fp);
			}else{
				//无法创建备份文件
				return false;
			}
			$extractdir=(false!==$pos=strrpos($rfilepath,'.'))?substr($rfilepath,0,$pos):$rfilepath;
			if($backup){
				$zip->extract($rfilepath,$extractdir,7);
				foreach ($filelist as $ufile){
					if(!$ufile['folder']){
						$sfile=trimmultichar($extractdir."/".$ufile['filename'],'/');
						writefile($ufile['filename'],$sfile,$isdone);
						@unlink($sfile);
					}
				}
				@FileHandler::remove($extractdir);
			}else{
				return false;
				//备份文件失败
			}
		}elseif($fileextname=='aut'){
			if(file_exists($rfilepath)){
				include($rfilepath);
			}
		}else{
			if(false===$flastmodified=filelastmodified($filepath))$flastmodified=0;
			if($isdone==0&&$flastmodified!=$file["lastmodified"]&&$foruminfo["lastmodified"]!=0&&$flastmodified>=$foruminfo["lastmodified"]){
				$syslastmodified>$flastmodified AND $syslastmodified=$flastmodified;
				$resultmsg.="<font color=red>{$lang["upgrade.info9"]}<b>{$file["filename"]}</b></font>{$lang["upgrade.cantupdate"]}<BR>{$lang["upgrade.cantupdatetip"]}<BR>";
				continue;
			}
			//读取原文件以做备份
			$osize=@filesize(ROOT_PATH.$filepath);
			$filestr=($osize!==false)?getfile(ROOT_PATH.$filepath):false;
			if($filestr&&$fp=fopen($rfilepath.".bak",'wb')){
				fwrite($fp,$filestr);
				fclose($fp);
			}

			//写入文件
			//debug 111
	
			if(writefile($file["filepath"],$rfilepath,$isdone)){
				$resultmsg.="{$lang["upgrade.info9"]}<b>{$file["filename"]}</b>{$lang["upgrade.info0"]}<BR>";
				$i_ok++;
			}else{
				//文件写入失败
				$resultmsg.="<font color=red>{$lang["upgrade.info9"]}<B>{$file["filename"]}</B>{$lang["upgrade.info10"]}<B>".dirname($filepath)."</b>{$lang["upgrade.info11"]}</font><BR>";
				$i_fail++;
			}
		}
		//check the file if modified since lastupdate

		if(false===$lastmodified=filelastmodified($file["filepath"]))$lastmodified=time();
		$sql="update {$dv}sysfiles set isdone=1,lastmodified={$lastmodified} where id={$file["id"]}";
		$db->query($sql);

	}

	$sql="update {$dv}sysupgrade set lastmodified={$syslastmodified}";
	@$db->query($sql);
	createupgradeconfig();
	$resultmsg.="{$lang["upgrade.info12"]}{$i_ok}{$lang["upgrade.info13"]},{$i_fail}{$lang["upgrade.info14"]}<BR>";
	return $resultmsg;
}

function restore($idlist){
	global $db,$dv,$foruminfo;
	if(empty($idlist))return;
	$sql="SELECT id,filepath,rawbinary FROM {$dv}sysfiles where isdone=1 and id in ({$idlist})";
	$sql.=" order by lastupdate ASC";
	$query=$db->query($sql);
	createftp();
	while($file=$db->fetch_array($query)){
		$filepath=$file["filepath"];
		$fileextname=strtolower((false===($dpos=strrpos($filepath,'.')))?'':substr($filepath,$dpos+1));
		$rfilepath=trimmultichar($filepath,'/').".bak";
		$rfilepath="./sysupgrade/".str_replace('/','__',$rfilepath);
		if(!file_exists($rfilepath)||!is_readable($rfilepath)){
			//还原文件失败,请检查文件是存在或者可读
		}
		$isrestore=false;
		if($fileextname=='zip'){
			$zip=new zip();
			$zip->extract($rfilepath,ROOT_PATH,7);
			$isrestore=true;
		}elseif($fileextname!='aut'){
			if(!file_exists($rfilepath)||writefile($filepath,$rfilepath,true)){
				$isrestore=true;
			}else{
				//还原文件失败，请检查此目录是否可写
			}
		}else{
			@unlink($rfilepath);
			
			$isrestore=true;
		}

		if($isrestore){
			if(false===$lastmodified=filelastmodified($file["filepath"]))$lastmodified=time();
			$sql="update {$dv}sysfiles set isdone=2,lastmodified={$lastmodified} where id={$file["id"]}";
			$db->query($sql);
		}
	}
}

function createftp(){
	//创建一个FTP连接，并自动切换到$root目录并检查认证文件
	global $ftp,$foruminfo,$forum_adminfolder;
	$authfile=str_replace("\\","/",$forum_adminfolder)."dvbbs_upgrade_authentication.key";
	if(!$ftp)$ftp=new ftpFileHandle($foruminfo["ftpserver"],$foruminfo["ftpport"],$foruminfo["ftpuser"]
	,$foruminfo["ftppass"]);
	if(!$ftp->connectioned()||!ftp_chdir($ftp->ftpconn,$foruminfo["ftproot"])||ftp_mdtm($ftp->ftpconn,$authfile)===-1){
		$ftp=false;
		return false;
	}
	return true;
}


function writefile($filepath,$sfilepath,$showerr=false){
	global $ftp,$lang;

	if(!file_exists($sfilepath))return false;
	//首先尝试用FTP写入文件
	$filepath=str_replace("\\","/",$filepath);
	if(substr($filepath,0,1)=='/')$filepath=substr($filepath,1);
	if($ftp||createftp()){
		if(!$fp=@fopen($sfilepath,"rb"))return false;
		if($ret=$ftp->fputfile($fp,$filepath)){
			@file_exists($sfilepath) AND (@unlink($sfilepath)||@$ftp->deletefile($sfilepath));
		}
		fclose($fp);
		if($ret)return true;
	}
	
	//FTP写入文件失败,则直接写入文件
	$realfp=trimmultichar(ROOT_PATH.$filepath,"/");
	if(!dir(dirname($realfp)))@createdir(dirname($realfp));
	if($fp=@fopen($realfp,"wb")){
		$filebinary=getfile($sfilepath);
		$wsize=fputs($fp,$filebinary);
		fclose($fp);
		return true;
	}elseif(!$ftp&&$showerr){
		//显示FTP错误
		head();
		show_msg("{$lang["upgrade.ftptest"]}","{$lang["upgrade.ftpconfigerr"]}",0,'','',"upgrade.php?reaction=setting","{$lang["upgrade.ftpconfig"]}");
		exit;
	}
	return false;
}

function ftptest($ftpserver="",$ftpport="",$ftpuser="",$ftppass="",$ftproot="",$showerr=true,$timeout=10){
	global $lang;
	$ftpconn=@ftp_connect($ftpserver,$ftpport,$timeout);
	$errno=0;
	global $forum_adminfolder;
	$authfile=str_replace("\\","/",$forum_adminfolder)."dvbbs_upgrade_authentication.key";
	if($ftpconn===false){
		//连接失败
		$errno=1;
		if($showerr)show_msg("{$lang["upgrade.ftptest"]}","{$lang["upgrade.ftpconnect"]}:{$ftpserver}:{$ftpport}...
		{$lang["upgrade.fail"]}",0,'','',"javascript:window.history.back(-1)","{$lang["upgrade.back"]}");
	}else{
		if(@ftp_login($ftpconn,$ftpuser,$ftppass)===false){
			//登陆失败
			$errno=2;
			if($showerr)show_msg("{$lang["upgrade.ftptest"]}","{$lang["upgrade.ftpconnect"]}:{$ftpserver}:{$ftpport}...
			{$lang["upgrade.ok"]}<BR>{$lang["upgrade.ftplogin"]}:{$ftpuser}:{$ftppass}...{$lang["upgrade.fail"]}",0,''
			,'',"javascript:window.history.back(-1)","{$lang["upgrade.back"]}");

		}elseif(@ftp_chdir($ftpconn,$ftproot)===false){
			//不存在此目录
			$errno=4;
			show_msg("{$lang["upgrade.ftptest"]}","{$lang["upgrade.ftptest"]}{$lang["upgrade.ok"]}<BR>
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{$lang["upgrade.ftpchangedir"]}:{$ftproot}{$lang["upgrade.fail"]}
			,{$lang["upgrade.drinoexists"]}",1,'','',"javascript:window.history.back(-1)","{$lang["upgrade.back"]}");
		}elseif(@$f=ftp_mdtm($ftpconn,$authfile)===-1){
			//认证失败
			$errno=8;
			show_msg("{$lang["upgrade.ftptest"]}","{$lang["upgrade.ftptest"]}{$lang["upgrade.ok"]}<BR>
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{$lang["upgrade.ftplogin"]}{$lang["upgrade.ok"]}<BR>
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{$lang["upgrade.authfailed"]}：($authfile){$lang["upgrade.fail"]}"
			,1,'','',"javascript:window.history.back(-1)","{$lang["upgrade.back"]}");
		}else{
			//成功
			show_msg("{$lang["upgrade.ftptest"]}","{$lang["upgrade.ftptest"]}{$lang["upgrade.ok"]}",1,''
			,'',"javascript:window.history.back(-1)","{$lang["upgrade.back"]}");
		}
		@ftp_close($ftpconn);
	}
	return $errno;
}
function getThisPageUrl(){
	global $_SERVER;
	$url="";
	if($_SERVER['URL']!="")return $_SERVER['URL'];
	if($_SERVER['HTTP_HOST']!=""){
		$server=$_SERVER['HTTP_HOST'];
	}elseif($_SERVER['SERVER_ADDR']!=""){
		$server=$_SERVER['SERVER_ADDR'];
	}
	if ($_SERVER['PHP_SELF']) {
		$scriptname = $_SERVER['PHP_SELF'];
	} elseif ($_SERVER['PATH_INFO']) {
		$scriptname = $_SERVER['PATH_INFO'];
	} elseif ($_SERVER['ORIG_PATH_INFO']) {
		$scriptname = $_SERVER['ORIG_PATH_INFO'];
	} elseif ($_SERVER['REQUEST_URI']) {
		$scriptname = $_SERVER['REQUEST_URI'];
		if (false !== ($ipos = strpos($scriptname, '?'))) {
			$scriptname = substr($scriptname, 0, $ipos);
		}
	} elseif ($_SERVER['URL']) {
		$scriptname = $_SERVER['URL'];
		if (false !== ($ipos = strpos($scriptname, '?'))) {
			$scriptname = substr($scriptname, 0, $ipos);
		}
	}
	$url="http://".$server.$scriptname;
	$_SERVER['QUERY_STRING']!="" AND $url."?".$_SERVER['QUERY_STRING'];
	return $url;
}

function filelastmodified($file){
	global $ftp;
	clearstatcache();
	$file=str_replace("\\","/",$file);
	$file{0}="/" AND $file=substr($file,1);
	$realpath=realpath(ROOT_PATH.$file);
	if(false!==($fstat=@stat($realpath)))return $fstat["mtime"];
	if($ftp)return $ftp->filelastmodified($file);
	return false;
}

function createupgradeconfig($foruminfo=false){
	global $db,$dv;
	if(!$foruminfo){
		$fquery=$db->query("select `script`,`version`,`database`,`charset`,`encode`,`lastupdate`,`lastmodified`,`query_interval`,`autoupgrade`,`autorun`,`upgradeserver`,`auth`,`rpkey`,`ftpserver`,`ftpport`,`ftpuser`,`ftppass`,`ftproot` from {$dv}sysupgrade");
		$foruminfo=$db->fetch_array($fquery);
	}
	if($foruminfo){
		if(!$fp=fopen(UPGRADECONFIGPATH,"wb")){
			return false;
		}else{
			@chmod(UPGRADECONFIGPATH,0777);
			$content="<?php\n".varstoscript("foruminfo",$foruminfo).";\n?>";
			fputs($fp,$content);
			@fclose($fp);
			return $foruminfo;
		}
	}else{
		return false;
	}
}

function trimmultichar($str,$trim){
	$strs=explode($trim,$str);
	foreach ($strs as $k=>$v){
		if(empty($v))unset($strs[$k]);
	}
	$str=join('/',$strs);
	return $str;
}

function createdir($pth,$mod=0777){
	$pth = explode("/",$pth);
	for($i=0;isset($pth[$i]);$i++){
		if(!$pth[$i]) continue;$pthss.=$pth[$i]."/";
		if(!is_dir($pthss))@mkdir($pthss,$mod);
	}
}
?>