cloud_security.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. <?php
  2. /**
  3. * [Discuz!] (C)2001-2099 Comsenz Inc.
  4. * This is NOT a freeware, use is subject to license terms
  5. *
  6. * $Id: cloud_security.php 36284 2016-12-12 00:47:50Z nemohou $
  7. */
  8. if(!defined('IN_DISCUZ') || !defined('IN_ADMINCP')) {
  9. exit('Access Denied');
  10. }
  11. $op = trim($_GET['op']);
  12. $_GET['anchor'] = in_array($_GET['anchor'], array('index', 'setting', 'thread', 'post', 'member', 'reportOperation', 'reopen')) ? $_GET['anchor'] : 'index';
  13. $pt = in_array($_GET['anchor'], array('thread', 'post')) ? $_GET['anchor'] : 'thread';
  14. $current = array($_GET['anchor'] => 1);
  15. $operateresultmap = array(
  16. '0' => 1,
  17. '-1' => 0,
  18. '-5' => 0
  19. );
  20. $securitynav = array();
  21. $securitynav[0] = array('security_index', 'cloud&operation=security&anchor=index', $current['index']);
  22. $securitynav[1] = array('security_blanklist', 'cloud&operation=security&anchor=setting', $current['setting']);
  23. $securitynav[2] = array('security_thread_list', 'cloud&operation=security&anchor=thread', $current['thread']);
  24. $securitynav[3] = array('security_post_list', 'cloud&operation=security&anchor=post', $current['post']);
  25. $securitynav[4] = array('security_member_list', 'cloud&operation=security&anchor=member', $current['member']);
  26. if (!$_G['inajax']) {
  27. cpheader();
  28. shownav('safe', 'menu_cloud_security', 'security_'.$_GET['anchor'].'_list');
  29. showsubmenu('menu_cloud_security', $securitynav);
  30. }
  31. $tpp = !empty($_GET['tpp']) ? $_GET['tpp'] : '20';
  32. $start_limit = ($page - 1) * $tpp;
  33. require_once libfile('function/discuzcode');
  34. require_once libfile('function/core');
  35. $datas = $data = $eviluids = $evilPids = $evilTids = $members = $thread = $post = '';
  36. if($_GET['anchor'] != 'reopen') {
  37. $apps = $appService->getCloudApps();
  38. if(empty($apps) || empty($apps[$operation]) || $apps[$operation]['status'] == 'close') {
  39. cpmsg('security_reopen', '', 'succeed');
  40. }
  41. }
  42. if ($_GET['anchor'] == 'index') {
  43. $utilService = Cloud::loadClass('Service_Util');
  44. $signUrl = $utilService->generateSiteSignUrl(array('v' => 2));
  45. $utilService->redirect($cloudDomain.'/security/stats/list/?' . $signUrl);
  46. } elseif ($_GET['anchor'] == 'setting') {
  47. if (!submitcheck('settingsubmit')) {
  48. loadcache('setting');
  49. $evilthreads = C::t('common_setting')->fetch('cloud_security_stats_thread');
  50. $evilposts = C::t('common_setting')->fetch('cloud_security_stats_post');
  51. $evilmembers = C::t('common_setting')->fetch('cloud_security_stats_member');
  52. $usergroupswhitelist = $_G['setting']['security_usergroups_white_list'];
  53. $groupselect = array();
  54. foreach (C::t('common_usergroup')->fetch_all_not(array('6','7')) as $group) {
  55. $group['type'] = $group['type'] == 'special' && $group['radminid'] ? 'specialadmin' : $group['type'];
  56. $groupselect[$group['type']] .= "<option value=\"$group[groupid]\" ".(in_array($group['groupid'], $usergroupswhitelist) ? 'selected' : '').">$group[grouptitle]</option>\n";
  57. }
  58. $groupselect = '<optgroup label="'.$lang['usergroups_member'].'">'.$groupselect['member'].'</optgroup>'.
  59. ($groupselect['special'] ? '<optgroup label="'.$lang['usergroups_special'].'">'.$groupselect['special'].'</optgroup>' : '').
  60. ($groupselect['specialadmin'] ? '<optgroup label="'.$lang['usergroups_specialadmin'].'">'.$groupselect['specialadmin'].'</optgroup>' : '').
  61. '<optgroup label="'.$lang['usergroups_system'].'">'.$groupselect['system'].'</optgroup>';
  62. $forumswhitelist = $_G['setting']['security_forums_white_list'];
  63. require_once libfile('function/forumlist');
  64. loadcache('forums');
  65. $forumselect = str_replace('%', '%%', forumselect(FALSE, 0, $forumswhitelist, TRUE));
  66. showformheader('cloud&operation=security&anchor=setting');
  67. showtableheader('security_white_list_setting', '', '', 2);
  68. showsetting('security_usergroup_white_list', '', '', '<select name="groupid[]" multiple="multiple" size="10">'.$groupselect.'</select>');
  69. showsetting('security_forum_white_list', '', '', '<select name="fid[]" multiple="multiple" size="10">'.$forumselect.'</select>');
  70. showsubmit('settingsubmit');
  71. showtablefooter();
  72. showformfooter();
  73. } else {
  74. $usergroups = $_POST['groupid'];
  75. $forums = $_POST['fid'];
  76. $updateData = array(
  77. 'security_usergroups_white_list' => serialize($usergroups),
  78. 'security_forums_white_list' => serialize($forums)
  79. );
  80. C::t('common_setting')->update_batch($updateData);
  81. updatecache('setting');
  82. cpmsg('setting_update_succeed', 'action=cloud&operation=security&anchor='.$_GET['anchor'], 'succeed');
  83. }
  84. } elseif ($_GET['anchor'] == 'thread') {
  85. $count = C::t('#security#security_evilpost')->count_by_type('1');
  86. $multipage = multi($count, $tpp, $page, ADMINSCRIPT.'?action=cloud&operation=security&anchor=thread');
  87. list($datas, $evilTids) = getEvilList('thread', $start_limit, $tpp);
  88. echo "<p><a href='###' onclick='$(\"recyclebinform\").submit();'>{$lang['security_recyclebin_thread']}</a></p>";
  89. showformheader('recyclebin&operation=search', 'style="display: none;"', 'recyclebinform');
  90. showhiddenfields(array('security' => 1, 'searchsubmit' => 1));
  91. showformfooter();
  92. showtableheader('', '', 'id = "security_list"');
  93. showsubtitle(array('security_subject', 'security_forum', 'security_author', 'security_thread_status'));
  94. foreach($datas as $key => $value) {
  95. if(!$value['message']) {
  96. $subjectstyle = 'class = "threadopt"';
  97. } else {
  98. $subjectstyle = '';
  99. }
  100. $value['message'] = convertMessage($value);
  101. $modthreadkey = modauthkey($value['tid']);
  102. $viewlink = $value['message'] ? '<a href="forum.php?mod=redirect&goto=findpost&ptid='.$value['tid'].'&pid='.$value['pid'].'&modthreadkey='.$modthreadkey.'" target="_blank" title="'.$lang['security_view_thread'].'">'.$value['subject'].'</a>' : '';
  103. $thread = array(convertSubjectandIP($value, $viewlink), getNamebyFid($value['fid']), convertAuthorAndDate($value), //convertIdtoStr($value['eviltype']),
  104. convertIdtoStr($value['invisible'], 'adminoperate'));
  105. showtagheader('tbody', '', true, 'hover');
  106. showtablerow($subjectstyle, array('width = "400px"'), $thread);
  107. $value['message'] ? showtablerow('class="threadopt" style = "display: none;" id = "mod_'.$value['tid'].'_row_'.$key.'"', 'colspan = "6"', $value['message']) : '';
  108. showtagfooter('tbody');
  109. }
  110. if ($multipage) {
  111. showtablerow('', 'colspan = "6"', $multipage);
  112. }
  113. showtablefooter();
  114. } elseif($_GET['anchor'] == 'post') {
  115. $count = C::t('#security#security_evilpost')->count_by_type('0');
  116. $multipage = multi($count, $tpp, $page, ADMINSCRIPT.'?action=cloud&operation=security&anchor=post');
  117. list($datas, $evilPids) = getEvilList('post', $start_limit, $tpp);
  118. echo "<p><a href='###' onclick='$(\"recyclebinpostform\").submit();'>{$lang['security_recyclebin_post']}</a></p>";
  119. showformheader('recyclebinpost&operation=search', 'style="display: none;"', 'recyclebinpostform');
  120. showhiddenfields(array('security' => 1, 'searchsubmit' => 1));
  121. showformfooter();
  122. showtableheader('', '', 'id = "security_list"');
  123. showsubtitle(array('security_subject', 'security_forum', 'security_author', 'security_post_status'));
  124. foreach($datas as $key => $value) {
  125. if(!$value['message']) {
  126. $subjectstyle = 'class = "threadopt"';
  127. } else {
  128. $subjectstyle = '';
  129. }
  130. $value['message'] = convertMessage($value);
  131. $modthreadkey = modauthkey($value['tid']);
  132. $thread = array(convertSubjectandIP($value), getNamebyFid($value['fid']), convertAuthorAndDate($value), //convertIdtoStr($value['eviltype']),
  133. convertIdtoStr($value['invisible'], 'adminoperate'), $viewlink);
  134. showtagheader('tbody', '', true, 'hover');
  135. showtablerow($subjectstyle,array('width = "400px"'), $thread);
  136. $value['message'] ? showtablerow('class="threadopt" style="display: none;" id = "mod_'.$value['tid'].'_row_'.$key.'"', 'colspan = "6"', $value['message']) : '';
  137. showtagfooter('tbody');
  138. }
  139. if ($multipage) {
  140. showtablerow('', 'colspan = "6"', $multipage);
  141. }
  142. showtablefooter();
  143. } elseif($_GET['anchor'] == 'member') {
  144. showtips('security_member_tips');
  145. if($_GET['ignoreuid']) {
  146. C::t('#security#security_eviluser')->delete(intval($_GET['ignoreuid']));
  147. }
  148. $memberperpage = $_G['setting']['memberperpage'];
  149. $start_limit = ($page - 1) * $memberperpage;
  150. $count = C::t('#security#security_eviluser')->count();
  151. $multipage = multi($count, $memberperpage, $page, ADMINSCRIPT.'?action=cloud&operation=security&anchor=member');
  152. list($datas, $eviluids) = getEvilList('user', $start_limit, $memberperpage);
  153. showformheader('recyclebinpost&operation=search', 'style="display: none;"', 'recyclebinmember');
  154. showhiddenfields(array('security' => 1, 'searchsubmit' => 1));
  155. echo "\n<input type=\"hidden\" name=\"authors\" id=\"authors\" value=\"\">";
  156. showformfooter();
  157. showformheader("members&operation=clean", '');
  158. showtableheader();
  159. showsubtitle(array('','security_members_name', 'members_edit_info', 'security_thread_member_group', 'security_createtime', '', '', ''));
  160. foreach($datas as $value) {
  161. if ($value['username']) {
  162. $username = '<a href="home.php?mod=space&uid='.$value['uid'].'&do=profile" target="_blank" title="'.$title.'">'.$value['username'].'</a>';
  163. } else {
  164. $username = $lang['security_userdeleted']."(uid:{$value['uid']})";
  165. }
  166. $del = '<input type="checkbox" name="uidarray[]" value="'.$value['uid'].'"'.($value['adminid'] == 1 ? 'disabled' : '').' class="checkbox">';
  167. $optmember = '<a href="'.ADMINSCRIPT.'?action=members&operation=ban&uid='.$value['uid'].'" target="_blank">'.cplang('members_ban').'</a>';
  168. $ignorethis = '<a href="'.ADMINSCRIPT.'?action=cloud&operation=security&anchor=member&ignoreuid='.$value['uid'].'&page='.$page.'">'.cplang('security_member_ignore_this').'</a>';
  169. $createtime = date('Y-m-d', $value['createtime']);
  170. $evilthreads = '<a href="javascript:void(0);" onclick="searchevilpost_member(\''.$value['username'].'\', 1);return false;">'.cplang('security_thread_list').'</a>';
  171. $evilposts = '<a href="javascript:void(0);" onclick="searchevilpost_member(\''.$value['username'].'\', 2);return false;">'.cplang('security_post_list').'</a>';
  172. $member = array($del, $username, convertMemberInfo($value), $value['grouptitle'], $createtime, $evilthreads, $evilposts, $optmember, $ignorethis);
  173. showtablerow('',array('class="td25"'),$member);
  174. }
  175. showsubmit('deletesubmit', cplang('delete'), '', '', $multipage);
  176. showtablefooter();
  177. showformfooter();
  178. } elseif($_GET['anchor'] == 'reopen') {
  179. Cloud::loadFile('Service_Client_Cloud');
  180. $Cloud_Service_Client_Cloud = new Cloud_Service_Client_Cloud;
  181. $return = $Cloud_Service_Client_Cloud->appOpenWithRegister('security');
  182. if($return['errCode']) {
  183. cpmsg($return['errMessage'], 'action=cloud&operation=security&anchor=index', 'error');
  184. } else {
  185. dheader('location: '.ADMINSCRIPT.'?action=cloud&operation=security&anchor=index');
  186. }
  187. }
  188. echo "
  189. <script type='text/javascript'>
  190. function searchevilpost_member(username, type) {
  191. $('recyclebinmember').action= '".ADMINSCRIPT."?'+(type == 1 ? 'action=recyclebin&operation=search' : 'action=recyclebinpost&operation=search');
  192. $('authors').value=username;
  193. $('recyclebinmember').submit();
  194. return false;
  195. }
  196. </script>";
  197. $jsScript = <<<EOF
  198. <script type='text/javascript'>
  199. function toggle_mod(id) {
  200. if($(id).style.display == 'none') {
  201. $(id).style.display = '';
  202. } else {
  203. $(id).style.display = 'none';
  204. }
  205. return false;
  206. }
  207. function security_foldall() {
  208. var trs = $('security_list').getElementsByTagName('TR');
  209. for(var i in trs) {
  210. if(trs[i].id && trs[i].id.match(/mod_(\d+)_row_(\d+)/) != null) {
  211. trs[i].style.display = "none";
  212. }
  213. }
  214. }
  215. function security_exfoldall() {
  216. var trs = $('security_list').getElementsByTagName('TR');
  217. for(var i in trs) {
  218. if(trs[i].id && trs[i].id.match(/mod_(\d+)_row_(\d+)/) != null) {
  219. trs[i].style.display = "";
  220. }
  221. }
  222. }
  223. </script>
  224. EOF;
  225. echo $jsScript;
  226. function convertIdtoStr($id, $type = 'security_type', $subtype = 'thread') {
  227. global $lang;
  228. if ($type == 'security_type') {
  229. $id = min(6, $id);
  230. $result = $lang['security_type_'.$id];
  231. } elseif($type == 'checkreported') {
  232. $result = $id ? $lang['security_isreported_yes'] : $lang['security_isreported_no'];
  233. } elseif($type == 'adminoperate') {
  234. if ($id === null) {
  235. return $lang['security_opreateresult_2'];
  236. }
  237. if (in_array($subtype, array('thread', 'post'))) {
  238. global $operateresultmap;
  239. $result = $lang['security_opreateresult_'.$operateresultmap[$id]];
  240. } elseif ($subtype == 'member') {
  241. global $nooperategroup;
  242. if (in_array($id, $nooperategroup)) {
  243. $result = $lang['security_opreateresult_0'];
  244. } else {
  245. $result = $lang['security_opreateresult_1'];
  246. }
  247. }
  248. }
  249. return $result;
  250. }
  251. function convertMemberInfo($value) {
  252. global $lang;
  253. $result = '';
  254. if ($value['username']) {
  255. $result = $lang['members_edit_regdate'] . ': ' . dgmdate($value['regdate']) . '<br/>';
  256. $result .= $lang['members_edit_regip'] . ': ' . $value['regip'] . ' ' . convertip($value['regip']) . '<br/>';
  257. $result .= 'Email: ' . $value['email'];
  258. } else {
  259. $result = '<p style="margin:14px 0;">' . $lang['security_userdeleted'] . '</p>';
  260. }
  261. return $result;
  262. }
  263. function convertOperate($id = 0) {
  264. $ids = array('1' => 'delete',
  265. '2' => 'restore');
  266. if (!$ids[$id]) {
  267. return false;
  268. }
  269. return $ids[$id];
  270. }
  271. function getEvilList($type, $start, $ppp) {
  272. $datas = $data = array();
  273. $evilids = array();
  274. if ($type == 'member') {
  275. $type = 'user';
  276. }
  277. if ($type == 'user') {
  278. $query = C::t('#security#security_eviluser')->fetch_range($start, $ppp);
  279. $idtype = 'uid';
  280. } elseif($type == 'thread') {
  281. $query = C::t('#security#security_evilpost')->fetch_range_by_type('1', $start, $ppp);
  282. $idtype = 'pid';
  283. } elseif($type == 'post') {
  284. $query = C::t('#security#security_evilpost')->fetch_range_by_type('0', $start, $ppp);
  285. $idtype = 'pid';
  286. }
  287. foreach ($query as $data) {
  288. $datas[$data[$idtype]] = $data;
  289. $evilids[] = $data[$idtype];
  290. if ($data['tid']) {
  291. $evilTids[] = $data['tid'];
  292. $threadPid[$data['tid']][] = $data['pid'];
  293. }
  294. }
  295. if (is_array($evilTids)) {
  296. $evilTids = array_unique($evilTids);
  297. }
  298. if (!$evilids) {
  299. return false;
  300. }
  301. if ($type == 'user') {
  302. $usergroups = array();
  303. foreach (C::t('common_usergroup')->range() as $group) {
  304. $usergroups[$group['groupid']] = $group['grouptitle'];
  305. }
  306. $regips = C::t('common_member_status')->fetch_all($evilids);
  307. $query = C::t('common_member')->fetch_all($evilids);
  308. foreach ($query as $key => $user) {
  309. if(!empty($user) && !in_array($user['groupid'], array(4,5,6))) {
  310. $query[$key]['regip'] = $regips[$key]['regip'];
  311. }
  312. }
  313. if(count($evilids) != count($query)) {
  314. $deleviluids = array();
  315. foreach($evilids as $key => $eviluid) {
  316. if(empty($query[$eviluid])) {
  317. $deleviluids[] = $eviluid;
  318. unset($evilids[$key]);
  319. }
  320. }
  321. C::t('#security#security_eviluser')->delete($deleviluids);
  322. }
  323. } elseif($type == 'thread' || $type == 'post') {
  324. $query = C::t('forum_thread')->fetch_all_by_tid($evilTids);
  325. }
  326. foreach ($query as $data) {
  327. if ($type == 'thread' || $type == 'post') {
  328. foreach($threadPid[$data['tid']] as $pid) {
  329. $isFirst = ($type == 'thread') ? 1 : 0;
  330. $postData = C::t('forum_post')->fetch($data['posttableid'], $pid);
  331. if ($postData['pid']) {
  332. $datas[$postData['pid']] = array_merge($datas[$postData['pid']], $postData);
  333. if ($type == 'post') {
  334. $datas[$postData['pid']]['subject'] = $data['subject'];
  335. }
  336. }
  337. }
  338. } else {
  339. $data['grouptitle'] = $usergroups[$data['groupid']];
  340. $datas[$data[$idtype]] = array_merge($datas[$data[$idtype]], $data);
  341. }
  342. }
  343. return array($datas, $evilids);
  344. }
  345. function getNamebyFid($fid) {
  346. global $_G;
  347. if (!$fid) {
  348. return false;
  349. }
  350. $forumInfo = C::t('forum_forum')->fetch_all_name_by_fid($fid);
  351. $name = $forumInfo[$fid]['name'];
  352. $name = "<a href='forum.php?mod=forumdisplay&fid=$fid' target='_blank'>".$name."</a>";
  353. return $name;
  354. }
  355. function convertSubjectandIP($value, $viewlink = '') {
  356. global $lang;
  357. if ($viewlink) {
  358. $result = '<h3>'.$viewlink.'</h3>';
  359. } else {
  360. $result = '<h3><a title="'.$lang['security_clicktotoggle'].'" href="javascript:;" onclick="return toggle_mod(\'mod_'.$value['tid'].'_row_'.$value['pid'].'\');" target="_blank">'.$value['subject'].'</a></h3>';
  361. }
  362. $result .= '<p>'.$value['useip'].' '.convertip($value['useip']).' ( pid : '.$value['pid'].' ) </p>';
  363. if (!$value['message']) {
  364. return $lang['security_postdeleted']."(tid:{$value['tid']} pid:{$value['pid']})";
  365. }
  366. return $result;
  367. }
  368. function convertMessage($value) {
  369. global $lang;
  370. if (!$value['message']) {
  371. return false;
  372. }
  373. $value['message'] = discuzcode($value['message'], 0, 0, sprintf('%00b', $value['htmlon']), 1, 1, 1, 0);
  374. $value['message'] = '<div style="overflow: auto; overflow-x: hidden; max-height:120px; height:auto !important; height:100px; word-break: break-all;">'.$value['message'].'</div>';
  375. return $value['message'];
  376. }
  377. function convertAuthorAndDate($value) {
  378. if (!$value['author']) {
  379. return false;
  380. }
  381. $result = "<a href='home.php?mod=space&uid={$value[authorid]}&do=profile' target='_blank'>" . $value['author'] . "</a>" . '<p>';
  382. $result .= dgmdate($value['dateline']);
  383. $result .= '</a>';
  384. return $result;
  385. }
  386. function getDataToReport($operateType, $datatosync, $datas) {
  387. $datatoreport = array();
  388. foreach($datatosync as $operateresult => $ids) {
  389. foreach($ids as $id) {
  390. if(!$datas[$id]['isreported']) {
  391. $data = array(
  392. 'operateType' => $operateType,
  393. 'operate' => $operateresult == 'validate' ? 'restore' : 'delete',
  394. 'operateId' => $id,
  395. 'uid' => $datas[$id]['authorid'] ? $datas[$id]['authorid'] : $datas[$id]['uid'],
  396. );
  397. $data['openId'] = getOpenId($data['uid']);
  398. $data['clientIp'] = $datas[$id]['userip'] ? $datas[$id]['userip'] : getMemberIp($data['uid']);
  399. if ($operateType != 'member') {
  400. $data['tid'] = $datas[$id]['tid'];
  401. $data['pid'] = $datas[$id]['pid'];
  402. $data['fid'] = $datas[$id]['fid'];
  403. }
  404. array_push($datatoreport, $data);
  405. }
  406. }
  407. }
  408. return $datatoreport;
  409. }