国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

398 lines
14KB

  1. <?php
  2. @set_time_limit(0);
  3. /**
  4. * 系统运行环境检测
  5. *
  6. * @version $Id: testenv.php 13:57 2011/11/10 tianya $
  7. * @package DedeBIZ.Administrator
  8. * @copyright Copyright (c) 2020, DedeBIZ.COM
  9. * @license https://www.dedebiz.com/license
  10. * @link https://www.dedebiz.com
  11. */
  12. require_once(dirname(__FILE__) . "/config.php");
  13. CheckPurview('sys_Edit');
  14. $action = isset($action) ? $action : '';
  15. ?>
  16. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  17. <html xmlns="http://www.w3.org/1999/xhtml">
  18. <head>
  19. <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $GLOBALS['cfg_soft_lang']; ?>">
  20. <title>系统运行目录权限检测</title>
  21. <link rel="stylesheet" type="text/css" href="css/base.css" />
  22. <link rel="stylesheet" type="text/css" href="css/indexbody.css" />
  23. <script type="text/javascript" src="../static/js/jquery.js"></script>
  24. </head>
  25. <body leftmargin="8" topmargin='8' bgcolor="#FFFFFF" style="min-width:840px">
  26. <?php
  27. if (!function_exists('TestWriteable')) {
  28. // 检测是否可写
  29. function TestWriteable($d, $c = TRUE)
  30. {
  31. $tfile = '_write_able.txt';
  32. $d = preg_replace("/\/$/", '', $d);
  33. $fp = @fopen($d . '/' . $tfile, 'w');
  34. if (!$fp) {
  35. if ($c == false) {
  36. @chmod($d, 0777);
  37. return false;
  38. } else return TestWriteable($d, true);
  39. } else {
  40. fclose($fp);
  41. return @unlink($d . '/' . $tfile) ? true : false;
  42. }
  43. }
  44. }
  45. if (!function_exists('TestExecuteable')) {
  46. // 检查是否具目录可执行
  47. function TestExecuteable($d = '.', $siteuRL = '', $rootDir = '')
  48. {
  49. $testStr = '<' . chr(0x3F) . 'p' . chr(hexdec(68)) . chr(112) . "\n\r";
  50. $filename = md5($d) . '.php';
  51. $testStr .= 'function test(){ echo md5(\'' . $d . '\');}' . "\n\rtest();\n\r";
  52. $testStr .= chr(0x3F) . '>';
  53. $reval = false;
  54. if (empty($rootDir)) $rootDir = DEDEROOT;
  55. if (TestWriteable($d)) {
  56. @file_put_contents($d . '/' . $filename, $testStr);
  57. $remoteUrl = $siteuRL . '/' . str_replace($rootDir, '', str_replace("\\", '/', realpath($d))) . '/' . $filename;
  58. $tempStr = @PostHost($remoteUrl);
  59. $reval = (md5($d) == trim($tempStr)) ? true : false;
  60. unlink($d . '/' . $filename);
  61. return $reval;
  62. } else {
  63. return -1;
  64. }
  65. }
  66. }
  67. if (!function_exists('PostHost')) {
  68. function PostHost($host, $data = '', $method = 'GET', $showagent = null, $port = null, $timeout = 30)
  69. {
  70. $parse = @parse_url($host);
  71. if (empty($parse)) return false;
  72. if ((int)$port > 0) {
  73. $parse['port'] = $port;
  74. } elseif (!@$parse['port']) {
  75. $parse['port'] = '80';
  76. }
  77. $parse['host'] = str_replace(array('http://', 'https://'), array('', 'ssl://'), "$parse[scheme]://") . $parse['host'];
  78. if (!$fp = @fsockopen($parse['host'], $parse['port'], $errnum, $errstr, $timeout)) {
  79. return false;
  80. }
  81. $method = strtoupper($method);
  82. $wlength = $wdata = $responseText = '';
  83. $parse['path'] = str_replace(array('\\', '//'), '/', @$parse['path']) . "?" . @$parse['query'];
  84. if ($method == 'GET') {
  85. $separator = @$parse['query'] ? '&' : '';
  86. substr($data, 0, 1) == '&' && $data = substr($data, 1);
  87. $parse['path'] .= $separator . $data;
  88. } elseif ($method == 'POST') {
  89. $wlength = "Content-length: " . strlen($data) . "\r\n";
  90. $wdata = $data;
  91. }
  92. $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";
  93. @fwrite($fp, $write);
  94. while ($data = @fread($fp, 4096)) {
  95. $responseText .= $data;
  96. }
  97. @fclose($fp);
  98. empty($showagent) && $responseText = trim(stristr($responseText, "\r\n\r\n"), "\r\n");
  99. return $responseText;
  100. }
  101. }
  102. $allPath = array();
  103. $needDir = "$cfg_medias_dir|
  104. $cfg_image_dir|
  105. $ddcfg_image_dir|
  106. $cfg_user_dir|
  107. $cfg_soft_dir|
  108. $cfg_other_medias|
  109. $cfg_medias_dir/flink|
  110. $cfg_cmspath/data|
  111. $cfg_cmspath/data/$cfg_backup_dir|
  112. $cfg_cmspath/data/textdata|
  113. $cfg_cmspath/data/sessions|
  114. $cfg_cmspath/data/tplcache|
  115. $cfg_cmspath/data/admin|
  116. $cfg_cmspath/data/enums|
  117. $cfg_cmspath/data/mark|
  118. $cfg_cmspath/data/module|
  119. $cfg_cmspath/data/rss|
  120. $cfg_special|
  121. $cfg_cmspath$cfg_arcdir";
  122. $needDir = explode('|', $needDir);
  123. foreach ($needDir as $key => $val) {
  124. $allPath[trim($val)] = array(
  125. 'read' => true, // 读取
  126. 'write' => true, // 写入
  127. 'execute' => false // 执行
  128. );
  129. }
  130. // 所有栏目目录
  131. $sql = "SELECT typedir FROM #@__arctype ORDER BY id DESC";
  132. $dsql->SetQuery($sql);
  133. $dsql->Execute('al', $sql);
  134. while ($row = $dsql->GetArray('al')) {
  135. $typedir = str_replace($cfg_basehost, '', $row['typedir']);
  136. if (preg_match("/^http:|^ftp:/i", $row['typedir'])) continue;
  137. $typedir = str_replace("{cmspath}", $cfg_cmspath, $row['typedir']);
  138. $allPath[trim($typedir)] = array(
  139. 'read' => true, // 读取
  140. 'write' => true, // 写入
  141. 'execute' => false // 执行
  142. );
  143. }
  144. // 只允许读取,不允许写入的目录
  145. $needDir = array(
  146. 'include',
  147. 'member',
  148. 'plus',
  149. );
  150. // 获取子目录
  151. function GetSondir($d, &$dirname = array())
  152. {
  153. $dh = dir($d);
  154. while ($filename = $dh->read()) {
  155. if (
  156. substr($filename, 0, 1) == '.' || is_file($d . '/' . $filename) ||
  157. preg_match("#^(svn|bak-)#i", $filename)
  158. ) {
  159. continue;
  160. }
  161. if (is_dir($d . '/' . $filename)) {
  162. $dirname[] = $d . '/' . $filename;
  163. GetSondir($d . '/' . $filename, $dirname);
  164. }
  165. }
  166. $dh->close();
  167. return $dirname;
  168. }
  169. //获取所有文件列表
  170. function preg_ls($path = ".", $rec = FALSE, $pat = "/.*/", $ignoredir = '')
  171. {
  172. while (substr($path, -1, 1) == "/") {
  173. $path = substr($path, 0, -1);
  174. }
  175. if (!is_dir($path)) {
  176. $path = dirname($path);
  177. }
  178. if ($rec !== TRUE) {
  179. $rec = FALSE;
  180. }
  181. $d = dir($path);
  182. $ret = array();
  183. while (FALSE !== ($e = $d->read())) {
  184. if (($e == ".") || ($e == "..")) {
  185. continue;
  186. }
  187. if ($rec && is_dir($path . "/" . $e) && ($ignoredir == '' || strpos($ignoredir, $e) === FALSE)) {
  188. $ret = array_merge($ret, preg_ls($path . "/" . $e, $rec, $pat, $ignoredir));
  189. continue;
  190. }
  191. if (!preg_match($pat, $e)) {
  192. continue;
  193. }
  194. $ret[] = $path . "/" . $e;
  195. }
  196. return (empty($ret) && preg_match($pat, basename($path))) ? array($path . "/") : $ret;
  197. }
  198. foreach ($needDir as $key => $val) {
  199. $allPath[trim('/' . $val)] = array(
  200. 'read' => true, // 读取
  201. 'write' => false, // 写入
  202. 'execute' => true // 执行
  203. );
  204. $sonDir = GetSondir(DEDEROOT . '/' . $val);
  205. foreach ($sonDir as $kk => $vv) {
  206. $vv = trim(str_replace(DEDEROOT, '', $vv));
  207. $allPath[$vv] = array(
  208. 'read' => true, // 读取
  209. 'write' => false, // 写入
  210. 'execute' => true // 执行
  211. );
  212. }
  213. }
  214. // 不需要执行的
  215. $needDir = array(
  216. '/images',
  217. '/templets'
  218. );
  219. foreach ($needDir as $key => $val) {
  220. $allPath[trim('/' . $val)] = array(
  221. 'read' => true, // 读取
  222. 'write' => false, // 写入
  223. 'execute' => false // 执行
  224. );
  225. $sonDir = GetSondir(DEDEROOT . '/' . $val);
  226. foreach ($sonDir as $kk => $vv) {
  227. $vv = trim(str_replace(DEDEROOT . '/', '', $vv));
  228. $allPath[$vv] = array(
  229. 'read' => true, // 读取
  230. 'write' => false, // 写入
  231. 'execute' => false // 执行
  232. );
  233. }
  234. }
  235. // 所有js建议只读
  236. $jsDir = array(
  237. '/images',
  238. '/templets',
  239. '/include'
  240. );
  241. foreach ($jsDir as $k => $v) {
  242. $jsfiles = preg_ls(DEDEROOT . $v, TRUE, "/.*\.(js)$/i");
  243. foreach ($jsfiles as $k => $v) {
  244. $vv = trim(str_replace(DEDEROOT . '/', '/', $v));
  245. $allPath[$vv] = array(
  246. 'read' => true, // 读取
  247. 'write' => false, // 写入
  248. 'execute' => false // 执行
  249. );
  250. }
  251. }
  252. ?>
  253. <div id="safemsg">
  254. <dl style="margin-left:0.5%;margin-right:0.5%; width:97%" id="item1" class="dbox">
  255. <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>
  256. <dd>
  257. <div style="padding:10px"> 说明:本程序用于检测DedeCMSV6站点所涉及的目录权限,并且提供一个全面的检测说明,您可以根据检测报告来配置站点以保证站点更为安全。</div>
  258. <div id="tableHeader" style="margin-left:10px">
  259. <table width="784" border="0" cellpadding="0" cellspacing="1" bgcolor="#047700" id="scanTable">
  260. <thead>
  261. <tr>
  262. <td width="40%" height="25" align="center" bgcolor="#E3F1D1">目录</td>
  263. <td width="20%" height="25" align="center" bgcolor="#E3F1D1">执行</td>
  264. <td width="20%" height="25" align="center" bgcolor="#E3F1D1">读取</td>
  265. <td width="20%" height="25" align="center" bgcolor="#E3F1D1">写入</td>
  266. </tr>
  267. </thead>
  268. </table>
  269. </div>
  270. <div id="safelist" style="margin-left:10px">
  271. <div class="install" id="log" style="height: 260px; overflow: auto;">
  272. <table width="784" border="0" cellpadding="0" cellspacing="1" bgcolor="#047700" id="scanTable">
  273. <tbody id="mainList">
  274. </tbody>
  275. </table>
  276. </div>
  277. </div>
  278. </dd>
  279. </dl>
  280. </div>
  281. <div style="margin: 0 auto; width:200px"><a href="javascript:startScan();"><img src="images/btn_scan.gif" width="154" height="46" /></a></div>
  282. <script type="text/javascript">
  283. $ = jQuery;
  284. var log = "<?php
  285. foreach ($allPath as $key => $val) {
  286. if (is_dir(DEDEROOT . $key)) {
  287. ?><?php echo $key; ?>|<?php
  288. $rs = TestExecuteable(DEDEROOT . $key, $cfg_basehost, $cfg_cmspath);
  289. if ($rs === -1) {
  290. echo "<font color='red'>无法判断</font>";
  291. } else {
  292. if ($val['execute'] == true)
  293. echo $rs != $val['execute'] ? "<font color='red'>错误(不可执行)</font>" : "<font color='green'>正常(可执行)</font>";
  294. else
  295. echo $rs != $val['execute'] ? "<font color='red'>错误(可执行)</font>" : "<font color='green'>正常(不可执行)</font>";
  296. }
  297. ?>|<?php
  298. if ($val['read'] == true)
  299. echo is_readable(DEDEROOT . $key) != $val['read'] ? "<font color='red'>错误(不可读)</font>" : "<font color='green'>正常(可读)</font>";
  300. else
  301. echo is_readable(DEDEROOT . $key) != $val['read'] ? "<font color='red'>错误(可读)</font>" : "<font color='green'>正常(不可读)</font>";
  302. ?>|<?php
  303. if ($val['write'] == true)
  304. echo TestWriteable(DEDEROOT . $key) != $val['write'] ? "<font color='red'>错误(不可写)</font>" : "<font color='green'>正常(可写)</font>";
  305. else
  306. echo TestWriteable(DEDEROOT . $key) != $val['write'] ? "<font color='red'>错误(可写)</font>" : "<font color='green'>正常(不可写)</font>";
  307. ?><dedecms><?php
  308. } else {
  309. ?><?php echo $key; ?>|无需判断|<?php
  310. if ($val['read'] == true)
  311. echo is_readable(DEDEROOT . $key) != $val['read'] ? "<font color='red'>错误(不可读)</font>" : "<font color='green'>正常(可读)</font>";
  312. else
  313. echo is_readable(DEDEROOT . $key) != $val['read'] ? "<font color='red'>错误(可读)</font>" : "<font color='green'>正常(不可读)</font>";
  314. ?>|<?php
  315. if ($val['write'] == true)
  316. echo is_writable(DEDEROOT . $key) != $val['write'] ? "<font color='red'>错误(不可写)</font>" : "<font color='green'>正常(可写)</font>";
  317. else
  318. echo is_writable(DEDEROOT . $key) != $val['write'] ? "<font color='red'>错误(可写)</font>" : "<font color='green'>正常(不可写)</font>";
  319. ?><dedecms><?php
  320. }
  321. }
  322. ?>";
  323. var n = 0;
  324. var timer = 0;
  325. log = log.split('<dedecms>');
  326. function GoPlay() {
  327. if (n > log.length - 1) {
  328. n = -1;
  329. clearIntervals();
  330. }
  331. if (n > -1) {
  332. postcheck(n);
  333. n++;
  334. }
  335. }
  336. function postcheck(n) {
  337. var item = log[n];
  338. item = item.split('|');
  339. document.getElementById('log').scrollTop = document.getElementById('log').scrollHeight;
  340. if (item == '') {
  341. return false;
  342. }
  343. var tempvar = '<tr>\r <td width="40%" height="23" bgcolor="#FFFFFF">' + item[0] + '</td>\r <td width="20%" height="23" align="center" bgcolor="#FEF7C5">' + item[1] + '</td>\r <td width="20%" height="23" align="center" bgcolor="#FFFFFF">\r ' + item[2] + '</td>\r <td width="20%" height="23" align="center" bgcolor="#FFFFFF">\r ' + item[3] + '</td>\r </tr> ';
  344. //chiledelem.innerHTML = tempvar;
  345. //document.getElementById("mainList").appendChild(chiledelem);
  346. $("#mainList").append(tempvar);
  347. document.getElementById('log').scrollTop = document.getElementById('log').scrollHeight;
  348. }
  349. function setIntervals() {
  350. timer = setInterval('GoPlay()', 50);
  351. }
  352. function clearIntervals() {
  353. clearInterval(timer);
  354. //document.getElementById('install').submit();
  355. alert('全部检测完毕,您可以按照检测结果进行系统权限调整!');
  356. }
  357. //setTimeout(setIntervals, 100);
  358. function changeHeight() {
  359. var newheight = $(window).height() - 170;
  360. $("#safelist").css('height', newheight + 'px');
  361. var logheight = newheight;
  362. $("#log").css('height', logheight + 'px');
  363. }
  364. // 开始检测
  365. function startScan() {
  366. setTimeout(setIntervals, 100);
  367. }
  368. $.ready = function() {
  369. changeHeight();
  370. $(window).resize(function() {
  371. changeHeight();
  372. });
  373. };
  374. </script>
  375. </body>