国内流行的内容管理系统(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.

454 lines
9.6KB

  1. <?php
  2. if (!defined('DEDEINC')) exit('dedebiz');
  3. //允许的函数
  4. $GLOBALS['allowedCalls'] = array(
  5. //系统
  6. 'var_dump',
  7. //数学
  8. 'ceil',
  9. 'floor',
  10. 'fmod',
  11. 'log',
  12. 'mt_rand',
  13. 'mt_srand',
  14. 'pow',
  15. 'rand',
  16. 'sqrt',
  17. 'srand',
  18. //变量
  19. 'empty',
  20. 'floatval',
  21. 'intval',
  22. 'is_array',
  23. 'is_binary',
  24. 'is_bool',
  25. 'is_double',
  26. 'is_float',
  27. 'is_int',
  28. 'is_integer',
  29. 'is_long',
  30. 'is_null',
  31. 'is_numeric',
  32. 'is_real',
  33. 'is_scalar',
  34. 'is_string',
  35. 'is_unicode',
  36. 'isset',
  37. 'strval',
  38. 'unset',
  39. //数组
  40. 'array_change_key_case',
  41. 'array_chunk',
  42. 'array_combine',
  43. 'array_count_values',
  44. 'array_diff_assoc',
  45. 'array_diff_key',
  46. 'array_diff',
  47. 'array_fill_keys',
  48. 'array_fill',
  49. 'array_flip',
  50. 'array_intersect_assoc',
  51. 'array_intersect_key',
  52. 'array_intersect',
  53. 'array_key_exists',
  54. 'array_keys',
  55. 'array_merge_recursive',
  56. 'array_merge',
  57. 'array_multisort',
  58. 'array_pad',
  59. 'array_pop',
  60. 'array_product',
  61. 'array_push',
  62. 'array_rand',
  63. 'array_reverse',
  64. 'array_search',
  65. 'array_shift',
  66. 'array_slice',
  67. 'array_splice',
  68. 'array_sum',
  69. 'array_unique',
  70. 'array_unshift',
  71. 'array_values',
  72. 'array',
  73. 'arsort',
  74. 'asort',
  75. 'compact',
  76. 'count',
  77. 'current',
  78. 'each',
  79. 'end',
  80. 'in_array',
  81. 'key',
  82. 'krsort',
  83. 'ksort',
  84. 'natcasesort',
  85. 'natsort',
  86. 'next',
  87. 'pos',
  88. 'prev',
  89. 'range',
  90. 'reset',
  91. 'rsort',
  92. 'shuffle',
  93. 'sizeof',
  94. 'sort',
  95. //字符串
  96. 'json_encode',
  97. 'json_decode',
  98. 'json_last_error',
  99. 'json_last_error_msg',
  100. 'base64_decode',
  101. 'base64_encode',
  102. 'urlencode',
  103. 'urldecode',
  104. 'parse_url',
  105. 'addslashes',
  106. 'addcslashes',
  107. 'chop',
  108. 'count_chars',
  109. 'explode',
  110. 'implode',
  111. 'join',
  112. 'levenshtein',
  113. 'ltrim',
  114. 'metaphone',
  115. 'money_format',
  116. 'number_format',
  117. 'rtrim',
  118. 'similar_text',
  119. 'soundex',
  120. 'str_getcsv',
  121. 'str_ireplace',
  122. 'str_pad',
  123. 'str_repeat',
  124. 'str_replace',
  125. 'str_rot13',
  126. 'str_shuffle',
  127. 'str_split',
  128. 'str_word_count',
  129. 'strcasecmp',
  130. 'strchr',
  131. 'strcmp',
  132. 'strcspn',
  133. 'stripos',
  134. 'stristr',
  135. 'strlen',
  136. 'strnatcasecmp',
  137. 'strnatcmp',
  138. 'strncasecmp',
  139. 'strncmp',
  140. 'strpbrk',
  141. 'strpos',
  142. 'strrchr',
  143. 'strrev',
  144. 'strripos',
  145. 'strrpos',
  146. 'strspn',
  147. 'strstr',
  148. 'strtolower',
  149. 'strtoupper',
  150. 'strtr',
  151. 'substr_compare',
  152. 'substr_count',
  153. 'substr_replace',
  154. 'substr',
  155. 'trim',
  156. 'ucfirst',
  157. 'ucwords',
  158. 'wordwrap',
  159. //dede内置
  160. 'html2text',
  161. 'removexss',
  162. 'htmlreplace',
  163. 'getmktime',
  164. 'getpinyin',
  165. 'cn_substr',
  166. 'cn_substrr',
  167. 'mydate',
  168. 'subday',
  169. 'addday',
  170. 'getdatetimemk',
  171. 'getdatemk',
  172. 'floortime',
  173. 'getcururl',
  174. 'utf82gb',
  175. 'gb2utf8',
  176. 'u2utf8',
  177. 'utf82u',
  178. 'big52gb',
  179. 'gb2big5',
  180. 'litimgurls',
  181. 'split',
  182. //时间
  183. 'strtotime',
  184. 'date',
  185. 'idate',
  186. 'gmdate',
  187. 'mktime',
  188. 'gmmktime',
  189. 'checkdate',
  190. 'strftime',
  191. 'gmstrftime',
  192. 'time',
  193. 'localtime',
  194. 'getdate',
  195. 'date_create',
  196. 'date_create_immutable',
  197. 'date_create_from_format',
  198. 'date_create_immutable_from_format',
  199. 'date_parse',
  200. 'date_parse_from_format',
  201. 'date_get_last_errors',
  202. 'date_format',
  203. 'date_modify',
  204. 'date_add',
  205. 'date_sub',
  206. 'date_timezone_get',
  207. 'date_timezone_set',
  208. 'date_offset_get',
  209. 'date_diff',
  210. 'date_time_set',
  211. 'date_date_set',
  212. 'date_isodate_set',
  213. 'date_timestamp_set',
  214. 'date_timestamp_get',
  215. 'timezone_open',
  216. 'timezone_name_get',
  217. 'timezone_name_from_abbr',
  218. 'timezone_offset_get',
  219. 'timezone_transitions_get',
  220. 'timezone_location_get',
  221. 'timezone_identifiers_list',
  222. 'timezone_abbreviations_list',
  223. 'timezone_version_get',
  224. 'date_interval_create_from_date_string',
  225. 'date_interval_format',
  226. 'date_default_timezone_set',
  227. 'date_default_timezone_get',
  228. 'date_sunrise',
  229. 'date_sunset',
  230. 'date_sun_info',
  231. //mb字符串处理
  232. 'mb_convert_case',
  233. 'mb_strtoupper',
  234. 'mb_strtolower',
  235. 'mb_language',
  236. 'mb_internal_encoding',
  237. 'mb_http_input',
  238. 'mb_http_output',
  239. 'mb_detect_order',
  240. 'mb_substitute_character',
  241. 'mb_parse_str',
  242. 'mb_output_handler',
  243. 'mb_preferred_mime_name',
  244. 'mb_strlen',
  245. 'mb_strpos',
  246. 'mb_strrpos',
  247. 'mb_stripos',
  248. 'mb_strripos',
  249. 'mb_strstr',
  250. 'mb_strrchr',
  251. 'mb_stristr',
  252. 'mb_strrichr',
  253. 'mb_substr_count',
  254. 'mb_substr',
  255. 'mb_strcut',
  256. 'mb_strwidth',
  257. 'mb_strimwidth',
  258. 'mb_convert_encoding',
  259. 'mb_detect_encoding',
  260. 'mb_list_encodings',
  261. 'mb_encoding_aliases',
  262. 'mb_convert_kana',
  263. 'mb_encode_mimeheader',
  264. 'mb_decode_mimeheader',
  265. 'mb_convert_variables',
  266. 'mb_encode_numericentity',
  267. 'mb_decode_numericentity',
  268. 'mb_send_mail',
  269. 'mb_get_info',
  270. 'mb_check_encoding',
  271. 'mb_ord',
  272. 'mb_chr',
  273. 'mb_scrub',
  274. 'mb_regex_encoding',
  275. 'mb_regex_set_options',
  276. 'mb_ereg',
  277. 'mb_eregi',
  278. 'mb_ereg_replace',
  279. 'mb_eregi_replace',
  280. 'mb_ereg_replace_callback',
  281. 'mb_split',
  282. 'mb_ereg_match',
  283. 'mb_ereg_search',
  284. 'mb_ereg_search_pos',
  285. 'mb_ereg_search_regs',
  286. 'mb_ereg_search_init',
  287. 'mb_ereg_search_getregs',
  288. 'mb_ereg_search_getpos',
  289. 'mb_ereg_search_setpos',
  290. );
  291. //允许的语法
  292. $GLOBALS['allowedTokens'] = array(
  293. 'T_AND_EQUAL',
  294. 'T_ARRAY',
  295. 'T_ARRAY_CAST',
  296. 'T_AS',
  297. 'T_BOOLEAN_AND',
  298. 'T_BOOLEAN_OR',
  299. 'T_BOOL_CAST',
  300. 'T_BREAK',
  301. 'T_CASE',
  302. 'T_CHARACTER',
  303. 'T_CONCAT_EQUAL',
  304. 'T_CONSTANT_ENCAPSED_STRING',
  305. 'T_CONTINUE',
  306. 'T_CURLY_OPEN',
  307. 'T_DEC',
  308. 'T_DECLARE',
  309. 'T_DEFAULT',
  310. 'T_DIV_EQUAL',
  311. 'T_DNUMBER',
  312. 'T_DO',
  313. 'T_DOUBLE_ARROW',
  314. 'T_DOUBLE_CAST',
  315. 'T_ELSE',
  316. 'T_ELSEIF',
  317. 'T_EMPTY',
  318. 'T_ENCAPSED_AND_WHITESPACE',
  319. 'T_ENDDECLARE',
  320. 'T_ENDFOR',
  321. 'T_ENDFOREACH',
  322. 'T_ENDIF',
  323. 'T_ENDSWITCH',
  324. 'T_FOR',
  325. 'T_FOREACH',
  326. 'T_IF',
  327. 'T_INC',
  328. 'T_INT_CAST',
  329. 'T_ISSET',
  330. 'T_IS_EQUAL',
  331. 'T_IS_GREATER_OR_EQUAL',
  332. 'T_IS_IDENTICAL',
  333. 'T_IS_NOT_EQUAL',
  334. 'T_IS_NOT_IDENTICAL',
  335. 'T_IS_SMALLER_OR_EQUAL',
  336. 'T_LNUMBER',
  337. 'T_LOGICAL_AND',
  338. 'T_LOGICAL_OR',
  339. 'T_LOGICAL_XOR',
  340. 'T_MINUS_EQUAL',
  341. 'T_MOD_EQUAL',
  342. 'T_MUL_EQUAL',
  343. 'T_NUM_STRING',
  344. 'T_OR_EQUAL',
  345. 'T_PLUS_EQUAL',
  346. 'T_RETURN',
  347. 'T_SL',
  348. 'T_SL_EQUAL',
  349. 'T_SR',
  350. 'T_SR_EQUAL',
  351. 'T_STRING',
  352. 'T_STRING_CAST',
  353. 'T_STRING_VARNAME',
  354. 'T_SWITCH',
  355. 'T_UNSET',
  356. 'T_UNSET_CAST',
  357. 'T_VARIABLE',
  358. 'T_WHILE',
  359. 'T_WHITESPACE',
  360. 'T_XOR_EQUAL',
  361. );
  362. //禁止的表达式
  363. $GLOBALS['disallowedExpressions'] = array(
  364. '/`/',
  365. '/\$\W/',
  366. '/(\]|\})\s*\(/',
  367. '/\$\w\w*\s*\(/',
  368. );
  369. //执行脚本
  370. function evalCode($code)
  371. {
  372. ob_start();
  373. $code = eval('if (0){'."\n".$code."\n".'}');
  374. ob_end_clean();
  375. return $code !== false;
  376. }
  377. //校验脚本
  378. function checkCode($code)
  379. {
  380. global $allowedCalls, $allowedTokens, $disallowedExpressions;
  381. $tokens = token_get_all('<?php '.$code.' ?>');
  382. $errors = array();
  383. $braces = 0;
  384. foreach ($tokens as $token) {
  385. if ($token == '{') $braces = $braces + 1;
  386. else if ($token == '}') $braces = $braces - 1;
  387. if ($braces < 0) {
  388. $errors[0]['name'] = 'Syntax error.';
  389. break;
  390. }
  391. }
  392. if (empty($errors)) {
  393. if ($braces) $errors[0]['name'] = 'Unbalanced braces.';
  394. } else if (!evalCode($code)) {
  395. $errors[0]['name'] = 'Syntax error.';
  396. }
  397. if (empty($errors)) foreach ($disallowedExpressions as $disallowedExpression) {
  398. unset($matches);
  399. preg_match($disallowedExpression, $code, $matches);
  400. if ($matches) {
  401. $errors[0]['name'] = 'Execution operator / variable function name / variable variable name detected.';
  402. break;
  403. }
  404. }
  405. if (empty($errors)) {
  406. unset($tokens[0]);
  407. unset($tokens[0]);
  408. array_pop($tokens);
  409. array_pop($tokens);
  410. $i = 0;
  411. foreach ($tokens as $key => $token) {
  412. $i++;
  413. if (is_array($token)) {
  414. $id = token_name($token[0]);
  415. switch ($id) {
  416. case ('T_STRING'):
  417. if (in_array(strtolower($token[1]), $allowedCalls) === false) {
  418. $errors[$i]['name'] = 'Illegal function: '.$token[1];
  419. $errors[$i]['line'] = $token[2];
  420. }
  421. break;
  422. default:
  423. if (in_array($id, $allowedTokens) === false) {
  424. $errors[$i]['name'] = 'Illegal token: '.$token[1];
  425. $errors[$i]['line'] = $token[2];
  426. }
  427. break;
  428. }
  429. }
  430. }
  431. }
  432. if (!empty($errors)) {
  433. return $errors;
  434. }
  435. }
  436. //错误提示
  437. function htmlErrors($errors = null)
  438. {
  439. if ($errors) {
  440. $errorsHTML = "<div style='width:98%;margin:1rem auto;color:#842029;background:#f8d7da;border-color:#842029;position:relative;padding:.75rem 1.25rem;border:1px solid transparent;border-radius:.5rem'>";
  441. $errorsHTML .= '内嵌脚本缺失,请添加该函数:';
  442. $errorsHTML .= '<dl>';
  443. foreach ($errors as $error) {
  444. if ($error['line']) {
  445. $errorsHTML .= '<dt>Line '.$error['line'].'</dt>';
  446. }
  447. $errorsHTML .= '<dd>'.$error['name'].'</dd>';
  448. }
  449. $errorsHTML .= '</dl>';
  450. $errorsHTML .= "</div>\r\n";
  451. echo $errorsHTML;
  452. }
  453. }
  454. ?>