<?php
@set_time_limit(0);
/**
 * 系统运行环境检测
 *
 * @version        $Id: testenv.php 13:57 2011/11/10 tianya $
 * @package        DedeBIZ.Administrator
 * @copyright      Copyright (c) 2022, DedeBIZ.COM
 * @license        https://www.dedebiz.com/license
 * @link           https://www.dedebiz.com
 */
require_once(dirname(__FILE__)."/config.php");
CheckPurview('sys_Edit');
$action = isset($action) ? $action : '';
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $GLOBALS['cfg_soft_lang']; ?>">
	<title>系统运行目录权限检测</title>
	<link rel="stylesheet" href="../static/web/css/admin.css" />
	<link rel="stylesheet" href="css/indexbody.css" />
	<script type="text/javascript" src="../static/web/js/jquery.min.js"></script>
</head>
<body leftmargin="8" topmargin='8' bgcolor="#FFFFFF" style="min-width:840px">
	<?php
	if (!function_exists('TestWriteable')) {
		//检测是否可写
		function TestWriteable($d, $c = TRUE)
		{
			$tfile = '_write_able.txt';
			$d = preg_replace("/\/$/", '', $d);
			$fp = @fopen($d.'/'.$tfile, 'w');
			if (!$fp) {
				if ($c == false) {
					@chmod($d, 0777);
					return false;
				} else return TestWriteable($d, true);
			} else {
				fclose($fp);
				return @unlink($d.'/'.$tfile) ? true : false;
			}
		}
	}
	if (!function_exists('TestExecuteable')) {
		//检查是否具目录可执行
		function TestExecuteable($d = '.', $siteuRL = '', $rootDir = '')
		{
			$testStr = '<'.chr(0x3F).'p'.chr(hexdec(68)).chr(112)."\n\r";
			$filename = md5($d).'.php';
			$testStr .= 'function test(){ echo md5(\''.$d.'\');}'."\n\rtest();\n\r";
			$testStr .= chr(0x3F).'>';
			$reval = false;
			if (empty($rootDir)) $rootDir = DEDEROOT;
			if (TestWriteable($d)) {
				@file_put_contents($d.'/'.$filename, $testStr);
				$remoteUrl = $siteuRL.'/'.str_replace($rootDir, '', str_replace("\\", '/', realpath($d))).'/'.$filename;
				$tempStr = @PostHost($remoteUrl);

				$reval = (md5($d) == trim($tempStr)) ? true : false;
				unlink($d.'/'.$filename);
				return $reval;
			} else {
				return -1;
			}
		}
	}
	if (!function_exists('PostHost')) {
		function PostHost($host, $data = '', $method = 'GET', $showagent = null, $port = null, $timeout = 30)
		{
			$parse = @parse_url($host);
			if (empty($parse)) return false;
			if ((int)$port > 0) {
				$parse['port'] = $port;
			} elseif (!@$parse['port']) {
				$parse['port'] = '80';
			}
			$parse['host'] = str_replace(array('http://', 'https://'), array('', 'ssl://'), "$parse[scheme]://").$parse['host'];
			if (!$fp = @fsockopen($parse['host'], $parse['port'], $errnum, $errstr, $timeout)) {
				return false;
			}
			$method = strtoupper($method);
			$wlength = $wdata = $responseText = '';
			$parse['path'] = str_replace(array('\\', '//'), '/', @$parse['path'])."?".@$parse['query'];
			if ($method == 'GET') {
				$separator = @$parse['query'] ? '&' : '';
				substr($data, 0, 1) == '&' && $data = substr($data, 1);
				$parse['path'] .= $separator.$data;
			} elseif ($method == 'POST') {
				$wlength = "Content-length: ".strlen($data)."\r\n";
				$wdata = $data;
			}
			$write = "$method $parse[path] HTTP/1.0\r\nHost: $parse[host]\r\nContent-type: application/x-www-form-urlencoded\r\n{$wlength}Connection: close\r\n\r\n$wdata";
			@fwrite($fp, $write);
			while ($data = @fread($fp, 4096)) {
				$responseText .= $data;
			}
			@fclose($fp);
			empty($showagent) && $responseText = trim(stristr($responseText, "\r\n\r\n"), "\r\n");
			return $responseText;
		}
	}
	$allPath = array();
	$needDir = "$cfg_medias_dir|
	$cfg_image_dir|
	$ddcfg_image_dir|
	$cfg_user_dir|
	$cfg_soft_dir|
	$cfg_other_medias|
	$cfg_medias_dir/flink|
	$cfg_cmspath/data|
	$cfg_cmspath/data/$cfg_backup_dir|
	$cfg_cmspath/data/textdata|
	$cfg_cmspath/data/sessions|
	$cfg_cmspath/data/tplcache|
	$cfg_cmspath/data/admin|
	$cfg_cmspath/data/enums|
	$cfg_cmspath/data/mark|
	$cfg_cmspath/data/module|
	$cfg_cmspath/data/rss|
	$cfg_special|
	$cfg_cmspath$cfg_arcdir";
	$needDir = explode('|', $needDir);
	foreach ($needDir as $key => $val) {
		$allPath[trim($val)] = array(
			'read' => true,    //读取
			'write' => true,   //写入
			'execute' => false //执行
		);
	}
	//所有栏目目录
	$sql = "SELECT typedir FROM #@__arctype ORDER BY id DESC";
	$dsql->SetQuery($sql);
	$dsql->Execute('al', $sql);
	while ($row = $dsql->GetArray('al')) {
		$typedir = str_replace($cfg_basehost, '', $row['typedir']);
		if (preg_match("/^http:|^ftp:/i", $row['typedir'])) continue;
		$typedir = str_replace("{cmspath}", $cfg_cmspath, $row['typedir']);
		$allPath[trim($typedir)] = array(
			'read' => true,    //读取
			'write' => true,   //写入
			'execute' => false //执行
		);
	}
	//只允许读取,不允许写入的目录
	$needDir = array(
		'include',
		'member',
		'plus',
	);
	//获取子目录
	function GetSondir($d, &$dirname = array())
	{
		$dh = dir($d);
		while ($filename = $dh->read()) {
			if (
				substr($filename, 0, 1) == '.' || is_file($d.'/'.$filename) ||
				preg_match("#^(svn|bak-)#i", $filename)
			) {
				continue;
			}
			if (is_dir($d.'/'.$filename)) {
				$dirname[] = $d.'/'.$filename;
				GetSondir($d.'/'.$filename, $dirname);
			}
		}
		$dh->close();
		return $dirname;
	}
	//获取所有文件列表
	function preg_ls($path = ".", $rec = FALSE, $pat = "/.*/", $ignoredir = '')
	{
		while (substr($path, -1, 1) == "/") {
			$path = substr($path, 0, -1);
		}
		if (!is_dir($path)) {
			$path = dirname($path);
		}
		if ($rec !== TRUE) {
			$rec = FALSE;
		}
		$d = dir($path);
		$ret = array();
		while (FALSE !== ($e = $d->read())) {
			if (($e == ".") || ($e == "..")) {
				continue;
			}
			if ($rec && is_dir($path."/".$e) && ($ignoredir == '' || strpos($ignoredir, $e) === FALSE)) {
				$ret = array_merge($ret, preg_ls($path."/".$e, $rec, $pat, $ignoredir));
				continue;
			}
			if (!preg_match($pat, $e)) {
				continue;
			}
			$ret[] = $path."/".$e;
		}
		return (empty($ret) && preg_match($pat, basename($path))) ? array($path."/") : $ret;
	}
	foreach ($needDir as $key => $val) {
		$allPath[trim('/'.$val)] = array(
			'read' => true,    //读取
			'write' => false,   //写入
			'execute' => true //执行
		);
		$sonDir = GetSondir(DEDEROOT.'/'.$val);
		foreach ($sonDir as $kk => $vv) {
			$vv = trim(str_replace(DEDEROOT, '', $vv));
			$allPath[$vv] = array(
				'read' => true,    //读取
				'write' => false,   //写入
				'execute' => true //执行
			);
		}
	}
	//不需要执行的
	$needDir = array(
		'/images',
		'/templets'
	);
	foreach ($needDir as $key => $val) {
		$allPath[trim('/'.$val)] = array(
			'read' => true,    //读取
			'write' => false,   //写入
			'execute' => false //执行
		);
		$sonDir = GetSondir(DEDEROOT.'/'.$val);
		foreach ($sonDir as $kk => $vv) {
			$vv = trim(str_replace(DEDEROOT.'/', '', $vv));
			$allPath[$vv] = array(
				'read' => true,    //读取
				'write' => false,   //写入
				'execute' => false //执行
			);
		}
	}
	//所有js建议只读
	$jsDir = array(
		'/images',
		'/templets',
		'/include'
	);
	foreach ($jsDir as $k => $v) {
		$jsfiles = preg_ls(DEDEROOT.$v, TRUE, "/.*\.(js)$/i");
		foreach ($jsfiles as $k => $v) {
			$vv = trim(str_replace(DEDEROOT.'/', '/', $v));
			$allPath[$vv] = array(
				'read' => true,    //读取
				'write' => false,   //写入
				'execute' => false //执行
			);
		}
	}
	?>
	<div id="safemsg">
		<dl style="margin-left:0.5%;margin-right:0.5%; width:97%" id="item1" class="dbox">
			<dt class="lside"><span class="l" style="float:left">系统运行目录权限检测</span><span style="float:right; margin-right:20px"><a href="index_body.php">返回主页</a></span><span style="float:right; margin-right:20px"><a href="https://www.dedebiz.com/help" target="_blank">帮助说明</a></span></dt>
			<dd>
				<div style="padding:10px"> 说明：本程序用于检测DedeBIZ站点所涉及的目录权限，并且提供一个全面的检测说明，您可以根据检测报告来配置站点以保证站点更为安全</div>
				<div id="tableHeader" style="margin-left:10px">
					<table width="784" border="0" cellpadding="0" cellspacing="1" bgcolor="#047700" id="scanTable">
						<thead>
							<tr>
								<td width="40%" height="26" align="center" bgcolor="#E3F1D1">目录</td>
								<td width="20%" height="26" align="center" bgcolor="#E3F1D1">执行</td>
								<td width="20%" height="26" align="center" bgcolor="#E3F1D1">读取</td>
								<td width="20%" height="26" align="center" bgcolor="#E3F1D1">写入</td>
							</tr>
						</thead>
					</table>
				</div>
				<div id="safelist" style="margin-left:10px">
					<div class="install" id="log" style="height: 260px; overflow: auto;">
						<table width="784" border="0" cellpadding="0" cellspacing="1" bgcolor="#047700" id="scanTable">
							<tbody id="mainList">
							</tbody>
						</table>
					</div>
				</div>
			</dd>
		</dl>
	</div>
	<div style="margin: 0 auto; width:200px"><a href="javascript:startScan();"><img src="images/btn_scan.gif" width="154" height="36" /></a></div>
	<script type="text/javascript">
		$ = jQuery;
		var log = "<?php
					foreach ($allPath as $key => $val) {
						if (is_dir(DEDEROOT.$key)) {
					?><?php echo $key; ?>|<?php
											$rs = TestExecuteable(DEDEROOT.$key, $cfg_basehost, $cfg_cmspath);

											if ($rs === -1) {
												echo "<span style='color:#dc3545'>无法判断</span>";
											} else {
												if ($val['execute'] == true)
													echo $rs != $val['execute'] ? "<span style='color:#dc3545'>错误(不可执行)</span>" : "<span style='color:#28a745'>正常(可执行)</span>";
												else
													echo $rs != $val['execute'] ? "<span style='color:#dc3545'>错误(可执行)</span>" : "<span style='color:#28a745'>正常(不可执行)</span>";
											}
											?>|<?php
												if ($val['read'] == true)
													echo is_readable(DEDEROOT.$key) != $val['read'] ? "<span style='color:#dc3545'>错误(不可读)</span>" : "<span style='color:#28a745'>正常(可读)</span>";
												else
													echo is_readable(DEDEROOT.$key) != $val['read'] ? "<span style='color:#dc3545'>错误(可读)</span>" : "<span style='color:#28a745'>正常(不可读)</span>";
												?>|<?php
												if ($val['write'] == true)
													echo TestWriteable(DEDEROOT.$key) != $val['write'] ? "<span style='color:#dc3545'>错误(不可写)</span>" : "<span style='color:#28a745'>正常(可写)</span>";
												else
													echo TestWriteable(DEDEROOT.$key) != $val['write'] ? "<span style='color:#dc3545'>错误(可写)</span>" : "<span style='color:#28a745'>正常(不可写)</span>";
												?><dedecms><?php
										} else {
											?><?php echo $key; ?>|无需判断|<?php
																if ($val['read'] == true)
																	echo is_readable(DEDEROOT.$key) != $val['read'] ? "<span style='color:#dc3545'>错误(不可读)</span>" : "<span style='color:#28a745'>正常(可读)</span>";
																else
																	echo is_readable(DEDEROOT.$key) != $val['read'] ? "<span style='color:#dc3545'>错误(可读)</span>" : "<span style='color:#28a745'>正常(不可读)</span>";
																?>|<?php
																	if ($val['write'] == true)
																		echo is_writable(DEDEROOT.$key) != $val['write'] ? "<span style='color:#dc3545'>错误(不可写)</span>" : "<span style='color:#28a745'>正常(可写)</span>";
																	else
																		echo is_writable(DEDEROOT.$key) != $val['write'] ? "<span style='color:#dc3545'>错误(可写)</span>" : "<span style='color:#28a745'>正常(不可写)</span>";
																	?><dedecms><?php
															}
														}
																?>";
		var n = 0;
		var timer = 0;
		log = log.split('<dedecms>');

		function GoPlay() {
			if (n > log.length - 1) {
				n = -1;
				clearIntervals();
			}
			if (n > -1) {
				postcheck(n);
				n++;
			}
		}

		function postcheck(n) {
			var item = log[n];
			item = item.split('|');

			document.getElementById('log').scrollTop = document.getElementById('log').scrollHeight;
			if (item == '') {
				return false;
			}
			var tempvar = '<tr>\r				        <td width="40%" height="26" bgcolor="#FFFFFF">' + item[0] + '</td>\r		            <td width="20%" height="26" align="center" bgcolor="#FEF7C5">' + item[1] + '</td>\r				        <td width="20%" height="26" align="center" bgcolor="#FFFFFF">\r						' + item[2] + '</td>\r				        <td width="20%" height="26" align="center" bgcolor="#FFFFFF">\r						' + item[3] + '</td>\r			      </tr>  ';

			//chiledelem.innerHTML = tempvar;
			//document.getElementById("mainList").appendChild(chiledelem);
			$("#mainList").append(tempvar);
			document.getElementById('log').scrollTop = document.getElementById('log').scrollHeight;
		}

		function setIntervals() {
			timer = setInterval('GoPlay()', 50);
		}

		function clearIntervals() {
			clearInterval(timer);
			//document.getElementById('install').submit();
			alert('全部检测完毕，您可以按照检测结果进行系统权限调整');
		}
		//setTimeout(setIntervals, 100);


		function changeHeight() {
			var newheight = $(window).height() - 170;
			$("#safelist").css('height', newheight + 'px');
			var logheight = newheight;
			$("#log").css('height', logheight + 'px');
		}
		//开始检测
		function startScan() {
			setTimeout(setIntervals, 100);
		}
		$.ready = function() {
			changeHeight();
			$(window).resize(function() {
				changeHeight();
			});
		};
	</script>
</body>