function_editor.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  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: function_editor.php 36278 2016-12-09 07:52:35Z nemohou $
  7. */
  8. if(!defined('IN_DISCUZ')) {
  9. exit('Access Denied');
  10. }
  11. function absoluteurl($url) {
  12. global $_G;
  13. if($url{0} == '/') {
  14. return 'http://'.$_SERVER['HTTP_HOST'].$url;
  15. } else {
  16. return $_G['siteurl'].$url;
  17. }
  18. }
  19. function atag($aoptions, $text) {
  20. $href = getoptionvalue('href', $aoptions);
  21. if(substr($href, 0, 7) == 'mailto:') {
  22. $tag = 'email';
  23. $href = substr($href, 7);
  24. } else {
  25. $tag = 'url';
  26. if(!preg_match("/^[a-z0-9]+:/i", $href)) {
  27. $href = absoluteurl($href);
  28. }
  29. }
  30. return "[$tag=$href]".trim(recursion('a', $text, 'atag'))."[/$tag]";
  31. }
  32. function divtag($divoptions, $text) {
  33. $prepend = $append = '';
  34. parsestyle($divoptions, $prepend, $append);
  35. $align = getoptionvalue('align', $divoptions);
  36. switch($align) {
  37. case 'left':
  38. case 'center':
  39. case 'right':
  40. break;
  41. default:
  42. $align = '';
  43. }
  44. if($align) {
  45. $prepend .= "[align=$align]";
  46. $append .= "[/align]";
  47. }
  48. $append .= "\n";
  49. return $prepend.recursion('div', $text, 'divtag').$append;
  50. }
  51. function fetchoptionvalue($option, $text) {
  52. if(($position = strpos($text, $option)) !== false) {
  53. $delimiter = $position + strlen($option);
  54. if($text{$delimiter} == '"') {
  55. $delimchar = '"';
  56. } elseif($text{$delimiter} == '\'') {
  57. $delimchar = '\'';
  58. } else {
  59. $delimchar = ' ';
  60. }
  61. $delimloc = strpos($text, $delimchar, $delimiter + 1);
  62. if($delimloc === false) {
  63. $delimloc = strlen($text);
  64. } elseif($delimchar == '"' OR $delimchar == '\'') {
  65. $delimiter++;
  66. }
  67. return trim(substr($text, $delimiter, $delimloc - $delimiter));
  68. } else {
  69. return '';
  70. }
  71. }
  72. function fonttag($fontoptions, $text) {
  73. $tags = array('font' => 'face=', 'size' => 'size=', 'color' => 'color=');
  74. $prependtags = $appendtags = '';
  75. foreach($tags as $bbcode => $locate) {
  76. $optionvalue = fetchoptionvalue($locate, $fontoptions);
  77. if($optionvalue) {
  78. $prependtags .= "[$bbcode=$optionvalue]";
  79. $appendtags = "[/$bbcode]$appendtags";
  80. }
  81. }
  82. parsestyle($fontoptions, $prependtags, $appendtags);
  83. return $prependtags.recursion('font', $text, 'fonttag').$appendtags;
  84. }
  85. function getoptionvalue($option, $text) {
  86. preg_match("/$option(\s+?)?\=(\s+?)?[\"']?(.+?)([\"']|$|>)/is", $text, $matches);
  87. return isset($matches[3]) ? trim($matches[3]) : '';
  88. }
  89. function html2bbcode($text) {
  90. $text = strip_tags($text, '<table><tr><td><b><strong><i><em><u><a><div><span><p><strike><blockquote><ol><ul><li><font><img><br><br/><h1><h2><h3><h4><h5><h6><script>');
  91. if(ismozilla()) {
  92. $text = preg_replace("/(?<!<br>|<br \/>|\r)(\r\n|\n|\r)/", ' ', $text);
  93. }
  94. $pregfind = array(
  95. "/<script.*>.*<\/script>/siU",
  96. '/on(mousewheel|mouseover|click|load|onload|submit|focus|blur)="[^"]*"/i',
  97. "/(\r\n|\n|\r)/",
  98. "/<table.*>/siU",
  99. "/<tr.*>/siU",
  100. "/<td>/i",
  101. "/<\/td>/i",
  102. "/<\/tr>/i",
  103. "/<\/table>/i",
  104. '/<\/h([0-9]+)>/siU',
  105. "/<a\s+?name=.+?\".\">(.+?)<\/a>/is",
  106. "/<br.*>/siU",
  107. "/<span\s+?style=\"float:\s+(left|right);\">(.+?)<\/span>/is",
  108. );
  109. $pregreplace = array(
  110. '',
  111. '',
  112. '',
  113. '[table]',
  114. '[tr]',
  115. '[td]',
  116. '[/td]',
  117. '[/tr]',
  118. '[/table]',
  119. "[/size]\n\n",
  120. '\1',
  121. "\n",
  122. "[float=\\1]\\2[/float]",
  123. );
  124. $text = preg_replace($pregfind, $pregreplace, $text);
  125. $text = preg_replace_callback("/<table([^>]*(width|background|background-color|bgcolor)[^>]*)>/siU", 'html2bbcode_callback_tabletag_1', $text);
  126. $text = preg_replace_callback("/<td(.+)>/siU", 'html2bbcode_callback_tdtag_1', $text);
  127. $text = preg_replace_callback('/<h([0-9]+)[^>]*>/siU', 'html2bbcode_callback_1', $text);
  128. $text = preg_replace_callback("/<img[^>]+smilieid=\"(\d+)\".*>/siU", 'html2bbcode_callback_smileycode_1', $text);
  129. $text = preg_replace_callback("/<img([^>]*src[^>]*)>/iU", 'html2bbcode_callback_imgtag_1', $text);
  130. $text = recursion('b', $text, 'simpletag', 'b');
  131. $text = recursion('strong', $text, 'simpletag', 'b');
  132. $text = recursion('i', $text, 'simpletag', 'i');
  133. $text = recursion('em', $text, 'simpletag', 'i');
  134. $text = recursion('u', $text, 'simpletag', 'u');
  135. $text = recursion('a', $text, 'atag');
  136. $text = recursion('font', $text, 'fonttag');
  137. $text = recursion('blockquote', $text, 'simpletag', 'indent');
  138. $text = recursion('ol', $text, 'listtag');
  139. $text = recursion('ul', $text, 'listtag');
  140. $text = recursion('div', $text, 'divtag');
  141. $text = recursion('span', $text, 'spantag');
  142. $text = recursion('p', $text, 'ptag');
  143. $pregfind = array("/(?<!\r|\n|^)\[(\/list|list|\*)\]/", "/<li>(.*)((?=<li>)|<\/li>)/iU", "/<p.*>/iU", "/<p><\/p>/i", "/(<a>|<\/a>|<\/li>)/is", "/<\/?(A|LI|FONT|DIV|SPAN)>/siU", "/\[url[^\]]*\]\[\/url\]/i", "/\[url=javascript:[^\]]*\](.+?)\[\/url\]/is");
  144. $pregreplace = array("\n[\\1]", "\\1\n", "\n", '', '', '', '', "\\1");
  145. $text = preg_replace($pregfind, $pregreplace, $text);
  146. $strfind = array('&nbsp;', '&lt;', '&gt;', '&amp;');
  147. $strreplace = array(' ', '<', '>', '&');
  148. $text = str_replace($strfind, $strreplace, $text);
  149. return dhtmlspecialchars(trim($text));
  150. }
  151. function html2bbcode_callback_tabletag_1($matches) {
  152. return tabletag($matches[1]);
  153. }
  154. function html2bbcode_callback_tdtag_1($matches) {
  155. return tdtag($matches[1]);
  156. }
  157. function html2bbcode_callback_1($matches) {
  158. return '[size='.(7 - $matches[1]).']';
  159. }
  160. function html2bbcode_callback_smileycode_1($matches) {
  161. return smileycode($matches[1]);
  162. }
  163. function html2bbcode_callback_imgtag_1($matches) {
  164. return imgtag($matches[1]);
  165. }
  166. function imgtag($attributes) {
  167. $value = array('src' => '', 'width' => '', 'height' => '');
  168. preg_match_all("/(src|width|height)=([\"|\']?)([^\"']+)(\\2)/is", dstripslashes($attributes), $matches);
  169. if(is_array($matches[1])) {
  170. foreach($matches[1] as $key => $attribute) {
  171. $value[strtolower($attribute)] = $matches[3][$key];
  172. }
  173. }
  174. @extract($value);
  175. if(!preg_match("/^http:\/\//i", $src)) {
  176. $src = absoluteurl($src);
  177. }
  178. return $src ? ($width && $height ? '[img='.$width.','.$height.']'.$src.'[/img]' : '[img]'.$src.'[/img]') : '';
  179. }
  180. function ismozilla() {
  181. $useragent = strtolower($_SERVER['HTTP_USER_AGENT']);
  182. if(strpos($useragent, 'gecko') !== FALSE) {
  183. preg_match("/gecko\/(\d+)/", $useragent, $regs);
  184. return $regs[1];
  185. }
  186. return FALSE;
  187. }
  188. function litag($listoptions, $text) {
  189. return '[*]'.rtrim($text);
  190. }
  191. function listtag($listoptions, $text, $tagname) {
  192. require_once libfile('function/post');
  193. $text = preg_replace('/<li>((.(?!<\/li))*)(?=<\/?ol|<\/?ul|<li|\[list|\[\/list)/siU', '<li>\\1</li>', $text).(isopera() ? '</li>' : NULL);
  194. $text = recursion('li', $text, 'litag');
  195. if($tagname == 'ol') {
  196. $listtype = fetchoptionvalue('type=', $listoptions) ? fetchoptionvalue('type=', $listoptions) : 1;
  197. if(in_array($listtype, array('1', 'a', 'A'))) {
  198. $opentag = '[list='.$listtype.']';
  199. }
  200. } else {
  201. $opentag = '[list]';
  202. }
  203. return $text ? $opentag.recursion($tagname, $text, 'listtag').'[/list]' : FALSE;
  204. }
  205. function parsestyle($tagoptions, &$prependtags, &$appendtags) {
  206. $searchlist = array(
  207. array('tag' => 'align', 'option' => TRUE, 'regex' => 'text-align:\s*(left);?', 'match' => 1),
  208. array('tag' => 'align', 'option' => TRUE, 'regex' => 'text-align:\s*(center);?', 'match' => 1),
  209. array('tag' => 'align', 'option' => TRUE, 'regex' => 'text-align:\s*(right);?', 'match' => 1),
  210. array('tag' => 'color', 'option' => TRUE, 'regex' => '(?<![a-z0-9-])color:\s*([^;]+);?', 'match' => 1),
  211. array('tag' => 'font', 'option' => TRUE, 'regex' => 'font-family:\s*([^;]+);?', 'match' => 1),
  212. array('tag' => 'size', 'option' => TRUE, 'regex' => 'font-size:\s*(\d+(\.\d+)?(px|pt|in|cm|mm|pc|em|ex|%|));?', 'match' => 1),
  213. array('tag' => 'b', 'option' => FALSE, 'regex' => 'font-weight:\s*(bold);?'),
  214. array('tag' => 'i', 'option' => FALSE, 'regex' => 'font-style:\s*(italic);?'),
  215. array('tag' => 'u', 'option' => FALSE, 'regex' => 'text-decoration:\s*(underline);?')
  216. );
  217. $style = getoptionvalue('style', $tagoptions);
  218. $style = preg_replace_callback("/(?<![a-z0-9-])color:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)(;?)/i", 'parsestyle_callback_sprintf_4123', $style);
  219. foreach($searchlist as $searchtag) {
  220. if(preg_match('/'.$searchtag['regex'].'/i', $style, $match)) {
  221. $opnvalue = $match["$searchtag[match]"];
  222. $prependtags .= '['.$searchtag['tag'].($searchtag['option'] == TRUE ? '='.$opnvalue.']' : ']');
  223. $appendtags = '[/'.$searchtag['tag']."]$appendtags";
  224. }
  225. }
  226. }
  227. function parsestyle_callback_sprintf_4123($matches) {
  228. return sprintf("color: #%02X%02X%02X".$matches[4], $matches[1], $matches[2], $matches[3]);
  229. }
  230. function ptag($poptions, $text) {
  231. $align = getoptionvalue('align', $poptions);
  232. switch($align) {
  233. case 'left':
  234. case 'center':
  235. case 'right':
  236. break;
  237. default:
  238. $align = '';
  239. }
  240. $prepend = $append = '';
  241. parsestyle($poptions, $prepend, $append);
  242. if($align) {
  243. $prepend .= "[align=$align]";
  244. $append .= "[/align]";
  245. }
  246. $append .= "\n";
  247. return $prepend.recursion('p', $text, 'ptag').$append;
  248. }
  249. function recursion($tagname, $text, $function, $extraargs = '') {
  250. $tagname = strtolower($tagname);
  251. $open_tag = "<$tagname";
  252. $open_tag_len = strlen($open_tag);
  253. $close_tag = "</$tagname>";
  254. $close_tag_len = strlen($close_tag);
  255. $beginsearchpos = 0;
  256. do {
  257. $textlower = strtolower($text);
  258. $tagbegin = @strpos($textlower, $open_tag, $beginsearchpos);
  259. if($tagbegin === FALSE) {
  260. break;
  261. }
  262. $strlen = strlen($text);
  263. $inquote = '';
  264. $found = FALSE;
  265. $tagnameend = FALSE;
  266. for($optionend = $tagbegin; $optionend <= $strlen; $optionend++) {
  267. $char = $text{$optionend};
  268. if(($char == '"' || $char == "'") && $inquote == '') {
  269. $inquote = $char;
  270. } elseif(($char == '"' || $char == "'") && $inquote == $char) {
  271. $inquote = '';
  272. } elseif($char == '>' && !$inquote) {
  273. $found = TRUE;
  274. break;
  275. } elseif(($char == '=' || $char == ' ') && !$tagnameend) {
  276. $tagnameend = $optionend;
  277. }
  278. }
  279. if(!$found) {
  280. break;
  281. }
  282. if(!$tagnameend) {
  283. $tagnameend = $optionend;
  284. }
  285. $offset = $optionend - ($tagbegin + $open_tag_len);
  286. $tagoptions = substr($text, $tagbegin + $open_tag_len, $offset);
  287. $acttagname = substr($textlower, $tagbegin + 1, $tagnameend - $tagbegin - 1);
  288. if($acttagname != $tagname) {
  289. $beginsearchpos = $optionend;
  290. continue;
  291. }
  292. $tagend = strpos($textlower, $close_tag, $optionend);
  293. if($tagend === FALSE) {
  294. break;
  295. }
  296. $nestedopenpos = strpos($textlower, $open_tag, $optionend);
  297. while($nestedopenpos !== FALSE && $tagend !== FALSE) {
  298. if($nestedopenpos > $tagend) {
  299. break;
  300. }
  301. $tagend = strpos($textlower, $close_tag, $tagend + $close_tag_len);
  302. $nestedopenpos = strpos($textlower, $open_tag, $nestedopenpos + $open_tag_len);
  303. }
  304. if($tagend === FALSE) {
  305. $beginsearchpos = $optionend;
  306. continue;
  307. }
  308. $localbegin = $optionend + 1;
  309. $localtext = $function($tagoptions, substr($text, $localbegin, $tagend - $localbegin), $tagname, $extraargs);
  310. $text = substr_replace($text, $localtext, $tagbegin, $tagend + $close_tag_len - $tagbegin);
  311. $beginsearchpos = $tagbegin + strlen($localtext);
  312. } while($tagbegin !== FALSE);
  313. return $text;
  314. }
  315. function simpletag($options, $text, $tagname, $parseto) {
  316. if(trim($text) == '') {
  317. return '';
  318. }
  319. $text = recursion($tagname, $text, 'simpletag', $parseto);
  320. return "[$parseto]{$text}[/$parseto]";
  321. }
  322. function smileycode($smileyid) {
  323. global $_G;
  324. if(!is_array($_G['cache']['smileycodes'])) {
  325. loadcache(array('bbcodes_display', 'bbcodes', 'smileycodes', 'smilies', 'smileytypes', 'domainwhitelist'));
  326. }
  327. foreach($_G['cache']['smileycodes'] as $id => $code) {
  328. if($smileyid == $id) {
  329. return $code;
  330. }
  331. }
  332. }
  333. function spantag($spanoptions, $text) {
  334. $prependtags = $appendtags = '';
  335. parsestyle($spanoptions, $prependtags, $appendtags);
  336. return $prependtags.recursion('span', $text, 'spantag').$appendtags;
  337. }
  338. function tabletag($attributes) {
  339. $attributes = dstripslashes($attributes);
  340. $width = '';
  341. if(preg_match("/width=([\"|\']?)(\d{1,4}%?)(\\1)/is", $attributes, $matches)) {
  342. $width = substr($matches[2], -1) == '%' ? (substr($matches[2], 0, -1) <= 98 ? $matches[2] : '98%') : ($matches[2] <= 560 ? $matches[2] : '560');
  343. } elseif(preg_match("/width\s?:\s?(\d{1,4})([px|%])/is", $attributes, $matches)) {
  344. $width = $matches[2] == '%' ? ($matches[1] <= 98 ? $matches[1].'%' : '98%') : ($matches[1] <= 560 ? $matches[1] : '560');
  345. }
  346. if(preg_match("/(?:background|background-color|bgcolor)[:=]\s*([\"']?)((rgb\(\d{1,3}%?,\s*\d{1,3}%?,\s*\d{1,3}%?\))|(#[0-9a-fA-F]{3,6})|([a-zA-Z]{1,20}))(\\1)/i", $attributes, $matches)) {
  347. $bgcolor = $matches[2];
  348. $width = $width ? $width : '98%';
  349. } else {
  350. $bgcolor = '';
  351. }
  352. return $bgcolor ? "[table=$width,$bgcolor]" :($width ? "[table=$width]" : '[table]');
  353. }
  354. function tdtag($attributes) {
  355. $value = array('colspan' => 1, 'rowspan' => 1, 'width' => '');
  356. preg_match_all("/(colspan|rowspan|width)=([\"|\']?)(\d{1,4}%?)(\\2)/is", dstripslashes($attributes), $matches);
  357. if(is_array($matches[1])) {
  358. foreach($matches[1] as $key => $attribute) {
  359. $value[strtolower($attribute)] = $matches[3][$key];
  360. }
  361. }
  362. @extract($value);
  363. return $width == '' ? ($colspan == 1 && $rowspan == 1 ? '[td]' : "[td=$colspan,$rowspan]") : "[td=$colspan,$rowspan,$width]";
  364. }
  365. ?>