PageRenderTime 114ms CodeModel.GetById 2ms RepoModel.GetById 1ms app.codeStats 1ms

/includes/bbcode.php

http://github.com/MightyGorgon/icy_phoenix
PHP | 4718 lines | 3684 code | 297 blank | 737 comment | 680 complexity | 442916b2d1bda1372e286b299bbb16db MD5 | raw file
Possible License(s): AGPL-1.0
  1. <?php
  2. /**
  3. *
  4. * @package Icy Phoenix
  5. * @version $Id$
  6. * @copyright (c) 2008 Icy Phoenix
  7. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  8. *
  9. */
  10. /**
  11. *
  12. * @Extra credits for this file
  13. * Vjacheslav Trushkin (http://www.stsoftware.biz)
  14. *
  15. */
  16. if (!defined('IN_ICYPHOENIX'))
  17. {
  18. die('Hacking attempt');
  19. }
  20. /*
  21. =================
  22. Includes
  23. =================
  24. include_once(IP_ROOT_PATH . 'includes/bbcode.' . PHP_EXT);
  25. =================
  26. Globals
  27. =================
  28. global $bbcode;
  29. =================
  30. BBCode Parsing
  31. =================
  32. $text = $bbcode->parse($text);
  33. =================
  34. BBCode Conditions
  35. =================
  36. $bbcode->allow_html = ($user->data['user_allowhtml'] && $config['allow_html']) ? true : false;
  37. $bbcode->allow_bbcode = ($user->data['user_allowbbcode'] && $config['allow_bbcode']) ? true : false;
  38. $bbcode->allow_smilies = ($user->data['user_allowsmile'] && $config['allow_smilies']) ? true : false;
  39. =================
  40. $html_on = ($user->data['user_allowhtml'] && $config['allow_html']) ? 1 : 0 ;
  41. $bbcode_on = ($user->data['user_allowbbcode'] && $config['allow_bbcode']) ? 1 : 0 ;
  42. $smilies_on = ($user->data['user_allowsmile'] && $config['allow_smilies']) ? 1 : 0 ;
  43. $bbcode->allow_html = $html_on;
  44. $bbcode->allow_bbcode = $bbcode_on;
  45. $bbcode->allow_smilies = $smilies_on;
  46. =================
  47. $bbcode->allow_html = ($config['allow_html'] ? true : false);
  48. $bbcode->allow_bbcode = ($config['allow_bbcode'] ? true : false);
  49. $bbcode->allow_smilies = ($config['allow_smilies'] ? true : false);
  50. =================
  51. $bbcode->allow_html = (($config['allow_html'] && $row['enable_bbcode']) ? true : false);
  52. $bbcode->allow_bbcode = (($config['allow_bbcode'] && $row['enable_bbcode']) ? true : false);
  53. $bbcode->allow_smilies = (($config['allow_smilies'] && $row['enable_smilies']) ? true : false);
  54. =================
  55. $bbcode->allow_html = ($config['allow_html'] && $postrow[$i]['enable_bbcode'] ? true : false);
  56. $bbcode->allow_bbcode = ($config['allow_bbcode'] && $postrow[$i]['enable_bbcode'] ? true : false);
  57. $bbcode->allow_smilies = ($config['allow_smilies'] && $postrow[$i]['enable_smilies'] ? true : false);
  58. =================
  59. =================================
  60. Acronyms, Autolinks
  61. =================================
  62. $text = $bbcode->acronym_pass($text);
  63. $text = $bbcode->autolink_text($text, $forum_id);
  64. ====================
  65. */
  66. // If included via function we need to make sure to have the requested globals...
  67. global $db, $cache, $config, $lang;
  68. // To use this file outside Icy Phoenix you need to comment the define below and remove the check on top of the file.
  69. define('IS_ICYPHOENIX', true);
  70. if(defined('IS_ICYPHOENIX'))
  71. {
  72. // Include moved to functions... to avoid including wrong lang file ($config['default_lang'] is only assigned after session request)
  73. //setup_extra_lang(array('lang_bbcb_mg'));
  74. }
  75. else
  76. {
  77. if (!defined('IP_ROOT_PATH')) define('IP_ROOT_PATH', './../');
  78. if (!defined('PHP_EXT')) define('PHP_EXT', substr(strrchr(__FILE__, '.'), 1));
  79. $config['allow_all_bbcode'] = 0;
  80. $config['allow_html'] = false;
  81. $config['allow_bbcode'] = true;
  82. $config['allow_smilies'] = true;
  83. $config['default_lang'] = 'english';
  84. $config['cookie_secure'] = 0;
  85. $config['server_name'] = 'icyphoenix.com';
  86. $config['script_path'] = '/';
  87. $config['liw_enabled'] = 0;
  88. $config['liw_max_width'] = 0;
  89. $config['thumbnail_cache'] = 0;
  90. $config['thumbnail_posts'] = 0;
  91. $config['thumbnail_highslide'] = 0;
  92. $config['disable_html_guests'] = 0;
  93. $config['quote_iterations'] = 3;
  94. $config['switch_bbcb_active_content'] = 1;
  95. $user->data['is_bot'] = false;
  96. $user->data['session_logged_in'] = 0;
  97. $lang['OpenNewWindow'] = 'Open in new window';
  98. $lang['Click_enlarge_pic'] = 'Click to enlarge the image';
  99. $lang['Links_For_Guests'] = 'You must be logged in to see this link';
  100. $lang['Quote'] = 'Quote';
  101. $lang['Code'] = 'Code';
  102. $lang['OffTopic'] = 'Off Topic';
  103. $lang['ReviewPost'] = 'Review Post';
  104. $lang['wrote'] = 'wrote';
  105. $lang['Description'] = 'Description';
  106. $lang['Download'] = 'Download';
  107. $lang['Hide'] = 'Hide';
  108. $lang['Show'] = 'Show';
  109. $lang['Select'] = 'Select';
  110. $lang['xs_bbc_hide_message'] = 'Hidden';
  111. $lang['xs_bbc_hide_message_explain'] = 'This message is hidden, you have to answer this topic to see it.';
  112. $lang['DOWNLOADED'] = 'Downloaded';
  113. $lang['FILESIZE'] = 'Filesize';
  114. $lang['FILENAME'] = 'Filename';
  115. $lang['Not_Authorized'] = 'Not Authorized';
  116. $lang['FILE_NOT_AUTH'] = 'You are not authorized to download this file';
  117. }
  118. $server_protocol = !empty($config['cookie_secure']) ? 'https://' : 'http://';
  119. $local_urls = array(
  120. $server_protocol . 'www.' . $config['server_name'] . $config['script_path'],
  121. $server_protocol . $config['server_name'] . $config['script_path']
  122. );
  123. if (function_exists('create_server_url'))
  124. {
  125. $server_url = create_server_url();
  126. }
  127. else
  128. {
  129. $host = getenv('HTTP_HOST');
  130. $host = (!empty($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : (!empty($host) ? $host : $config['server_name']));
  131. $server_url = $server_protocol . $host . $config['script_path'];
  132. }
  133. $smileys_path = $server_url . $config['smilies_path'] . '/';
  134. define('BBCODE_UID_LEN', 10);
  135. define('BBCODE_NOSMILIES_START', '<!-- no smilies start -->');
  136. define('BBCODE_NOSMILIES_END', '<!-- no smilies end -->');
  137. define('BBCODE_SMILIES_PATH', $smileys_path);
  138. define('AUTOURL', time());
  139. // Need to initialize the random numbers only ONCE
  140. mt_srand((double) microtime() * 1000000);
  141. class bbcode
  142. {
  143. var $text = '';
  144. var $html = '';
  145. var $tag = '';
  146. var $code_counter = 0;
  147. var $code_post_id = 0;
  148. var $allow_html = false;
  149. var $allow_styling = true;
  150. var $allow_bbcode = true;
  151. var $allow_smilies = true;
  152. var $allow_hs = true;
  153. var $plain_html = false;
  154. var $is_sig = false;
  155. var $params = array();
  156. var $data = array();
  157. var $replaced_smilies = array();
  158. var $self_closing_tags = array('[*]', '[hr]');
  159. var $allowed_bbcode = array(
  160. 'b' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  161. 'strong' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  162. 'em' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  163. 'i' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  164. 'u' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  165. 'tt' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  166. 'strike' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  167. 'sup' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  168. 'sub' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  169. 'color' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  170. 'highlight' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  171. 'rainbow' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  172. 'gradient' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  173. 'fade' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  174. 'opacity' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  175. 'align' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  176. 'center' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  177. 'font' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  178. 'size' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  179. 'hr' => array('nested' => true, 'inurl' => true, 'allow_empty' => true),
  180. 'url' => array('nested' => false, 'inurl' => false),
  181. 'a' => array('nested' => false, 'inurl' => false),
  182. 'email' => array('nested' => false, 'inurl' => false),
  183. 'list' => array('nested' => true, 'inurl' => false),
  184. 'ul' => array('nested' => true, 'inurl' => false),
  185. 'ol' => array('nested' => true, 'inurl' => false),
  186. 'li' => array('nested' => true, 'inurl' => false),
  187. '*' => array('nested' => true, 'inurl' => false),
  188. 'div' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  189. 'span' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  190. 'cell' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  191. 'spoiler' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  192. 'hide' => array('nested' => false, 'inurl' => true, 'allow_empty' => false),
  193. 'quote' => array('nested' => true, 'inurl' => false),
  194. 'ot' => array('nested' => true, 'inurl' => false),
  195. 'code' => array('nested' => false, 'inurl' => false),
  196. 'codeblock' => array('nested' => false, 'inurl' => false),
  197. 'c' => array('nested' => false, 'inurl' => false),
  198. 'img' => array('nested' => false, 'inurl' => true),
  199. 'imgba' => array('nested' => false, 'inurl' => true),
  200. 'albumimg' => array('nested' => false, 'inurl' => true),
  201. 'attachment' => array('nested' => false, 'inurl' => false, 'allow_empty' => true),
  202. 'download' => array('nested' => false, 'inurl' => false, 'allow_empty' => true),
  203. 'user' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  204. 'search' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  205. 'tag' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  206. 'langvar' => array('nested' => true, 'inurl' => true, 'allow_empty' => true),
  207. 'language' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  208. 'random' => array('nested' => true, 'inurl' => true, 'allow_empty' => true),
  209. 'marquee' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  210. 'smiley' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  211. 'flash' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  212. 'swf' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  213. 'flv' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  214. 'video' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  215. 'ram' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  216. 'quick' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  217. 'stream' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  218. 'emff' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  219. 'mp3' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  220. 'vimeo' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  221. 'youtube' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  222. 'googlevideo' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  223. // All these tags require HTML 4 specification (NON XHTML) and only work with IE!
  224. // Decomment below to use these properly...
  225. /*
  226. 'glow' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  227. 'shadow' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  228. 'blur' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  229. 'wave' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  230. 'fliph' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  231. 'flipv' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  232. */
  233. // Requires external file for parsing TEX
  234. //'tex' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  235. // To use tables you just need to decomment this... no need to decomment even TR and TD
  236. //'table' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  237. /*
  238. 'tr' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  239. 'td' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  240. */
  241. // To use IFRAMES you just need to decomment this line (and the block some hundreds lines below)... good luck!
  242. //'iframe' => array('nested' => true, 'inurl' => false, 'allow_empty' => true),
  243. );
  244. var $allowed_html = array(
  245. 'b' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  246. 'strong' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  247. 'em' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  248. 'i' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  249. 'u' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  250. 'tt' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  251. 'strike' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  252. 'sup' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  253. 'sub' => array('nested' => true, 'inurl' => true, 'allow_empty' => false),
  254. 'div' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  255. 'span' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  256. 'center' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  257. 'hr' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  258. 'a' => array('nested' => false, 'inurl' => false),
  259. 'ul' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  260. 'ol' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  261. 'li' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  262. 'code' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  263. 'blockquote' => array('nested' => true, 'inurl' => false, 'allow_empty' => false),
  264. 'table' => array('nested' => true, 'inurl' => false),
  265. /*
  266. 'tr' => array('nested' => true, 'inurl' => false),
  267. 'td' => array('nested' => true, 'inurl' => false),
  268. */
  269. // To use IFRAMES you just need to decomment this line (and the block some hundreds lines below)... good luck!
  270. //'iframe' => array('nested' => true, 'inurl' => false, 'allow_empty' => true),
  271. );
  272. var $allowed_smilies = array(
  273. array('code' => ':wink:', 'replace' => '(wink)'),
  274. array('code' => ';)', 'replace' => '(smile1)'),
  275. array('code' => ':)', 'replace' => '(smile2)'),
  276. );
  277. /**
  278. * Instantiate class
  279. */
  280. function __construct()
  281. {
  282. global $config;
  283. $this->allow_html = (!empty($config['allow_html']) ? true : false);
  284. $this->allow_bbcode = (!empty($config['allow_bbcode']) ? true : false);
  285. $this->allow_smilies = (!empty($config['allow_smilies']) ? true : false);
  286. }
  287. /*
  288. Clean bbcode/html tag.
  289. */
  290. function clean_tag(&$item)
  291. {
  292. $tag = $item['tag'];
  293. //echo 'clean_tag(', $tag, ')<br />';
  294. $start = substr($this->text, $item['start'], $item['start_len']);
  295. $end = substr($this->text, $item['end'], $item['end_len']);
  296. $content = substr($this->text, $item['start'] + $item['start_len'], $item['end'] - $item['start'] - $item['start_len']);
  297. $error = array(
  298. 'valid' => false,
  299. 'start' => $this->process_text($start),
  300. 'end' => $this->process_text($end)
  301. );
  302. if(isset($item['valid']) && $item['valid'] == false)
  303. {
  304. return $error;
  305. }
  306. // check if empty item is allowed
  307. if(!strlen($content))
  308. {
  309. $allow_empty = true;
  310. if($item['is_html'] && isset($this->allowed_html[$tag]['allow_empty']) && !$this->allowed_html[$tag]['allow_empty'])
  311. {
  312. $allow_empty = false;
  313. }
  314. if(!$item['is_html'] && isset($this->allowed_bbcode[$tag]['allow_empty']) && !$this->allowed_bbcode[$tag]['allow_empty'])
  315. {
  316. $allow_empty = false;
  317. }
  318. if(!$allow_empty)
  319. {
  320. return array(
  321. 'valid' => true,
  322. 'html' => '',
  323. 'end' => '',
  324. 'allow_nested' => false,
  325. );
  326. }
  327. }
  328. return array(
  329. 'valid' => true,
  330. 'start' => '',
  331. 'end' => ''
  332. );
  333. }
  334. /*
  335. Process bbcode/html tag.
  336. This is the only function you would want to modify to add your own bbcode/html tags.
  337. Note: this bbcode parser doesn't make any differece of bbcode and html, so <b> and [b] are treated exactly same way
  338. */
  339. function process_tag(&$item)
  340. {
  341. global $db, $cache, $config, $user, $lang, $topic_id, $local_urls, $meta_content;
  342. $server_protocol = !empty($config['cookie_secure']) ? 'https://' : 'http://';
  343. if (function_exists('create_server_url'))
  344. {
  345. $server_url = create_server_url();
  346. $local_urls = empty($local_urls) ? array($server_url) : array_merge(array($server_url), $local_urls);
  347. }
  348. else
  349. {
  350. $host = getenv('HTTP_HOST');
  351. $host = (!empty($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : (!empty($host) ? $host : $config['server_name']));
  352. $server_url = $server_protocol . $host . $config['script_path'];
  353. }
  354. //LIW - BEGIN
  355. $max_image_width = intval($config['liw_max_width']);
  356. //LIW - END
  357. $tag = $item['tag'];
  358. //echo 'process_tag(', $tag, ')<br />';
  359. $start = substr($this->text, $item['start'], $item['start_len']);
  360. $end = substr($this->text, $item['end'], $item['end_len']);
  361. $content = substr($this->text, $item['start'] + $item['start_len'], $item['end'] - $item['start'] - $item['start_len']);
  362. $error = array(
  363. 'valid' => false,
  364. 'start' => $this->process_text($start),
  365. 'end' => $this->process_text($end)
  366. );
  367. if(isset($item['valid']) && $item['valid'] == false)
  368. {
  369. return $error;
  370. }
  371. // check if empty item is allowed
  372. if(!strlen($content))
  373. {
  374. $allow_empty = true;
  375. if($item['is_html'] && isset($this->allowed_html[$tag]['allow_empty']) && !$this->allowed_html[$tag]['allow_empty'])
  376. {
  377. $allow_empty = false;
  378. }
  379. if(!$item['is_html'] && isset($this->allowed_bbcode[$tag]['allow_empty']) && !$this->allowed_bbcode[$tag]['allow_empty'])
  380. {
  381. $allow_empty = false;
  382. }
  383. if(!$allow_empty)
  384. {
  385. return array(
  386. 'valid' => true,
  387. 'html' => '',
  388. 'end' => '',
  389. 'allow_nested' => false,
  390. );
  391. }
  392. }
  393. // check if nested item is allowed
  394. if($item['iteration'])
  395. {
  396. if($item['is_html'] && !$this->allowed_html[$tag]['nested'])
  397. {
  398. return $error;
  399. }
  400. if(!$item['is_html'] && !$this->allowed_bbcode[$tag]['nested'])
  401. {
  402. return $error;
  403. }
  404. }
  405. // Simple tags: B, EM, STRONG, I, U, TT, STRIKE, SUP, SUB, DIV, SPAN, CENTER
  406. if(($tag === 'b') || ($tag === 'em') || ($tag === 'strong') || ($tag === 'i') || ($tag === 'u') || ($tag === 'tt') || ($tag === 'strike') || ($tag === 'sup') || ($tag === 'sub') || ($tag === 'div') || ($tag === 'span') || ($tag === 'center'))
  407. {
  408. $extras = $this->allow_styling ? array('style', 'class', 'name') : array('class', 'name');
  409. $html = '<' . $tag . $this->add_extras($item['params'], $extras) . '>';
  410. return array(
  411. 'valid' => true,
  412. 'start' => $html,
  413. 'end' => '</' . $tag . '>'
  414. );
  415. }
  416. // COLOR
  417. if($tag === 'color')
  418. {
  419. $extras = $this->allow_styling ? array('class') : array();
  420. $color = $this->valid_color((isset($item['params']['param']) ? $item['params']['param'] : (isset($item['params']['color']) ? $item['params']['color'] : false)));
  421. if($color === false)
  422. {
  423. return $error;
  424. }
  425. $html = '<span style="' . ($this->allow_styling && isset($item['params']['style']) ? htmlspecialchars($this->valid_style($item['params']['style'], '')) : '') . 'color: ' . $color . ';"' . $this->add_extras($item['params'], $extras) . '>';
  426. return array(
  427. 'valid' => true,
  428. 'start' => $html,
  429. 'end' => '</span>',
  430. );
  431. }
  432. // RAINBOW
  433. if($tag === 'rainbow')
  434. {
  435. $html = $this->rainbow($content);
  436. return array(
  437. 'valid' => true,
  438. 'html' => $html,
  439. 'allow_nested' => false,
  440. );
  441. }
  442. // GRADIENT
  443. if($tag === 'gradient')
  444. {
  445. $default_color1 = '#000080';
  446. $color1 = $this->valid_color((isset($item['params']['param']) ? $item['params']['param'] : (isset($item['params']['cols']) ? $item['params']['cols'] : $default_color1)), true);
  447. $color1 = (($color1 === false) ? $default_color1 : $color1);
  448. $default_color2 = '#aaccee';
  449. $color2 = $this->valid_color((isset($item['params']['cole']) ? $item['params']['cole'] : $default_color2), true);
  450. $color2 = (($color2 === false) ? $default_color2 : $color2);
  451. $mode = $this->process_text((isset($item['params']['mode']) ? $item['params']['mode'] : ''));
  452. $default_iterations = 10;
  453. $iterations = intval(isset($item['params']['iterations']) ? $item['params']['iterations'] : $default_iterations);
  454. $iterations = ((($iterations < 10) || ($iterations > 100)) ? $default_iterations : $iterations);
  455. $html = $this->gradient($content, $color1, $color2, $mode, $iterations);
  456. return array(
  457. 'valid' => true,
  458. 'html' => $html,
  459. 'allow_nested' => false,
  460. );
  461. }
  462. // HIGHLIGHT
  463. if($tag === 'highlight')
  464. {
  465. $extras = $this->allow_styling ? array('class') : array();
  466. $default_param = '#ffffaa';
  467. $color = (isset($item['params']['param']) ? $item['params']['param'] : (isset($item['params']['color']) ? $item['params']['color'] : $default_param));
  468. $color = $this->valid_color($color);
  469. if($color === false)
  470. {
  471. return $error;
  472. }
  473. $html = '<span style="' . ($this->allow_styling && isset($item['params']['style']) ? htmlspecialchars($this->valid_style($item['params']['style'], '')) : '') . 'background-color: ' . $color . ';"' . $this->add_extras($item['params'], $extras) . '>';
  474. return array(
  475. 'valid' => true,
  476. 'start' => $html,
  477. 'end' => '</span>',
  478. );
  479. }
  480. // SIZE
  481. if($tag === 'size')
  482. {
  483. $extras = $this->allow_styling ? array('class') : array();
  484. $default_param = 0;
  485. $size = intval((isset($item['params']['param']) ? $item['params']['param'] : (isset($item['params']['size']) ? $item['params']['size'] : $default_param)));
  486. if($size > 0 && $size < 7)
  487. {
  488. // vBulletin-style sizes
  489. switch($size)
  490. {
  491. case 1: $size = 7; break;
  492. case 2: $size = 8; break;
  493. case 3: $size = 10; break;
  494. case 4: $size = 12; break;
  495. case 5: $size = 15; break;
  496. case 6: $size = 24; break;
  497. }
  498. }
  499. if(($size < 6) || ($size > 48))
  500. {
  501. return $error;
  502. }
  503. $html = '<span style="' . ($this->allow_styling && isset($item['params']['style']) ? htmlspecialchars($this->valid_style($item['params']['style'], '')) : '') . 'font-size: ' . $size . 'px; line-height: 116%;"' . $this->add_extras($item['params'], $extras) . '>';
  504. return array(
  505. 'valid' => true,
  506. 'start' => $html,
  507. 'end' => '</span>',
  508. );
  509. }
  510. // Single tags: HR
  511. if($tag === 'hr')
  512. {
  513. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  514. $extras = $this->allow_styling ? array('style', 'class') : array();
  515. $color = $this->valid_color((isset($item['params']['param']) ? $item['params']['param'] : (isset($item['params']['color']) ? $item['params']['color'] : false)));
  516. $html = '<' . $tag . (($color === false) ? ($this->allow_styling && isset($item['params']['style']) ? (' style="' . htmlspecialchars($this->valid_style($item['params']['style'], '')) . '"') : '') : (' style="border-color: ' . $color . ';"')) . ' />';
  517. return array(
  518. 'valid' => true,
  519. 'html' => $html
  520. );
  521. }
  522. // ALIGN
  523. if($tag === 'align')
  524. {
  525. $extras = $this->allow_styling ? array('style', 'class') : array();
  526. $default_param = 'left';
  527. $align = (isset($item['params']['param']) ? $item['params']['param'] : (isset($item['params']['align']) ? $item['params']['align'] : $default_param));
  528. if (($align === 'left') || ($align === 'right') || ($align === 'center') || ($align === 'justify'))
  529. {
  530. $html = '<div style="text-align: ' . $align . ';' . (($align === 'center') ? (' margin-left: auto; margin-right: auto;') : '') . '">';
  531. return array(
  532. 'valid' => true,
  533. 'start' => $html,
  534. 'end' => '</div>',
  535. );
  536. }
  537. else
  538. {
  539. return $error;
  540. }
  541. }
  542. // IMG
  543. if($tag === 'img')
  544. {
  545. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  546. // main parameters
  547. $params = array(
  548. 'src' => false,
  549. 'alt' => false,
  550. 'slide' => false,
  551. );
  552. // additional allowed parameters
  553. $extras = $this->allow_styling ? array('width', 'height', 'border', 'style', 'class', 'title', 'align') : array('width', 'height', 'border', 'title', 'align');
  554. if ($config['thumbnail_highslide'])
  555. {
  556. $slideshow = !empty($item['params']['slide']) ? ', { slideshowGroup: \'' . $this->process_text($item['params']['slide']) . '\' } ' : '';
  557. }
  558. $liw_bypass = false;
  559. // [img=blah]blah2[/img]
  560. if(isset($item['params']['param']))
  561. {
  562. $params['src'] = $item['params']['param'];
  563. $img_url = $params['src'];
  564. $img_url_enc = urlencode(ip_utf8_decode($params['src']));
  565. $path_parts = pathinfo($img_url);
  566. $params['alt'] = (!empty($content) ? $content : ip_clean_string($path_parts['filename'], $lang['ENCODING'], true));
  567. }
  568. // [img src=blah alt=blah width=123][/img]
  569. elseif(isset($item['params']['src']))
  570. {
  571. $params['src'] = $item['params']['src'];
  572. $img_url = $params['src'];
  573. $img_url_enc = urlencode(ip_utf8_decode($params['src']));
  574. $path_parts = pathinfo($img_url);
  575. $params['alt'] = (isset($item['params']['alt']) ? $item['params']['alt'] : (!empty($content) ? $content : ip_clean_string($path_parts['filename'], $lang['ENCODING'], true)));
  576. for($i = 0; $i < sizeof($extras); $i++)
  577. {
  578. if(!empty($item['params'][$extras[$i]]))
  579. {
  580. if($extras[$i] === 'style')
  581. {
  582. $style = $this->valid_style($item['params']['style']);
  583. if($style !== false)
  584. {
  585. $params['style'] = $style;
  586. }
  587. }
  588. else
  589. {
  590. $params[$extras[$i]] = $item['params'][$extras[$i]];
  591. }
  592. }
  593. }
  594. }
  595. // [img]blah[/img], [img width=blah]blah[/img]
  596. elseif(!empty($content))
  597. {
  598. $params['src'] = $content;
  599. $img_url = $params['src'];
  600. $img_url_enc = urlencode(ip_utf8_decode($params['src']));
  601. $path_parts = pathinfo($img_url);
  602. $params['alt'] = (isset($item['params']['alt']) ? $item['params']['alt'] : (isset($params['title']) ? $params['title'] : ip_clean_string($path_parts['filename'], $lang['ENCODING'], true)));
  603. // LIW - BEGIN
  604. if (($config['liw_enabled'] == 1) && ($max_image_width > 0) && ($config['thumbnail_posts'] == 0) && empty($this->plain_html))
  605. {
  606. $liw_bypass = true;
  607. if (isset($item['params']['width']))
  608. {
  609. $item['params']['width'] = ($item['params']['width'] > $max_image_width) ? $max_image_width : $item['params']['width'];
  610. }
  611. else
  612. {
  613. $image_size = @getimagesize($content);
  614. $item['params']['width'] = ($image_size[0] > $max_image_width) ? $max_image_width : $image_size[0];
  615. }
  616. }
  617. // LIW - END
  618. for($i = 0; $i < sizeof($extras); $i++)
  619. {
  620. if(!empty($item['params'][$extras[$i]]))
  621. {
  622. if($extras[$i] === 'style')
  623. {
  624. $style = $this->valid_style($item['params']['style']);
  625. if($style !== false)
  626. {
  627. $params['style'] = $style;
  628. }
  629. }
  630. else
  631. {
  632. $params[$extras[$i]] = $item['params'][$extras[$i]];
  633. }
  634. }
  635. }
  636. }
  637. $is_smiley = false;
  638. if (substr($params['src'], 0, strlen(BBCODE_SMILIES_PATH)) == BBCODE_SMILIES_PATH)
  639. {
  640. $is_smiley = true;
  641. }
  642. if (!$is_smiley && $config['thumbnail_posts'] && ($liw_bypass == false) && empty($this->plain_html))
  643. {
  644. $process_thumb = !empty($config['thumbnail_cache']) ? true : false;
  645. $thumb_exists = false;
  646. $thumb_processed = false;
  647. $is_light_view = false;
  648. if (isset($item['params']['thumb']))
  649. {
  650. if ($item['params']['thumb'] == 'false')
  651. {
  652. $process_thumb = false;
  653. }
  654. }
  655. if(!empty($process_thumb))
  656. {
  657. $thumb_processed = true;
  658. $pic_id = $img_url;
  659. $pic_fullpath = str_replace(array(' '), array('%20'), $pic_id);
  660. $pic_id = str_replace('http://', '', str_replace('https://', '', $pic_id));
  661. $pic_path[] = array();
  662. $pic_path = explode('/', $pic_id);
  663. $pic_filename = end($pic_path);
  664. $file_part = explode('.', strtolower($pic_filename));
  665. $pic_filetype = end($file_part);
  666. $thumb_ext_array = array('gif', 'jpg', 'png');
  667. if (in_array($pic_filetype, $thumb_ext_array))
  668. {
  669. $user_dir = '';
  670. $users_images_path = str_replace('http://', '', str_replace('https://', '', $server_url . str_replace(IP_ROOT_PATH, '', POSTED_IMAGES_PATH)));
  671. $pic_title = substr($pic_filename, 0, strlen($pic_filename) - strlen($pic_filetype) - 1);
  672. $pic_title_reg = preg_replace('/[^A-Za-z0-9]+/', '_', $pic_title);
  673. $pic_thumbnail = 'mid_' . md5($pic_id) . '_' . $pic_filename;
  674. if (strpos($pic_id, $users_images_path) !== false)
  675. {
  676. $user_dir = str_replace($pic_filename, '', str_replace($users_images_path, '', $pic_id));
  677. $pic_thumbnail = $pic_filename;
  678. }
  679. $pic_thumbnail_fullpath = POSTED_IMAGES_THUMBS_PATH . $user_dir . $pic_thumbnail;
  680. // Light View - BEGIN
  681. $light_view = request_var('light_view', 0);
  682. // Force to false for debugging purpose...
  683. $light_view = 0;
  684. if (!empty($light_view) && !empty($user_dir))
  685. {
  686. $is_light_view = true;
  687. $pic_thumbnail_fullpath = POSTED_IMAGES_THUMBS_S_PATH . $user_dir . $pic_thumbnail;
  688. }
  689. // Light View - END
  690. if(file_exists($pic_thumbnail_fullpath))
  691. {
  692. $thumb_exists = true;
  693. $params['src'] = $server_url . str_replace(IP_ROOT_PATH, '', $pic_thumbnail_fullpath);
  694. }
  695. }
  696. }
  697. $cache_image = true;
  698. $cache_append = '';
  699. if (isset($item['params']['cache']))
  700. {
  701. if ($item['params']['cache'] == 'false')
  702. {
  703. //$bbc_eamp = '&amp;';
  704. $bbc_eamp = '&';
  705. $cache_image = false;
  706. $cache_append = 'cache=false' . $bbc_eamp . 'rand=' . md5(rand()) . $bbc_eamp;
  707. }
  708. else
  709. {
  710. $cache_image = true;
  711. }
  712. }
  713. if (!empty($process_thumb) && (($thumb_exists == false) || ($cache_image == false)))
  714. {
  715. $pic_thumbnail_script = $server_url . CMS_PAGE_IMAGE_THUMBNAIL . '?' . $cache_append . 'pic_id=' . $img_url_enc;
  716. // Light View - BEGIN
  717. if (!empty($thumb_processed) && !empty($is_light_view))
  718. {
  719. $img_url_enc = $user_dir . $pic_thumbnail;
  720. $pic_thumbnail_script = $server_url . CMS_PAGE_IMAGE_THUMBNAIL_S . '?' . $cache_append . 'pic_id=' . $img_url_enc;
  721. }
  722. // Light View - END
  723. $params['src'] = $pic_thumbnail_script;
  724. }
  725. }
  726. // generate html
  727. $html = '<img';
  728. foreach($params as $var => $value)
  729. {
  730. if ($this->process_text($value) != '')
  731. {
  732. $html .= ' ' . $var . '="' . $this->process_text($value) . '"';
  733. }
  734. if (($var == 'src') && (!$this->is_sig))
  735. {
  736. $meta_content['og_img'][] = $value;
  737. }
  738. }
  739. if(!isset($params['title']))
  740. {
  741. $html .= ' title="' . $this->process_text($params['alt']) . '"';
  742. }
  743. $html .= ' />';
  744. // add url
  745. /*
  746. if (strpos($params['src'], trim($config['server_name'])) == false)
  747. {
  748. $html = $this->process_text($params['alt']);
  749. }
  750. */
  751. // Light View - BEGIN
  752. if (!empty($thumb_processed) && !empty($is_light_view) && empty($this->plain_html))
  753. {
  754. $item['inurl'] = true;
  755. }
  756. // Light View - END
  757. if(empty($item['inurl']) && !$is_smiley && empty($this->plain_html))
  758. {
  759. if ($this->allow_hs && $config['thumbnail_posts'] && $config['thumbnail_highslide'])
  760. {
  761. $extra_html = ' class="highslide" onclick="return hs.expand(this' . $slideshow . ')"';
  762. }
  763. else
  764. {
  765. $extra_html = ' target="_blank" title="' . $lang['OpenNewWindow'] . '"';
  766. }
  767. $html = '<a href="' . $this->process_text($img_url) . '"' . $extra_html . '>' . $html . '</a>';
  768. }
  769. return array(
  770. 'valid' => true,
  771. 'html' => $html,
  772. 'allow_nested' => false,
  773. );
  774. }
  775. // IMGBA
  776. if($tag === 'imgba')
  777. {
  778. if($this->is_sig) return $error;
  779. if (!empty($this->plain_html)) return $error;
  780. // main parameters
  781. $params = array(
  782. 'before' => false,
  783. 'after' => false,
  784. 'width' => false,
  785. 'w' => false,
  786. 'height' => false,
  787. 'h' => false,
  788. 'alt' => false,
  789. 'title' => false,
  790. );
  791. foreach ($params as $k => $v)
  792. {
  793. $params[$k] = $item['params'][$k];
  794. }
  795. if (empty($params['before']) || empty($params['after']))
  796. {
  797. return $error;
  798. }
  799. $path_parts = pathinfo($params['before']);
  800. (int) $params['width'] = !empty($params['w']) ? intval($params['w']) : intval($params['width']);
  801. (int) $params['height'] = !empty($params['h']) ? intval($params['h']) : intval($params['height']);
  802. $params['alt'] = (!empty($params['alt']) ? $params['alt'] : ip_clean_string($path_parts['filename'], $lang['ENCODING'], true));
  803. if (empty($params['width']) || empty($params['height']))
  804. {
  805. return $error;
  806. }
  807. // Since we passed the main tests, we may force all needed JS inclusions...
  808. $config['jquery_ui'] = true;
  809. $config['jquery_ui_ba'] = true;
  810. $max_width = 600;
  811. $or_width = $params['width'];
  812. $or_height = $params['height'];
  813. if ($params['width'] > $max_width)
  814. {
  815. $params['width'] = $max_width;
  816. $params['height'] = $max_width / ($or_width / $or_height);
  817. }
  818. // additional allowed parameters
  819. $extras = $this->allow_styling ? array('style', 'class') : array();
  820. for($i = 0; $i < sizeof($extras); $i++)
  821. {
  822. if(!empty($item['params'][$extras[$i]]))
  823. {
  824. if($extras[$i] === 'style')
  825. {
  826. $style = $this->valid_style($item['params']['style']);
  827. if($style !== false)
  828. {
  829. $params['style'] = $style;
  830. }
  831. }
  832. else
  833. {
  834. $params[$extras[$i]] = $item['params'][$extras[$i]];
  835. }
  836. }
  837. }
  838. $container = 'imgba_' . substr(md5($params['before']), 0, 6);
  839. $imgba_error = false;
  840. $allowed_ext = array('gif', 'jpeg', 'jpg', 'png');
  841. $img_test_array = array('before', 'after');
  842. // Few "pseudo-security" tests
  843. foreach ($img_test_array as $img_test)
  844. {
  845. $file_ext = substr(strrchr($params[$img_test], '.'), 1);
  846. //if (!in_array($file_ext, $allowed_ext) || (strpos($params[$img_test], $server_url) !== 0) || (strpos($params[$img_test], '?') !== 0))
  847. if (!in_array($file_ext, $allowed_ext))
  848. {
  849. $imgba_error = true;
  850. }
  851. }
  852. if (!empty($imgba_error))
  853. {
  854. return $error;
  855. }
  856. // generate html
  857. $html = '';
  858. $html .= '<div id="' . $container . '"';
  859. foreach($params as $var => $value)
  860. {
  861. if (in_array($value, array('width', 'height')) && ($this->process_text($value) != ''))
  862. {
  863. $html .= ' ' . $var . '="' . $this->process_text($value) . '"';
  864. }
  865. }
  866. $html .= '>';
  867. $img_alt = $this->process_text($params['alt']);
  868. $img_title = (!empty($params['title']) ? ' title="' . $this->process_text($params['title']) . '"' : '');
  869. $html .= '<div><img src="' . $params['before'] . '" width="' . $params['width'] . '" height="' . $params['height'] . '" alt="Before: ' . $img_alt . '"' . $img_title . ' /></div>';
  870. $html .= '<div><img src="' . $params['after'] . '" width="' . $params['width'] . '" height="' . $params['height'] . '" alt="After: ' . $img_alt . '"' . $img_title . ' /></div>';
  871. $html .= '</div>';
  872. $html .= '<script type="text/javascript">$(function(){ $(\'#' . $container . '\').beforeAfter({imagePath: \'' . $server_url . 'templates/common/jquery/\', showFullLinks: true, cursor: \'e-resize\', dividerColor: \'#dd2222\', beforeLinkText: \'' . $lang['IMG_BA_SHOW_ONLY_BEFORE'] . '\', afterLinkText: \'' . $lang['IMG_BA_SHOW_ONLY_AFTER'] . '\'}); });</script>';
  873. return array(
  874. 'valid' => true,
  875. 'html' => $html,
  876. 'allow_nested' => false,
  877. );
  878. }
  879. // ALBUMIMG
  880. if($tag === 'albumimg')
  881. {
  882. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  883. if (!empty($this->plain_html)) return $error;
  884. // main parameters
  885. $params = array(
  886. 'src' => false,
  887. 'alt' => false,
  888. );
  889. // additional allowed parameters
  890. $extras = $this->allow_styling ? array('width', 'height', 'border', 'style', 'class', 'title', 'align') : array('width', 'height', 'border', 'title', 'align');
  891. // [albumimg=blah]blah2[/albumimg]
  892. if(isset($item['params']['param']))
  893. {
  894. $params['src'] = $item['params']['param'];
  895. $pic_url = $item['params']['param'];
  896. $params['alt'] = $content;
  897. }
  898. // [albumimg src=blah alt=blah width=123][/albumimg]
  899. elseif(isset($item['params']['src']))
  900. {
  901. $params['src'] = $item['params']['src'];
  902. $pic_url = $item['params']['src'];
  903. $params['alt'] = isset($item['params']['alt']) ? $item['params']['alt'] : $content;
  904. for($i = 0; $i < sizeof($extras); $i++)
  905. {
  906. if(!empty($item['params'][$extras[$i]]))
  907. {
  908. if($extras[$i] === 'style')
  909. {
  910. $style = $this->valid_style($item['params']['style']);
  911. if($style !== false)
  912. {
  913. $params['style'] = $style;
  914. }
  915. }
  916. else
  917. {
  918. $params[$extras[$i]] = $item['params'][$extras[$i]];
  919. }
  920. }
  921. }
  922. }
  923. // [albumimg]blah[/albumimg], [albumimg width=blah]blah[/albumimg]
  924. elseif(!empty($content))
  925. {
  926. $params['src'] = $content;
  927. $pic_url = $content;
  928. $params['alt'] = isset($item['params']['alt']) ? $item['params']['alt'] : (isset($params['title']) ? $params['title'] : '');
  929. for($i = 0; $i < sizeof($extras); $i++)
  930. {
  931. if(!empty($item['params'][$extras[$i]]))
  932. {
  933. if($extras[$i] === 'style')
  934. {
  935. $style = $this->valid_style($item['params']['style']);
  936. if($style !== false)
  937. {
  938. $params['style'] = $style;
  939. }
  940. }
  941. else
  942. {
  943. $params[$extras[$i]] = $item['params'][$extras[$i]];
  944. }
  945. }
  946. }
  947. }
  948. // generate html
  949. $pic_url = $server_url . 'album_showpage.' . PHP_EXT . '?pic_id=' . $pic_url;
  950. if(isset($item['params']['mode']))
  951. {
  952. $pic_mode = $item['params']['mode'];
  953. if ($pic_mode === 'full')
  954. {
  955. $params['src'] = $server_url . 'album_picm.' . PHP_EXT . '?pic_id=' . $params['src'];
  956. }
  957. else
  958. {
  959. $params['src'] = $server_url . 'album_thumbnail.' . PHP_EXT . '?pic_id=' . $params['src'];
  960. }
  961. }
  962. else
  963. {
  964. $params['src'] = $server_url . 'album_thumbnail.' . PHP_EXT . '?pic_id=' . $params['src'];
  965. }
  966. $html = '<img';
  967. foreach($params as $var => $value)
  968. {
  969. $html .= ' ' . $var . '="' . $this->process_text($value) . '"';
  970. if (($var == 'src') && (!$this->is_sig))
  971. {
  972. $meta_content['og_img'][] = $value;
  973. }
  974. }
  975. if(!isset($params['title']))
  976. {
  977. $html .= ' title="' . $this->process_text($params['alt']) . '"';
  978. }
  979. $html .= ' />';
  980. // add url
  981. if(empty($item['inurl']))
  982. {
  983. $html = '<a href="' . $this->process_text($pic_url) . '" title="' . $lang['Click_enlarge_pic'] . '">' . $html . '</a>';
  984. }
  985. return array(
  986. 'valid' => true,
  987. 'html' => $html,
  988. 'allow_nested' => false,
  989. );
  990. }
  991. // ATTACHMENT
  992. if(($tag === 'attachment') || ($tag === 'download'))
  993. {
  994. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  995. if (!empty($this->plain_html)) return $error;
  996. $html = '';
  997. $params['id'] = isset($item['params']['param']) ? intval($item['params']['param']) : (isset($item['params']['id']) ? intval($item['params']['id']) : false);
  998. $params['title'] = isset($item['params']['title']) ? $this->process_text($item['params']['title']) : false;
  999. $params['description'] = isset($item['params']['description']) ? $this->process_text($item['params']['description']) : (!empty($content) ? $this->process_text($content) : false);
  1000. $params['icon'] = isset($item['params']['icon']) ? $this->process_text($item['params']['icon']) : false;
  1001. $color = $this->valid_color(isset($item['params']['color']) ? $item['params']['color'] : false);
  1002. $bgcolor = $this->valid_color(isset($item['params']['bgcolor']) ? $item['params']['bgcolor'] : false);
  1003. $errored = false;
  1004. if ($params['id'] <= 0)
  1005. {
  1006. $errored = true;
  1007. }
  1008. if (!$errored)
  1009. {
  1010. if ($tag === 'attachment')
  1011. {
  1012. if (!function_exists('get_attachment_details'))
  1013. {
  1014. include_once(IP_ROOT_PATH . 'includes/functions_bbcode.' . PHP_EXT);
  1015. }
  1016. $is_auth_ary = auth(AUTH_READ, AUTH_LIST_ALL, $user->data);
  1017. $is_download_auth_ary = auth(AUTH_DOWNLOAD, AUTH_LIST_ALL, $user->data);
  1018. $attachment_details = get_attachment_details($params['id']);
  1019. if (($attachment_details == false) || !$is_auth_ary[$attachment_details['forum_id']]['auth_read'] || !$is_download_auth_ary[$attachment_details['forum_id']]['auth_download'])
  1020. {
  1021. $errored = true;
  1022. }
  1023. }
  1024. else
  1025. {
  1026. if (!function_exists('get_download_details'))
  1027. {
  1028. include_once(IP_ROOT_PATH . 'includes/functions_bbcode.' . PHP_EXT);
  1029. }
  1030. $attachment_details = get_download_details($params['id']);
  1031. $errored = ($attachment_details == false) ? true : false;
  1032. }
  1033. }
  1034. if (!$errored)
  1035. {
  1036. if ($tag === 'attachment')
  1037. {
  1038. $params['title'] = $params['title'] ? $params['title'] : (!empty($attachment_details['real_filename']) ? $attachment_details['real_filename'] : '&nbsp;');
  1039. $params['description'] = $params['description'] ? $params['description'] : (!empty($attachment_details['comment']) ? $attachment_details['comment'] : ' ');
  1040. $params['icon'] = IP_ROOT_PATH . FILES_ICONS_DIR . ($params['icon'] ? $params['icon'] : 'default.png');
  1041. $download_url = IP_ROOT_PATH . 'download.' . PHP_EXT . '?id=' . $params['id'];
  1042. }
  1043. else
  1044. {
  1045. $params['title'] = $params['title'] ? $params['title'] : (!empty($attachment_details['file_name']) ? $attachment_details['file_name'] : '&nbsp;');
  1046. $params['description'] = $params['description'] ? $params['description'] : (!empty($attachment_details['file_desc']) ? $attachment_details['file_desc'] : ' ');
  1047. $params['icon'] = IP_ROOT_PATH . FILES_ICONS_DIR . ($params['icon'] ? $params['icon'] : (!empty($attachment_details['file_posticon']) ? $attachment_details['file_posticon'] : 'default.png'));
  1048. $attachment_details['filesize'] = $attachment_details['file_size'];
  1049. $attachment_details['download_count'] = $attachment_details['file_dls'];
  1050. $download_url = IP_ROOT_PATH . 'dload.' . PHP_EXT . '?action=file&amp;file_id=' . $params['id'];
  1051. }
  1052. $params['title'] = htmlspecialchars($params['title']);
  1053. $params['description'] = htmlspecialchars($params['description']);
  1054. $params['icon'] = file_exists($params['icon']) ? $params['icon'] : (IP_ROOT_PATH . FILES_ICONS_DIR . 'default.png');
  1055. $style = ($color || $bgcolor) ? (' style="' . ($color ? 'color: ' . $color . ';' : '') . ($bgcolor ? 'background-color: ' . $bgcolor . ';' : '') . '"') : '';
  1056. $html .= '<div class="mg_attachtitle"' . $style . '>' . $params['title'] . '</div>';
  1057. $html .= '<div class="mg_attachdiv"><table>';
  1058. $html .= '<tr><td style="width: 15%;"><b class="gensmall">' . $lang['Description'] . ':</b></td><td style="width: 75%;"><span class="gensmall">' . $params['description'] . '</span></td><td rowspan="3" class="row-center" style="width: 10%;"><img src="' . $params['icon'] . '" alt="' . $params['description'] . '" /><br /><a href="' . append_sid($download_url) . '" title="' . $lang['Download'] . ' ' . $params['title'] . '"><b>' . $lang['Download'] . '</b></a></td></tr>';
  1059. $html .= '<tr><td><b class="gensmall">' . $lang['FILESIZE'] . ':</b></td><td><span class="gensmall">' . round(($attachment_details['filesize'] / 1024), 2) . ' KB</span></td></tr>';
  1060. $html .= '<tr><td><b class="gensmall">' . $lang['DOWNLOADED'] . ':</b></td><td><span class="gensmall">' . $attachment_details['download_count'] . '</span></td></tr>';
  1061. $html .= '</table></div>';
  1062. }
  1063. else
  1064. {
  1065. $style = ($color || $bgcolor) ? (' style="' . ($color ? 'color: ' . $color . ';' : '') . ($bgcolor ? 'background-color: ' . $bgcolor . ';' : '') . '"') : '';
  1066. $html .= '<div class="mg_attachtitle"' . $style . '>' . $lang['Not_Authorized'] . '</div>';
  1067. $html .= '<div class="mg_attachdiv"><div style="text-align: center;">' . $lang['FILE_NOT_AUTH'] . '</div></div>';
  1068. }
  1069. return array(
  1070. 'valid' => true,
  1071. 'html' => $html,
  1072. 'allow_nested' => false,
  1073. );
  1074. }
  1075. // LIST
  1076. if(($tag === 'list') || ($tag === 'ul') || ($tag === 'ol'))
  1077. {
  1078. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  1079. $extras = $this->allow_styling ? array('style', 'class') : array();
  1080. // check if nested tags are all [*]
  1081. $nested_count = 0;
  1082. for($i = 0; $i < sizeof($item['items']); $i++)
  1083. {
  1084. $tag2 = $item['items'][$i]['tag'];
  1085. if(($tag2 === '*') || ($tag2 === 'li'))
  1086. {
  1087. $nested_count++;
  1088. }
  1089. }
  1090. if(!$nested_count)
  1091. {
  1092. // no <li> items. return error
  1093. return $error;
  1094. }
  1095. // replace "list" with html tag
  1096. if($tag === 'list')
  1097. {
  1098. if(isset($item['params']['param']) || isset($item['params']['type']))
  1099. {
  1100. $tag = 'ol';
  1101. }
  1102. else
  1103. {
  1104. $tag = 'ul';
  1105. }
  1106. }
  1107. // valid tag. process subitems to make sure there are no extra items and remove all code between elements
  1108. $last_item = false;
  1109. for($i = 0; $i < sizeof($item['items']); $i++)
  1110. {
  1111. $item2 = &$item['items'][$i];
  1112. $tag2 = $item2['tag'];
  1113. if(($tag2 === '*') || ($tag2 === 'li'))
  1114. {
  1115. // mark as valid
  1116. $item2['list_valid'] = true;
  1117. if($last_item === false)
  1118. {
  1119. // change start position to end of [list]
  1120. $pos = !empty($pos) ? $pos : 0;
  1121. $pos2 = $item2['start'] + $item2['start_len'];
  1122. $item2['start'] = $pos;
  1123. $item2['start_len'] = $pos2 - $pos;
  1124. $item2['first_entry'] = true;
  1125. }
  1126. $last_item = &$item['items'][$i];
  1127. }
  1128. }
  1129. // generate html
  1130. $html = '<' . $tag;
  1131. if(isset($item['params']['param']))
  1132. {
  1133. $html .= ' type="' . htmlspecialchars($item['params']['param']) . '"';
  1134. }
  1135. elseif(isset($item['params']['type']))
  1136. {
  1137. $html .= ' type="' . htmlspecialchars($item['params']['type']) . '"';
  1138. }
  1139. $html .= $this->add_extras($item['params'], $extras) . '>';
  1140. return array(
  1141. 'valid' => true,
  1142. 'start' => $html,
  1143. 'end' => '</li></' . $tag . '>'
  1144. );
  1145. }
  1146. // [*], LI
  1147. if(($tag === '*') || ($tag === 'li'))
  1148. {
  1149. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  1150. $extras = $this->allow_styling ? array('style', 'class') : array();
  1151. // if not marked as valid return error
  1152. if(empty($item['list_valid']))
  1153. {
  1154. return $error;
  1155. }
  1156. $html = '<li';
  1157. if(empty($item['first_entry']))
  1158. {
  1159. // add closing tag for previous list entry
  1160. $html = '</li>' . $html;
  1161. }
  1162. $html .= $this->add_extras($item['params'], $extras) . '>';
  1163. return array(
  1164. 'valid' => true,
  1165. 'start' => $html,
  1166. 'end' => '',
  1167. );
  1168. }
  1169. // FONT
  1170. if($tag === 'font')
  1171. {
  1172. $fonts = array(
  1173. 'Arial',
  1174. 'Arial Black',
  1175. 'Comic Sans MS',
  1176. 'Courier New',
  1177. 'Impact',
  1178. 'Lucida Console',
  1179. 'Lucida Sans Unicode',
  1180. 'Microsoft Sans Serif',
  1181. 'Symbol',
  1182. 'Tahoma',
  1183. 'Times New Roman',
  1184. 'Traditional Arabic',
  1185. 'Trebuchet MS',
  1186. 'Verdana',
  1187. 'Webdings',
  1188. 'Wingdings'
  1189. );
  1190. if (defined('FONTS_DIR'))
  1191. {
  1192. foreach ($cache->obtain_fonts() as $font_file)
  1193. {
  1194. $fonts[] = substr($font_file, 0, -4);
  1195. }
  1196. }
  1197. $extras = $this->allow_styling ? array('style', 'class') : array();
  1198. $default_param = 'Verdana';
  1199. $font = (isset($item['params']['param']) ? $item['params']['param'] : (isset($item['params']['font']) ? $item['params']['font'] : $default_param));
  1200. $font = in_array($font, $fonts) ? $font : $default_param;
  1201. $html = '<span style="font-family: \'' . $font . '\';">';
  1202. return array(
  1203. 'valid' => true,
  1204. 'start' => $html,
  1205. 'end' => '</span>',
  1206. );
  1207. }
  1208. // CELL
  1209. if($tag === 'cell')
  1210. {
  1211. $extras = $this->allow_styling ? array('style', 'class', 'align', 'border') : array('class', 'align');
  1212. $width = (isset($item['params']['width']) ? (' width: ' . intval($item['params']['width']) . 'px;') : '');
  1213. $height = (isset($item['params']['height']) ? (' height: ' . intval($item['params']['height']) . 'px;') : '');
  1214. $padding = (isset($item['params']['padding']) ? (' padding: ' . intval($item['params']['padding']) . 'px;') : '');
  1215. $margin = (isset($item['params']['margin']) ? (' margin: ' . intval($item['params']['margin']) . 'px;') : '');
  1216. $borderwidth = (isset($item['params']['borderwidth']) ? (' border-width: ' . intval($item['params']['borderwidth']) . 'px;') : '');
  1217. $bgcolor = $this->valid_color((isset($item['params']['bgcolor']) ? $item['params']['bgcolor'] : false));
  1218. $bgcolor = (($bgcolor !== false) ? (' background-color: ' . $bgcolor . ';') : '');
  1219. $bordercolor = $this->valid_color((isset($item['params']['bordercolor']) ? $item['params']['bordercolor'] : false));
  1220. $bordercolor = (($bordercolor !== false) ? (' border-color: ' . $bordercolor . ';') : '');
  1221. $color = $this->valid_color((isset($item['params']['color']) ? $item['params']['color'] : false));
  1222. $color = (($color !== false) ? (' color: ' . $color . ';') : '');
  1223. $html = '<div style="' . ($this->allow_styling && isset($item['params']['style']) ? htmlspecialchars($this->valid_style($item['params']['style'], '')) : '') . $height . $width . $bgcolor . $bordercolor . $borderwidth . $color . $padding . $margin . '"' . $this->add_extras($item['params'], $extras) . '>';
  1224. return array(
  1225. 'valid' => true,
  1226. 'start' => $html,
  1227. 'end' => '</div>',
  1228. );
  1229. }
  1230. // URL, A
  1231. if(($tag === 'url') || ($tag === 'a'))
  1232. {
  1233. $extras = $this->allow_styling ? array('style', 'class', 'name', 'title') : array('name', 'title');
  1234. $allow_nested = true;
  1235. $strip_text = false;
  1236. $show_content = true;
  1237. $url = '';
  1238. // get url
  1239. if(!empty($item['params']['param']))
  1240. {
  1241. $url = $item['params']['param'];
  1242. }
  1243. elseif(!empty($item['params']['href']))
  1244. {
  1245. $url = $item['params']['href'];
  1246. }
  1247. elseif(!$item['is_html'])
  1248. {
  1249. $url = $content;
  1250. $allow_nested = false;
  1251. $strip_text = true;
  1252. }
  1253. else
  1254. {
  1255. return $error;
  1256. }
  1257. if(($url === $content) && (strlen($content) > 64))
  1258. {
  1259. $content = htmlspecialchars(substr($content, 0, 35) . '...' . substr($content, strlen($content) - 15));
  1260. $show_content = false;
  1261. }
  1262. // check if its email
  1263. if(substr(strtolower($url), 0, 7) === 'mailto:')
  1264. {
  1265. $item['tag'] = 'email';
  1266. return $this->process_tag($item);
  1267. }
  1268. // check for invalid urls
  1269. $url = $this->valid_url($url, '');
  1270. if(empty($url))
  1271. {
  1272. return $error;
  1273. }
  1274. // check nested items
  1275. if(!$allow_nested)
  1276. {
  1277. for($i = 0; $i < sizeof($item['items']); $i++)
  1278. {
  1279. $item['items'][$i]['valid'] = false;
  1280. }
  1281. }
  1282. else
  1283. {
  1284. for($i = 0; $i < sizeof($item['next']); $i++)
  1285. {
  1286. $tag2 = $item['next'][$i]['tag'];
  1287. $is_html = $item['next'][$i]['item']['is_html'];
  1288. $item['next'][$i]['item']['inurl'] = true;
  1289. if($is_html && !$this->allowed_html[$tag2]['inurl'])
  1290. {
  1291. $item['next'][$i]['item']['valid'] = false;
  1292. }
  1293. if(!$is_html && !$this->allowed_bbcode[$tag2]['inurl'])
  1294. {
  1295. $item['next'][$i]['item']['valid'] = false;
  1296. }
  1297. }
  1298. }
  1299. // check for incomplete url
  1300. if(substr(strtolower($url), 0, 4) === 'www.')
  1301. {
  1302. $url = 'http://' . $url;
  1303. }
  1304. // remove extra characters at the end
  1305. $last_char = substr($url, strlen($url) - 1);
  1306. $last_char_i = ord($last_char);
  1307. if((($last_char_i > 32) && ($last_char_i < 47)) || (($last_char_i > 57) && ($last_char_i < 65)))
  1308. {
  1309. $url = substr($url, 0, strlen($url) - 1);
  1310. }
  1311. // check if url is local
  1312. $is_local_url = false;
  1313. if (!empty($local_urls))
  1314. {
  1315. foreach ($local_urls as $local_url)
  1316. {
  1317. if((strlen($url) > strlen($local_url)) && strpos($url, $local_url) === 0)
  1318. {
  1319. $is_local_url = true;
  1320. }
  1321. }
  1322. }
  1323. if(empty($is_local_url) && (strpos($url, ':') === false))
  1324. {
  1325. $is_local_url = true;
  1326. }
  1327. // generate html
  1328. $url_target = ((isset($item['params']['target']) && (($item['params']['target'] != 0) || ($item['params']['target'] != 'false'))) ? true : false);
  1329. $url_class = empty($this->plain_html) ? ' class="post-url"' : '';
  1330. $html = '<a' . ($this->allow_styling && isset($item['params']['class']) ? '' : $url_class) . ' href="' . htmlspecialchars($url) . '"' . (($is_local_url && empty($url_target)) ? '' : (' target="_blank"' . ((!empty($item['params']['nofollow']) || $this->is_sig) ? ' rel="nofollow"' : ''))) . $this->add_extras($item['params'], $extras) . '>';
  1331. if ($config['disable_html_guests'] && !$user->data['session_logged_in'])
  1332. {
  1333. return array(
  1334. 'valid' => true,
  1335. 'html' => $lang['Links_For_Guests'],
  1336. 'allow_nested' => false,
  1337. );
  1338. }
  1339. else
  1340. {
  1341. if($show_content)
  1342. {
  1343. return array(
  1344. 'valid' => true,
  1345. 'start' => $html,
  1346. 'end' => '</a>',
  1347. );
  1348. }
  1349. else
  1350. {
  1351. return array(
  1352. 'valid' => true,
  1353. 'html' => $html . $content . '</a>',
  1354. 'allow_nested' => false,
  1355. );
  1356. }
  1357. }
  1358. }
  1359. // EMAIL
  1360. if($tag === 'email')
  1361. {
  1362. $extras = $this->allow_styling ? array('style', 'class', 'name', 'title') : array('name', 'title');
  1363. $allow_nested = true;
  1364. $strip_text = false;
  1365. $url = '';
  1366. // get url
  1367. if(!empty($item['params']['param']))
  1368. {
  1369. $url = $item['params']['param'];
  1370. }
  1371. elseif(!empty($item['params']['href']))
  1372. {
  1373. $url = $item['params']['href'];
  1374. }
  1375. elseif(!empty($item['params']['addr']))
  1376. {
  1377. $url = $item['params']['addr'];
  1378. }
  1379. else
  1380. {
  1381. $url = $content;
  1382. $pos = strpos($url, '?');
  1383. if($pos)
  1384. {
  1385. $content = substr($url, 0, $pos);
  1386. }
  1387. if(substr(strtolower($url), 0, 7) === 'mailto:')
  1388. {
  1389. $content = substr($content, 7);
  1390. }
  1391. $allow_nested = false;
  1392. $strip_text = true;
  1393. }
  1394. if(empty($url))
  1395. {
  1396. return $error;
  1397. }
  1398. // disable nested items
  1399. for($i = 0; $i < sizeof($item['items']); $i++)
  1400. {
  1401. $item['items'][$i]['valid'] = false;
  1402. }
  1403. // generate html
  1404. if(substr(strtolower($url), 0, 7) === 'mailto:')
  1405. {
  1406. $url = substr($url, 7);
  1407. }
  1408. $email = '<a' . ($this->allow_styling && isset($item['params']['class']) ? '' : ' class="post-email"') . ' href="mailto:' . htmlspecialchars($url) . '"' . $this->add_extras($item['params'], $extras) . '>' . $content . '</a>';
  1409. $pos = strpos($url, '?');
  1410. if($pos)
  1411. {
  1412. $str = substr($url, 0, $pos);
  1413. }
  1414. else
  1415. {
  1416. $str = $url;
  1417. }
  1418. if (!empty($this->plain_html))
  1419. {
  1420. $html = '<a href="mailto:' . htmlspecialchars($url) . '"' . $this->add_extras($item['params'], $extras) . '>' . $content . '</a>';
  1421. }
  1422. else
  1423. {
  1424. if (defined('IN_AJAX_CHAT'))
  1425. {
  1426. $html = htmlspecialchars(str_replace(array('@', '.'), array(' [at] ', ' [dot] '), $str));
  1427. }
  1428. else
  1429. {
  1430. $noscript = '<noscript>' . htmlspecialchars(str_replace(array('@', '.'), array(' [at] ', ' [dot] '), $str)) . '</noscript>';
  1431. // make javascript from it
  1432. $html = BBCODE_NOSMILIES_START . '<script type="text/javascript">' . "\n" . '// <![CDATA[' . "\n";
  1433. $bit_lenght = 5;
  1434. for($i = 0; $i < strlen($email); $i += $bit_lenght)
  1435. {
  1436. $str = substr($email, $i, $bit_lenght);
  1437. //$str = preg_replace('/[^A-Za-z0-9_\-@.]+/', '_', $str);
  1438. $html .= 'document.write(\'' . str_replace('/', '\/', addslashes($str)) . '\');' . "\n";
  1439. }
  1440. $html .= "\n" . '// ]]>' . "\n" . '</script>' . "\n" . $noscript . BBCODE_NOSMILIES_END;
  1441. }
  1442. }
  1443. return array(
  1444. 'valid' => true,
  1445. 'html' => $html,
  1446. //'html' => $email,
  1447. 'allow_nested' => false,
  1448. );
  1449. }
  1450. // QUOTE
  1451. if(($tag === 'quote') || ($tag === 'blockquote') || ($tag === 'ot'))
  1452. {
  1453. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  1454. if($item['iteration'] > ($config['quote_iterations']))
  1455. {
  1456. return $error;
  1457. }
  1458. // check user
  1459. $target_user = '';
  1460. $post_rev = '';
  1461. if(isset($item['params']['param']))
  1462. {
  1463. $target_user = htmlspecialchars($item['params']['param']);
  1464. }
  1465. elseif(isset($item['params']['user']))
  1466. {
  1467. $target_user = htmlspecialchars($item['params']['user']);
  1468. if(isset($item['params']['userid']) && intval($item['params']['userid']))
  1469. {
  1470. $target_user = '<a href="' . CMS_PAGE_PROFILE . '?mode=viewprofile&amp;' . POST_USERS_URL . '=' . intval($item['params']['userid']) . '">' . $target_user . '</a>';
  1471. }
  1472. }
  1473. if (!empty($this->plain_html))
  1474. {
  1475. // generate html
  1476. $html = '<blockquote>';
  1477. if($target_user)
  1478. {
  1479. $html .= '<div class="quote-user">' . $target_user . '&nbsp;' . $lang['wrote'] . ':&nbsp;' . $post_rev . '</div>';
  1480. }
  1481. return array(
  1482. 'valid' => true,
  1483. 'start' => $html,
  1484. 'end' => '</blockquote>'
  1485. );
  1486. }
  1487. else
  1488. {
  1489. // generate html
  1490. $html = '<blockquote class="quote"';
  1491. if(isset($item['params']['post']) && intval($item['params']['post']))
  1492. {
  1493. $post_rev = ($user->data['is_bot'] ? '&nbsp;' : ('[<a href="#" onclick="open_postreview(\'show_post.php?p=' . intval($item['params']['post']) . '\'); return false;" class="genmed">' . $lang['ReviewPost'] . '</a>]'));
  1494. $html .= ' cite="'. CMS_PAGE_VIEWTOPIC . '?' . POST_POST_URL . '=' . intval($item['params']['post']) . '#p' . intval($item['params']['post']) . '"';
  1495. }
  1496. $html .= '>';
  1497. if($target_user)
  1498. {
  1499. if ($tag === 'ot')
  1500. {
  1501. $html .= '<div class="quote-user"><div class="error-message" style="display:inline;">' . $lang['OffTopic'] . '</div>&nbsp;' . $target_user . ':&nbsp;' . $post_rev . '</div>';
  1502. }
  1503. else
  1504. {
  1505. $html .= '<div class="quote-user">' . $target_user . '&nbsp;' . $lang['wrote'] . ':&nbsp;' . $post_rev . '</div>';
  1506. }
  1507. }
  1508. else
  1509. {
  1510. if ($tag === 'ot')
  1511. {
  1512. $html .= '<div class="quote-nouser">&nbsp;<div class="error-message" style="display: inline;">' . $lang['OffTopic'] . '</div>:</div>';
  1513. }
  1514. else
  1515. {
  1516. $html .= '<div class="quote-nouser">' . $lang['Quote'] . ':</div>';
  1517. }
  1518. }
  1519. $html .= '<div class="post-text post-text-hide-flow">';
  1520. return array(
  1521. 'valid' => true,
  1522. 'start' => $html,
  1523. 'end' => '</div></blockquote>'
  1524. );
  1525. }
  1526. }
  1527. // INLINE CODE
  1528. if($tag === 'c')
  1529. {
  1530. $extras = $this->allow_styling ? array('style', 'name') : array('name');
  1531. $html = '<code class="inline"' . $this->add_extras($item['params'], $extras) . '>';
  1532. return array(
  1533. 'valid' => true,
  1534. 'start' => $html,
  1535. 'end' => '</code>'
  1536. );
  1537. }
  1538. // CODE, CODEBLOCK
  1539. if(($tag === 'code') || ($tag === 'codeblock'))
  1540. {
  1541. if (!empty($this->plain_html))
  1542. {
  1543. if($this->is_sig && !$config['allow_all_bbcode'])
  1544. {
  1545. return $error;
  1546. }
  1547. $text = $this->process_text($content, false, true);
  1548. $html = BBCODE_NOSMILIES_START . '<code>' . $text . '</code>' . BBCODE_NOSMILIES_END;
  1549. return array(
  1550. 'valid' => true,
  1551. 'html' => $html,
  1552. 'allow_nested' => false
  1553. );
  1554. }
  1555. else
  1556. {
  1557. // CODE
  1558. if($tag === 'code')
  1559. {
  1560. if($this->is_sig && !$config['allow_all_bbcode'])
  1561. {
  1562. return $error;
  1563. }
  1564. // replace spaces and tabs with &nbsp;
  1565. if(!defined('EXTRACT_CODE'))
  1566. {
  1567. /*
  1568. $search = array(
  1569. ' ',
  1570. "\t"
  1571. );
  1572. $replace = array(
  1573. '&nbsp; ',
  1574. '&nbsp; &nbsp; '
  1575. );
  1576. $text = str_replace($search, $replace, $this->process_text($content, false, true));
  1577. */
  1578. $text = $this->process_text($content, false, true);
  1579. }
  1580. else
  1581. {
  1582. $text = $this->process_text($content, false, true);
  1583. $search = array('[highlight]', '[/highlight]');
  1584. $replace = array('', '');
  1585. $text = str_replace($search, $replace, $text);
  1586. }
  1587. // check filename
  1588. if(isset($item['params']['filename']))
  1589. {
  1590. $item['params']['file'] = $item['params']['filename'];
  1591. }
  1592. if(defined('EXTRACT_CODE') && ($this->code_counter == EXTRACT_CODE))
  1593. {
  1594. $GLOBALS['code_text'] = $text;
  1595. if(!empty($item['params']['file']))
  1596. {
  1597. $GLOBALS['code_filename'] = $item['params']['file'];
  1598. }
  1599. }
  1600. if(substr($text, 0, 1) === "\n")
  1601. {
  1602. $text = substr($text, 1);
  1603. }
  1604. elseif(substr($text, 0, 2) === "\r\n")
  1605. {
  1606. $text = substr($text, 2);
  1607. }
  1608. $linenumbers = true;
  1609. if(isset($item['params']['linenumbers']))
  1610. {
  1611. $linenumbers = ($item['params']['linenumbers'] == 'true') ? true : false;
  1612. }
  1613. if ($linenumbers == true)
  1614. {
  1615. // convert to list
  1616. if(isset($item['params']['syntax']))
  1617. {
  1618. if ($item['params']['syntax'] == 'php')
  1619. {
  1620. /*
  1621. $html = strtr($text, array_flip(get_html_translation_table(HTML_ENTITIES)));
  1622. $html = highlight_string($html, true);
  1623. $html_search = array('<font color="', '</font', '&nbsp;');
  1624. $xhtml_replace = array('<code style="color:', '</code', ' ');
  1625. //$xhtml_replace = array('<div style="display:inline;color:', '</div', ' ');
  1626. //$xhtml_replace = array('<span style="display:inline;color:', '</span', ' ');
  1627. $html = str_replace ($html_search, $xhtml_replace, $html);
  1628. $html = '<li class="code-row"><div class="code-row-text">' . $html . '</div></li>';
  1629. */
  1630. /*
  1631. $html_search = array('<br />');
  1632. $xhtml_replace = array('</div></li><li class="code-row"><div class="code-row-text">');
  1633. $html = str_replace ($html_search, $xhtml_replace, $html);
  1634. */
  1635. //PHP Highlight - Start
  1636. $code_ary = explode("\n", $text);
  1637. $open_php_tag = 0;
  1638. $close_php_tag = 0;
  1639. for ($i = 0; $i < sizeof($code_ary); $i++)
  1640. {
  1641. if (($code_ary[$i] == '') || ($code_ary[$i] == ' ') || ($code_ary[$i] == '&nbsp;') || ($code_ary[$i] == "\n") || ($code_ary[$i] == "\r") || ($code_ary[$i] == "\n\r"))
  1642. {
  1643. $html .= '<li class="code-row"><span class="code-row-text">&nbsp;&nbsp;</span></li>';
  1644. }
  1645. else
  1646. {
  1647. $prefix = (strpos(' ' . $code_ary[$i], '&lt;?')) ? '' : '<?php ';
  1648. $suffix = (strpos(' ' . $code_ary[$i], '?&gt;')) ? '' : '?>';
  1649. $code_ary[$i] = str_replace(array('&lt;', '&gt;'), array('<', '>'), $code_ary[$i]);
  1650. $code_ary[$i] = highlight_string(strtr($prefix . $code_ary[$i] . $suffix, array_flip(get_html_translation_table(HTML_ENTITIES))), true);
  1651. $html_search = array('<code>', '</code>');
  1652. $xhtml_replace = array('', '');
  1653. $code_ary[$i] = str_replace($html_search, $xhtml_replace, $code_ary[$i]);
  1654. if ($open_php_tag || ($prefix != ''))
  1655. {
  1656. $html_search = array('&lt;?php');
  1657. $xhtml_replace = array('');
  1658. $code_ary[$i] = str_replace($html_search, $xhtml_replace, $code_ary[$i]);
  1659. }
  1660. if ($close_php_tag || ($suffix != ''))
  1661. {
  1662. $html_search = array('?&gt;&nbsp;', '?&gt;');
  1663. $xhtml_replace = array('', '');
  1664. $code_ary[$i] = str_replace($html_search, $xhtml_replace, $code_ary[$i]);
  1665. }
  1666. ($prefix == '') ? $open_php_tag++ : (($open_php_tag) ? $open_php_tag-- : '');
  1667. ($suffix == '') ? $close_php_tag++ : (($close_php_tag) ? $close_php_tag-- : '');
  1668. $html .= '<li class="code-row"><span class="code-row-text">' . $code_ary[$i] . '&nbsp;</span></li>';
  1669. }
  1670. }
  1671. $html_search = array('<font color="', '</font', '&nbsp;', '<code style="color:#0000BB"></code>', '<code style="color:#0000BB"> </code>', '> <');
  1672. $xhtml_replace = array('<code style="color:', '</code', ' ', '', '', '>&nbsp;<');
  1673. $html = str_replace($html_search, $xhtml_replace, $html);
  1674. //PHP Highlight - End
  1675. }
  1676. else
  1677. {
  1678. $search = array("\n", '[highlight]', '[/highlight]');
  1679. $replace = array('&nbsp;</span></li><li class="code-row"><span class="code-row-text">', '<span class="code-row-highlight">', '</span>');
  1680. $html = '<li class="code-row code-row-first"><span class="code-row-text">' . str_replace($search, $replace, $text) . '&nbsp;</span></li>';
  1681. }
  1682. }
  1683. else
  1684. {
  1685. $search = array("\n", '[highlight]', '[/highlight]');
  1686. $replace = array('&nbsp;</span></li><li class="code-row"><span class="code-row-text">', '<span class="code-row-highlight">', '</span>');
  1687. $html = '<li class="code-row code-row-first"><span class="code-row-text">' . str_replace($search, $replace, $text) . '&nbsp;</span></li>';
  1688. }
  1689. $str = '<li class="code-row"><div class="code-row-text">&nbsp;</div></li>';
  1690. if(substr($html, strlen($html) - strlen($str)) === $str)
  1691. {
  1692. $html = substr($html, 0, strlen($html) - strlen($str));
  1693. }
  1694. $start = isset($item['params']['start']) ? intval($item['params']['start']) : 1;
  1695. $can_download = !empty($this->code_post_id) ? $this->code_post_id : 0;
  1696. if($can_download)
  1697. {
  1698. //$download_text = ' [<a href="download.php?post=' . $can_download;
  1699. $download_text = ' [<a href="download_post.' . PHP_EXT . '?post=' . $can_download;
  1700. if($this->code_counter)
  1701. {
  1702. $download_text .= '&amp;item=' . $this->code_counter;
  1703. }
  1704. $download_text .= '">' . $lang['Download'] . '</a>]';
  1705. }
  1706. else
  1707. {
  1708. $download_text = '';
  1709. }
  1710. $code_id = substr(md5($content . mt_rand()), 0, 8);
  1711. $str = BBCODE_NOSMILIES_START . '<div class="code">';
  1712. $str .= '<div class="code-header" id="codehdr2_' . $code_id . '" style="position: relative;">' . $lang['Code'] . ':' . (empty($item['params']['file']) ? '' : ' (' . htmlspecialchars($item['params']['file']) . ')') . $download_text . ' [<a href="#" onclick="ShowHide(\'code_' . $code_id . '\',\'code2_' . $code_id . '\',\'\'); ShowHide(\'codehdr_' . $code_id . '\', \'codehdr2_' . $code_id . '\', \'\'); return false;">' . $lang['Hide'] . '</a>]</div>';
  1713. $str .= '<div class="code-header" id="codehdr_' . $code_id . '" style="position: relative; display: none;">' . $lang['Code'] . ':' . (empty($item['params']['file']) ? '' : ' (' . htmlspecialchars($item['params']['file']) . ')') . $download_text . ' [<a href="#" onclick="ShowHide(\'code_' . $code_id . '\',\'code2_' . $code_id . '\',\'\'); ShowHide(\'codehdr_' . $code_id . '\',\'codehdr2_' . $code_id . '\',\'\'); return false;">' . $lang['Show'] . '</a>]</div>';
  1714. $html = $str . '<div class="code-content" id="code_' . $code_id . '" style="position: relative;"><ol class="code-list" start="' . $start . '">' . $html . '</ol></div></div>' . BBCODE_NOSMILIES_END;
  1715. // check highlight
  1716. // format: highlight="1,2,3-10"
  1717. if(isset($item['params']['highlight']))
  1718. {
  1719. $search = '<li class="code-row';
  1720. $replace = '<li class="code-row code-row-highlight';
  1721. $search_len = strlen($search);
  1722. $replace_len = strlen($replace);
  1723. // get highlight string
  1724. $items = array();
  1725. $str = $item['params']['highlight'];
  1726. $list = explode(',', $str);
  1727. for($i = 0; $i < sizeof($list); $i++)
  1728. {
  1729. $str = trim($list[$i]);
  1730. if(strpos($str, '-'))
  1731. {
  1732. $row = explode('-', $str);
  1733. if(sizeof($row) == 2)
  1734. {
  1735. $num1 = intval($row[0]);
  1736. if($num1 == 0)
  1737. {
  1738. $num1 = 1;
  1739. }
  1740. $num2 = intval($row[1]);
  1741. if($num1 > 0 && $num2 > $num1 && ($num2 - $num1) < 256)
  1742. {
  1743. for($j=$num1; $j<=$num2; $j++)
  1744. {
  1745. $items['row' . $j] = true;
  1746. }
  1747. }
  1748. }
  1749. }
  1750. else
  1751. {
  1752. $num = intval($str);
  1753. if($num)
  1754. {
  1755. $items['row' . $num] = true;
  1756. }
  1757. }
  1758. }
  1759. if(sizeof($items))
  1760. {
  1761. // process all lines
  1762. $num = $start - 1;
  1763. $pos = strpos($html, $search);
  1764. $total = sizeof($items);
  1765. $found = 0;
  1766. while($pos !== false)
  1767. {
  1768. $num++;
  1769. if(isset($items['row' . $num]))
  1770. {
  1771. $found++;
  1772. $html = substr($html, 0, $pos) . $replace . substr($html, $pos + $search_len);
  1773. $pos += $replace_len;
  1774. }
  1775. else
  1776. {
  1777. $pos += $search_len;
  1778. }
  1779. $pos = $found < $total ? strpos($html, $search, $pos) : false;
  1780. }
  1781. }
  1782. }
  1783. // $html = BBCODE_NOSMILIES_START . '<div class="code"><div class="code-header">Code:</div><div class="code-content">' . $text . '</div></div>' . BBCODE_NOSMILIES_END;
  1784. $this->code_counter++;
  1785. return array(
  1786. 'valid' => true,
  1787. 'html' => $html,
  1788. 'allow_nested' => false
  1789. );
  1790. }
  1791. else
  1792. {
  1793. $syntax_highlight = false;
  1794. if(isset($item['params']['syntax']))
  1795. {
  1796. if ($item['params']['syntax'] == 'php')
  1797. {
  1798. $html = strtr($text, array_flip(get_html_translation_table(HTML_ENTITIES)));
  1799. $html = highlight_string($html, true);
  1800. $html_search = array('<code>', '</code>', '<font color="', '</font', '&nbsp;', '<code style="color:#0000BB"></code>', '<code style="color:#0000BB"> </code>');
  1801. $xhtml_replace = array('', '', '<code style="color:', '</code', ' ', '', '');
  1802. $html = str_replace ($html_search, $xhtml_replace, $html);
  1803. $syntax_highlight = true;
  1804. }
  1805. }
  1806. if ($syntax_highlight == false)
  1807. {
  1808. $html = $text;
  1809. $search = array('[highlight]', '[/highlight]');
  1810. $replace = array('</span><span class="code-row code-row-highlight">', '</span><span class="code-row-text">');
  1811. $html = str_replace($search, $replace, $html);
  1812. $html = str_replace(array("\n", "\r\n"), array("<br />\n", "<br />\r\n"), $html);
  1813. }
  1814. $can_download = !empty($this->code_post_id) ? $this->code_post_id : 0;
  1815. if($can_download)
  1816. {
  1817. $download_text = ' [<a href="download_post.' . PHP_EXT . '?post=' . $can_download;
  1818. if($this->code_counter)
  1819. {
  1820. $download_text .= '&amp;item=' . $this->code_counter;
  1821. }
  1822. $download_text .= '">' . $lang['Download'] . '</a>]';
  1823. }
  1824. else
  1825. {
  1826. $download_text = '';
  1827. }
  1828. $code_id = substr(md5($content . mt_rand()), 0, 8);
  1829. $str = BBCODE_NOSMILIES_START . '<div class="code">';
  1830. $str .= '<div class="code-header" id="codehdr2_' . $code_id . '" style="position: relative;">' . $lang['Code'] . ':' . (empty($item['params']['file']) ? '' : ' (' . htmlspecialchars($item['params']['file']) . ')') . $download_text . ' [<a href="#" onclick="ShowHide(\'code_' . $code_id . '\',\'code2_' . $code_id . '\',\'\'); ShowHide(\'codehdr_' . $code_id . '\',\'codehdr2_' . $code_id . '\',\'\'); return false;">' . $lang['Hide'] . '</a>] [<a href="#" onclick="select_text(\'code_' . $code_id . '\'); return false;">' . $lang['Select'] . '</a>]</div>';
  1831. $str .= '<div class="code-header" id="codehdr_' . $code_id . '" style="position: relative; display: none;">' . $lang['Code'] . ':' . (empty($item['params']['file']) ? '' : ' (' . htmlspecialchars($item['params']['file']) . ')') . $download_text . ' [<a href="#" onclick="ShowHide(\'code_' . $code_id . '\',\'code2_' . $code_id . '\',\'\'); ShowHide(\'codehdr_' . $code_id . '\',\'codehdr2_' . $code_id . '\',\'\'); return false;">' . $lang['Show'] . '</a>]</div>';
  1832. $html = $str . '<div class="code-content" id="code_' . $code_id . '" style="position: relative;"><span class="code-row-text">' . $html . '</span></div></div>' . BBCODE_NOSMILIES_END;
  1833. $this->code_counter++;
  1834. return array(
  1835. 'valid' => true,
  1836. 'html' => $html,
  1837. 'allow_nested' => false
  1838. );
  1839. }
  1840. }
  1841. // CODEBLOCK
  1842. if($tag === 'codeblock')
  1843. {
  1844. if($this->is_sig && !$config['allow_all_bbcode'])
  1845. {
  1846. return $error;
  1847. }
  1848. if(!defined('EXTRACT_CODE'))
  1849. {
  1850. /*
  1851. $search = array(
  1852. ' ',
  1853. "\t"
  1854. );
  1855. $replace = array(
  1856. '&nbsp; ',
  1857. '&nbsp; &nbsp; '
  1858. );
  1859. $text = str_replace($search, $replace, $this->process_text($content, false, true));
  1860. */
  1861. $text = $this->process_text($content, false, true);
  1862. }
  1863. else
  1864. {
  1865. $text = $this->process_text($content, false, true);
  1866. $search = array('[highlight]', '[/highlight]');
  1867. $replace = array('', '');
  1868. $text = str_replace($search, $replace, $text);
  1869. }
  1870. // check filename
  1871. if(isset($item['params']['filename']))
  1872. {
  1873. $item['params']['file'] = $item['params']['filename'];
  1874. }
  1875. if(defined('EXTRACT_CODE') && $this->code_counter == EXTRACT_CODE)
  1876. {
  1877. $GLOBALS['code_text'] = $text;
  1878. if(!empty($item['params']['file']))
  1879. {
  1880. $GLOBALS['code_filename'] = $item['params']['file'];
  1881. }
  1882. }
  1883. if(substr($text, 0, 1) === "\n")
  1884. {
  1885. $text = substr($text, 1);
  1886. }
  1887. elseif(substr($text, 0, 2) === "\r\n")
  1888. {
  1889. $text = substr($text, 2);
  1890. }
  1891. $syntax_highlight = false;
  1892. if(isset($item['params']['syntax']))
  1893. {
  1894. if ($item['params']['syntax'] == 'php')
  1895. {
  1896. $html = strtr($text, array_flip(get_html_translation_table(HTML_ENTITIES)));
  1897. $html = highlight_string($html, true);
  1898. $html_search = array('<code>', '</code>', '<font color="', '</font', '&nbsp;', '<code style="color:#0000BB"></code>', '<code style="color:#0000BB"> </code>');
  1899. $xhtml_replace = array('', '', '<code style="color:', '</code', ' ', '', '');
  1900. $html = str_replace ($html_search, $xhtml_replace, $html);
  1901. $syntax_highlight = true;
  1902. }
  1903. }
  1904. if ($syntax_highlight == false)
  1905. {
  1906. $html = $text;
  1907. $search = array('[highlight]', '[/highlight]');
  1908. $replace = array('</span><span class="code-row code-row-highlight">', '</span><span class="code-row-text">');
  1909. $html = str_replace($search, $replace, $html);
  1910. $html = str_replace(array("\n", "\r\n"), array("<br />\n", "<br />\r\n"), $html);
  1911. }
  1912. $can_download = !empty($this->code_post_id) ? $this->code_post_id : 0;
  1913. if($can_download)
  1914. {
  1915. $download_text = ' [<a href="download_post.' . PHP_EXT . '?post=' . $can_download;
  1916. if($this->code_counter)
  1917. {
  1918. $download_text .= '&amp;item=' . $this->code_counter;
  1919. }
  1920. $download_text .= '">' . $lang['Download'] . '</a>]';
  1921. }
  1922. else
  1923. {
  1924. $download_text = '';
  1925. }
  1926. $code_id = substr(md5($content . mt_rand()), 0, 8);
  1927. $str = BBCODE_NOSMILIES_START . '<div class="code">';
  1928. $str .= '<div class="code-header" id="codehdr2_' . $code_id . '" style="position: relative;">' . $lang['Code'] . ':' . (empty($item['params']['file']) ? '' : ' (' . htmlspecialchars($item['params']['file']) . ')') . $download_text . ' [<a href="#" onclick="ShowHide(\'code_' . $code_id . '\',\'code2_' . $code_id . '\',\'\'); ShowHide(\'codehdr_' . $code_id . '\',\'codehdr2_' . $code_id . '\',\'\'); return false;">' . $lang['Hide'] . '</a>] [<a href="#" onclick="select_text(\'code_' . $code_id . '\'); return false;">' . $lang['Select'] . '</a>]</div>';
  1929. $str .= '<div class="code-header" id="codehdr_' . $code_id . '" style="position: relative; display: none;">' . $lang['Code'] . ':' . (empty($item['params']['file']) ? '' : ' (' . htmlspecialchars($item['params']['file']) . ')') . $download_text . ' [<a href="#" onclick="ShowHide(\'code_' . $code_id . '\',\'code2_' . $code_id . '\',\'\'); ShowHide(\'codehdr_' . $code_id . '\',\'codehdr2_' . $code_id . '\',\'\'); return false;">' . $lang['Show'] . '</a>]</div>';
  1930. $html = $str . '<div class="code-content" id="code_' . $code_id . '" style="position: relative;"><span class="code-row-text">' . $html . '</span></div></div>' . BBCODE_NOSMILIES_END;
  1931. $this->code_counter++;
  1932. return array(
  1933. 'valid' => true,
  1934. 'html' => $html,
  1935. 'allow_nested' => false
  1936. );
  1937. }
  1938. }
  1939. }
  1940. // HIDE
  1941. if($tag === 'hide')
  1942. {
  1943. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  1944. if (!empty($this->plain_html)) return $error;
  1945. if($item['iteration'] > 1)
  1946. {
  1947. return $error;
  1948. }
  1949. $show = false;
  1950. if(defined('IS_ICYPHOENIX') && $user->data['session_logged_in'])
  1951. {
  1952. if (($user->data['user_level'] == ADMIN) || ($user->data['user_level'] == MOD))
  1953. {
  1954. $show = true;
  1955. }
  1956. else
  1957. {
  1958. $sql = "SELECT p.poster_id, p.topic_id
  1959. FROM " . POSTS_TABLE . " p
  1960. WHERE p.topic_id = " . intval($topic_id) . "
  1961. AND p.poster_id = " . $user->data['user_id'];
  1962. $db->sql_return_on_error(true);
  1963. $result = $db->sql_query($sql);
  1964. $db->sql_return_on_error(false);
  1965. if ($result)
  1966. {
  1967. $show = $db->sql_numrows($result) ? true : false;
  1968. $db->sql_freeresult($result);
  1969. }
  1970. $sql = "SELECT *
  1971. FROM " . POSTS_LIKES_TABLE . "
  1972. WHERE topic_id = " . intval($topic_id) . "
  1973. AND user_id = " . $user->data['user_id'];
  1974. $db->sql_return_on_error(true);
  1975. $result = $db->sql_query($sql);
  1976. $db->sql_return_on_error(false);
  1977. if ($result)
  1978. {
  1979. $show = ($db->sql_numrows($result) || ($show == true))? true : false;
  1980. $db->sql_freeresult($result);
  1981. }
  1982. }
  1983. }
  1984. // generate html
  1985. $html = '<blockquote class="quote"><div class="quote-nouser">' . $lang['xs_bbc_hide_message'] . ':</div><div class="post-text post-text-hide-flow">';
  1986. if(!$show)
  1987. {
  1988. return array(
  1989. 'valid' => true,
  1990. 'html' => $html . $lang['xs_bbc_hide_message_explain'] . '</div></blockquote>',
  1991. 'allow_nested' => false,
  1992. );
  1993. }
  1994. else
  1995. {
  1996. return array(
  1997. 'valid' => true,
  1998. 'start' => $html,
  1999. 'end' => '</div></blockquote>'
  2000. );
  2001. }
  2002. }
  2003. // SPOILER
  2004. if($tag === 'spoiler')
  2005. {
  2006. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  2007. if (!empty($this->plain_html)) return $error;
  2008. if($item['iteration'] > 1)
  2009. {
  2010. return $error;
  2011. }
  2012. $spoiler_id = substr(md5($content . mt_rand()), 0, 8);
  2013. $str = '<div class="spoiler">';
  2014. $str .= '<div class="code-header" id="spoilerhdr_' . $spoiler_id . '" style="position: relative;">' . $lang['bbcb_mg_spoiler'] . ': [ <a href="#" onclick="ShowHide(\'spoiler_' . $spoiler_id . '\', \'spoiler2_' . $spoiler_id . '\', \'\'); ShowHide(\'spoilerhdr_' . $spoiler_id . '\', \'spoilerhdr2_' . $spoiler_id . '\', \'\'); return false;">' . $lang['Show'] . '</a> ]</div>';
  2015. $str .= '<div class="code-header" id="spoilerhdr2_' . $spoiler_id . '" style="position: relative; display: none;">' . $lang['bbcb_mg_spoiler'] . ': [ <a href="#" onclick="ShowHide(\'spoiler_' . $spoiler_id . '\', \'spoiler2_' . $spoiler_id . '\', \'\'); ShowHide(\'spoilerhdr_' . $spoiler_id . '\', \'spoilerhdr2_' . $spoiler_id . '\', \'\'); return false;">' . $lang['Hide'] . '</a> ]</div>';
  2016. $str .= '<div class="spoiler-content" id="spoiler2_' . $spoiler_id . '" style="position: relative; display: none;">' . $html;
  2017. return array(
  2018. 'valid' => true,
  2019. 'start' => $str,
  2020. 'end' => '</div></div>'
  2021. );
  2022. }
  2023. // USER
  2024. // Insert the username and avatar for the selected id
  2025. if($tag === 'user')
  2026. {
  2027. if($this->is_sig) return $error;
  2028. if (!empty($this->plain_html)) return $error;
  2029. if(isset($item['params']['param']))
  2030. {
  2031. $bb_userid = (int) $item['params']['param'];
  2032. }
  2033. else
  2034. {
  2035. $bb_userid = (int) $content;
  2036. }
  2037. if ($bb_userid < 2)
  2038. {
  2039. return $error;
  2040. }
  2041. $bb_user_data = get_userdata($bb_userid);
  2042. if (empty($bb_user_data))
  2043. {
  2044. return $error;
  2045. }
  2046. $bb_name_link = colorize_username($bb_user_data['user_id'], $bb_user_data['username'], $bb_user_data['user_color'], $bb_user_data['user_active']);
  2047. $bb_avatar_img = user_get_avatar($bb_user_data['user_id'], $bb_user_data['user_level'], $bb_user_data['user_avatar'], $bb_user_data['user_avatar_type'], $bb_user_data['user_allowavatar'], '', 30);
  2048. $html = $bb_avatar_img . ' ' . $bb_name_link;
  2049. return array(
  2050. 'valid' => true,
  2051. 'html' => $html
  2052. );
  2053. }
  2054. // LANGVAR
  2055. // Insert the content of a lang var into post... maybe we need to filter something?
  2056. if($tag === 'langvar')
  2057. {
  2058. if(isset($item['params']['param']))
  2059. {
  2060. $langvar = $item['params']['param'];
  2061. }
  2062. else
  2063. {
  2064. $langvar = $content;
  2065. }
  2066. $html = (isset($lang[$langvar]) ? $lang[$langvar] : '');
  2067. return array(
  2068. 'valid' => true,
  2069. 'html' => $html
  2070. );
  2071. }
  2072. // LANGUAGE
  2073. // Parse the content only if in the same language of the user viewing it!!!
  2074. if($tag === 'language')
  2075. {
  2076. $language = '';
  2077. if(isset($item['params']['param']))
  2078. {
  2079. $language = $item['params']['param'];
  2080. }
  2081. $content = ($config['default_lang'] != $language) ? '' : $content;
  2082. // We need this trick to process BBCodes withing language BBCode
  2083. if(empty($content))
  2084. {
  2085. return array(
  2086. 'valid' => true,
  2087. 'html' => '',
  2088. );
  2089. }
  2090. else
  2091. {
  2092. return array(
  2093. 'valid' => true,
  2094. 'start' => '',
  2095. 'end' => ''
  2096. );
  2097. }
  2098. }
  2099. // SEARCH
  2100. if($tag === 'search')
  2101. {
  2102. if(empty($content)) return $error;
  2103. if (!empty($this->plain_html)) return $error;
  2104. $str = '<a href="' . CMS_PAGE_SEARCH . '?search_keywords=' . urlencode($this->process_text($content)) . '">';
  2105. return array(
  2106. 'valid' => true,
  2107. 'start' => $str,
  2108. 'end' => '</a>'
  2109. );
  2110. }
  2111. // TAG
  2112. if($tag === 'tag')
  2113. {
  2114. if(empty($content)) return $error;
  2115. if (!empty($this->plain_html)) return $error;
  2116. $str = '<a href="tags.' . PHP_EXT . '?tag_text=' . urlencode($this->process_text($content)) . '">';
  2117. return array(
  2118. 'valid' => true,
  2119. 'start' => $str,
  2120. 'end' => '</a>'
  2121. );
  2122. }
  2123. // Random number or quote (quote not implemented yet)
  2124. if($tag === 'random')
  2125. {
  2126. $max_n = 6;
  2127. $max_n = intval((isset($item['params']['param']) ? $item['params']['param'] : (isset($item['params']['max']) ? $item['params']['max'] : 6)));
  2128. $max_n = ($max_n <= 0) ? 6 : $max_n;
  2129. /*
  2130. include_once(IP_ROOT_PATH . 'language/lang_' . $config['default_lang'] . '/lang_randomquote.' . PHP_EXT);
  2131. $randomquote_phrase = $randomquote[rand(0, sizeof($randomquote) - 1)];
  2132. */
  2133. $html = rand(1, $max_n);
  2134. return array(
  2135. 'valid' => true,
  2136. 'html' => $html
  2137. );
  2138. }
  2139. // MARQUEE
  2140. if($tag === 'marquee')
  2141. {
  2142. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  2143. if (!empty($this->plain_html)) return $error;
  2144. $extras = $this->allow_styling ? array('style', 'class') : array();
  2145. $directions_array = array('up', 'right', 'down', 'left');
  2146. $default_param = 'right';
  2147. $direction = (isset($item['params']['param']) ? $item['params']['param'] : (isset($item['params']['direction']) ? $item['params']['direction'] : $default_param));
  2148. $direction = (in_array($direction, $directions_array) ? $direction : $default_param);
  2149. $default_scroll = '120';
  2150. $scrolldelay = (isset($item['params']['scrolldelay']) ? intval($item['params']['scrolldelay']) : $default_scroll);
  2151. $scrolldelay = ((($scrolldelay > 10) && ($scrolldelay < 601)) ? $scrolldelay : $default_scroll);
  2152. $default_behavior = 'scroll';
  2153. $behavior = (isset($item['params']['behavior']) ? intval($item['params']['behavior']) : $default_behavior);
  2154. $behavior = ((($behavior === 'alternate') || ($behavior === 'slide')) ? $behavior : $default_behavior);
  2155. $html = '<marquee behavior="' . $behavior . '" direction="' . $direction . '" scrolldelay="' . $scrolldelay . '" loop="true" onmouseover="this.stop()" onmouseout="this.start()">';
  2156. return array(
  2157. 'valid' => true,
  2158. 'start' => $html,
  2159. 'end' => '</marquee>',
  2160. );
  2161. }
  2162. // Active Content - BEGIN
  2163. // Added by Tom XS2 Build 054
  2164. if ($config['switch_bbcb_active_content'] == 1)
  2165. {
  2166. // FLASH, SWF, FLV, VIDEO, REAL, QUICK, STREAM, EMFF, VIMEO, YOUTUBE, GOOGLEVIDEO
  2167. if(($tag === 'flash') || ($tag === 'swf') || ($tag === 'flv') || ($tag === 'video') || ($tag === 'ram') || ($tag === 'quick') || ($tag === 'stream') || ($tag === 'emff') || ($tag === 'mp3') || ($tag === 'vimeo') || ($tag === 'youtube') || ($tag === 'googlevideo'))
  2168. {
  2169. if($this->is_sig && !$config['allow_all_bbcode'])
  2170. {
  2171. return $error;
  2172. }
  2173. $content = $this->process_text(isset($item['params']['param']) ? $item['params']['param'] : $content);
  2174. $color_1 = $this->valid_color((isset($item['params']['colors']) ? $item['params']['colors'] : false));
  2175. $color_2 = $this->valid_color((isset($item['params']['colore']) ? $item['params']['colore'] : false));
  2176. // 4/3 YouTube width and height: 425x350
  2177. // 16/9 YouTube width and height: 640x385
  2178. $default_width = 320;
  2179. $default_height = 240;
  2180. $default_ratio = $default_width / $default_height;
  2181. if (($tag === 'vimeo') || ($tag === 'youtube') || ($tag === 'googlevideo'))
  2182. {
  2183. $default_width = 640;
  2184. $default_height = 385;
  2185. $default_ratio = 16 / 9;
  2186. }
  2187. $width_array = array(240, 270, 300, 320, 400, 425, 426, 480, 540, 600, 640, 720, 854);
  2188. $height_array = array(135, 152, 169, 180, 202, 203, 225, 240, 270, 300, 304, 319, 320, 337, 338, 360, 405, 420, 450, 480, 540, 640);
  2189. // Allows both WIDTH and W
  2190. if (isset($item['params']['width']) || isset($item['params']['w']))
  2191. {
  2192. $item['params']['width'] = isset($item['params']['width']) ? $item['params']['width'] : $item['params']['w'];
  2193. }
  2194. $width = (isset($item['params']['width']) ? intval($item['params']['width']) : $default_width);
  2195. $width = ((($width > 10) && ($width < 855)) ? $width : $default_width);
  2196. // Allows both HEIGHT and H
  2197. if (isset($item['params']['height']) || isset($item['params']['h']))
  2198. {
  2199. $item['params']['height'] = isset($item['params']['height']) ? $item['params']['width'] : $item['params']['h'];
  2200. }
  2201. $height = (isset($item['params']['height']) ? intval($item['params']['height']) : $default_height);
  2202. $height = ((($height > 10) && ($height < 641)) ? $height : $default_height);
  2203. // Width and Height check-in...
  2204. // 4/3 YouTube width and height: 425x350
  2205. // 16/9 YouTube width and height: 640x385
  2206. if (($tag === 'vimeo') || ($tag === 'youtube') || ($tag === 'googlevideo'))
  2207. {
  2208. // Consider that YouTube HTML code may need 25px extra in height to display the control bar... hence the edited code below!
  2209. $width = in_array($width, $width_array) ? $width : 640;
  2210. $height = (in_array($height, $height_array) || in_array($height + 25, $height_array)) ? $height : 385;
  2211. }
  2212. // Set Ratio
  2213. if (isset($item['params']['ratio']) || isset($item['params']['r']))
  2214. {
  2215. $item['params']['ratio'] = isset($item['params']['ratio']) ? $item['params']['ratio'] : $item['params']['r'];
  2216. $ratio = (isset($item['params']['ratio']) ? floatval($item['params']['ratio']) : $default_ratio);
  2217. if (($ratio > 1) && ($ratio < 2))
  2218. {
  2219. $height = round($width / $ratio, 0);
  2220. if (($tag === 'vimeo') || ($tag === 'youtube') || ($tag === 'googlevideo'))
  2221. {
  2222. // Adds extra height for the control bar... to be checked for futures updates...
  2223. $height = $height + 25;
  2224. }
  2225. }
  2226. }
  2227. if (($tag === 'flash') || ($tag === 'swf'))
  2228. {
  2229. $html = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0" width="' . $width . '" height="' . $height . '"><param name="movie" value="' . $content . '"><param name="quality" value="high"><param name="scale" value="noborder"><param name="wmode" value="transparent"><param name="bgcolor" value="#000000"><embed src="' . $content . '" quality="high" scale="noborder" wmode="transparent" bgcolor="#000000" width="' . $width . '" height="' . $height . '" type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"></embed></object>';
  2230. }
  2231. elseif ($tag === 'flv')
  2232. {
  2233. $html = '<object type="application/x-shockwave-flash" width="' . $width . '" height="' . $height . '" wmode="transparent" data="flv_player.swf?file=' . $content . '&amp;autoStart=false"><param name="movie" value="flv_player.swf?file=' . $content . '&amp;autoStart=false"/><param name="wmode" value="transparent"/></object>';
  2234. }
  2235. elseif ($tag === 'video')
  2236. {
  2237. $html = '<div align="center"><embed src="' . $content . '" width="' . $width . '" height="' . $height . '" autostart="false"></embed></div>';
  2238. }
  2239. elseif ($tag === 'ram')
  2240. {
  2241. $html = '<div align="center"><embed src="' . $content . '" align="center" width="275" height="40" type="audio/x-pn-realaudio-plugin" console="cons" controls="ControlPanel" autostart="false"></embed></div>';
  2242. }
  2243. elseif ($tag === 'quick')
  2244. {
  2245. $html = '<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="//www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0" width="' . $width . '" height="' . $height . '" align="middle"><param name="controller" value="true"><param name="type" value="video/quicktime"><param name="autoplay" value="true"><param name="target" value="myself"><param name="src" value="' . $content . '"><param name="pluginspage" value="//www.apple.com/quicktime/download/indext.html"><param name="kioskmode" value="true"><embed src="' . $content . '" width="' . $width . '" height="' . $height . '" align="middle" kioskmode="true" controller="true" target="myself" type="video/quicktime" border="0" pluginspage="//www.apple.com/quicktime/download/indext.html"></embed></object>';
  2246. }
  2247. elseif ($tag === 'stream')
  2248. {
  2249. $html = '<object id="wmp" width="' . $width . '" height="' . $height . '" classid="CLSID:22d6f312-b0f6-11d0-94ab-0080c74c7e95" codebase="//activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,0,0,0" standby="Loading Microsoft Windows Media Player components..." type="application/x-oleobject"><param name="FileName" value="' . $content . '"><param name="ShowControls" value="1"><param name="ShowDisplay" value="0"><param name="ShowStatusBar" value="1"><param name="AutoSize" value="1"><embed type="application/x-mplayer2" pluginspage="//www.microsoft.com/windows95/downloads/contents/wurecommended/s_wufeatured/mediaplayer/default.asp" src="' . $content . '" name="MediaPlayer2" showcontrols="1" showdisplay="0" showstatusbar="1" autosize="1" visible="1" animationatstart="0" transparentatstart="1" loop="0" height="70" width="300"></embed></object>';
  2250. }
  2251. elseif (($tag === 'emff') || ($tag === 'mp3'))
  2252. {
  2253. $html = '<object data="emff_player.swf" type="application/x-shockwave-flash" width="200" height="55" align="top" ><param name="FlashVars" value="src=' . $content . '" /><param name="movie" value="emff_player.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#f8f8f8" /></object>';
  2254. }
  2255. elseif ($tag === 'vimeo')
  2256. {
  2257. $html = '<object type="application/x-shockwave-flash" width="' . $width . '" height="' . $height . '" data="//www.vimeo.com/moogaloop.swf?clip_id=' . $content . '"><param name="quality" value="best" /><param name="allowfullscreen" value="true" /><param name="scale" value="showAll" /><param name="movie" value="//www.vimeo.com/moogaloop.swf?clip_id=' . $content . '" /></object><br /><a href="//www.vimeo.com/moogaloop.swf?clip_id=' . $content . '" target="_blank">Link</a><br />';
  2258. }
  2259. elseif ($tag === 'youtube')
  2260. {
  2261. //check URL type
  2262. $video_file = $content;
  2263. if (strpos($content, 'youtu.be') !== false)
  2264. {
  2265. // Short URL
  2266. // parse the URL to split it in parts
  2267. $parsed_url = parse_url($content);
  2268. // get the path and delete the initial / simbol
  2269. $video_file = str_replace('/', '', $parsed_url['path']);
  2270. }
  2271. elseif (strrpos($content, 'youtube') !== false)
  2272. {
  2273. // Long URL
  2274. // parse the URL to split it in parts
  2275. $parsed_url = parse_url($content);
  2276. // get the query part (vars) and parse them into name and value
  2277. parse_str($parsed_url['query'], $qvars);
  2278. // send the value to the destination var.
  2279. $video_file = $qvars['v'];
  2280. }
  2281. $video_file = preg_replace('/[^A-Za-z0-9_-]+/', '', $video_file);
  2282. $color_append = '';
  2283. if ($color_1 || $color_2)
  2284. {
  2285. $color_append .= ($color_1 ? ('&amp;color1=0x' . str_replace('#', '', $color_1)) : '');
  2286. $color_append .= ($color_2 ? ('&amp;color2=0x' . str_replace('#', '', $color_2)) : '');
  2287. }
  2288. $video_link = '<br /><a href="//youtube.com/watch?v=' . $video_file . $color_append . '" target="_blank">YouTube Link</a><br />';
  2289. // OLD OBJECT Version
  2290. //$html = '<object width="' . $width . '" height="' . $height . '"><param name="movie" value="//www.youtube.com/v/' . $video_file . $color_append . '" /><embed src="//www.youtube.com/v/' . $video_file . $color_append . '" type="application/x-shockwave-flash" width="' . $width . '" height="' . $height . '"></embed></object>' . $video_link;
  2291. // IFRAME Version
  2292. $html = '<iframe width="' . $width . '" height="' . $height . '" src="//www.youtube.com/embed/' . $video_file . '?autoplay=0' . $color_append . '" frameborder="0"></iframe>' . $video_link;
  2293. }
  2294. elseif ($tag === 'googlevideo')
  2295. {
  2296. $html = '<object width="' . $width . '" height="' . $height . '"><param name="movie" value="//video.google.com/googleplayer.swf?docId=' . $content . '"></param><embed style="width:' . $width . 'px; height:' . $height . 'px;" id="VideoPlayback" align="middle" type="application/x-shockwave-flash" src="//video.google.com/googleplayer.swf?docId=' . $content . '" allowScriptAccess="sameDomain" quality="best" bgcolor="#f8f8f8" scale="noScale" salign="TL" FlashVars="playerMode=embedded"></embed></object><br /><a href="//video.google.com/videoplay?docid=' . $content . '" target="_blank">Link</a><br />';
  2297. }
  2298. return array(
  2299. 'valid' => true,
  2300. 'html' => $html
  2301. );
  2302. }
  2303. }
  2304. // Active Content - END
  2305. // SMILEY
  2306. if($tag === 'smiley')
  2307. {
  2308. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  2309. if (!empty($this->plain_html)) return $error;
  2310. $extras = $this->allow_styling ? array('style', 'class') : array();
  2311. $text = htmlspecialchars((isset($item['params']['param']) ? $item['params']['param'] : (isset($item['params']['text']) ? $item['params']['text'] : $content)));
  2312. if(isset($item['params']['smilie']))
  2313. {
  2314. if (($item['params']['smilie'] == 'standard') || ($item['params']['smilie'] == 'random'))
  2315. {
  2316. //$smilie = $item['params']['smilie'];
  2317. $smilie = '1';
  2318. }
  2319. else
  2320. {
  2321. $smilie = intval($item['params']['smilie']);
  2322. }
  2323. }
  2324. else
  2325. {
  2326. $smilie = '1';
  2327. }
  2328. $default_fontcolor = '000000';
  2329. $fontcolor = $this->valid_color((isset($item['params']['fontcolor']) ? $item['params']['fontcolor'] : $default_fontcolor));
  2330. $fontcolor = (($fontcolor === false) ? $default_fontcolor : str_replace('#', '', $fontcolor));
  2331. $default_shadowcolor = '888888';
  2332. $shadowcolor = $this->valid_color((isset($item['params']['shadowcolor']) ? $item['params']['shadowcolor'] : $default_shadowcolor));
  2333. $shadowcolor = (($shadowcolor === false) ? $default_shadowcolor : str_replace('#', '', $shadowcolor));
  2334. $default_shieldshadow = 0;
  2335. $shieldshadow = (isset($item['params']['shieldshadow']) ? (($item['params']['shieldshadow'] == 1) ? 1 : $default_param) : $default_param);
  2336. //$html = '<img src="text2shield.' . PHP_EXT . '?smilie=' . $smilie . '&amp;fontcolor=' . $fontcolor . '&amp;shadowcolor=' . $shadowcolor . '&amp;shieldshadow=' . $shieldshadow . '&amp;text=' . $text . '" alt="Smiley" title="Smiley" />';
  2337. $html = '<img src="text2shield.' . PHP_EXT . '?smilie=' . $smilie . '&amp;fontcolor=' . $fontcolor . '&amp;shadowcolor=' . $shadowcolor . '&amp;shieldshadow=' . $shieldshadow . '&amp;text=' . urlencode(ip_utf8_decode($text)) . '" alt="'. $text . '" title="' . $text . '" />';
  2338. return array(
  2339. 'valid' => true,
  2340. 'html' => $html,
  2341. 'allow_nested' => false,
  2342. );
  2343. }
  2344. // OPACITY
  2345. if($tag === 'opacity')
  2346. {
  2347. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  2348. if (!empty($this->plain_html)) return $error;
  2349. if(isset($item['params']['param']))
  2350. {
  2351. $opacity = intval($item['params']['param']);
  2352. if (($opacity > 0) && ($opacity < 101))
  2353. {
  2354. $opacity = $opacity;
  2355. }
  2356. }
  2357. else
  2358. {
  2359. $opacity = '100';
  2360. }
  2361. $opacity_dec = $opacity / 100;
  2362. $html = '<div class="opacity" style="opacity: ' . $opacity_dec . '; filter: Alpha(Opacity=' . $opacity . ');">';
  2363. return array(
  2364. 'valid' => true,
  2365. 'start' => $html,
  2366. 'end' => '</div>',
  2367. );
  2368. }
  2369. // FADE
  2370. if($tag === 'fade')
  2371. {
  2372. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  2373. if (!empty($this->plain_html)) return $error;
  2374. if(isset($item['params']['param']))
  2375. {
  2376. $opacity = intval($item['params']['param']);
  2377. if (($opacity > 0) && ($opacity < 101))
  2378. {
  2379. $opacity = $opacity;
  2380. }
  2381. }
  2382. else
  2383. {
  2384. $opacity = '100';
  2385. }
  2386. $opacity_dec = $opacity / 100;
  2387. $html = '<div style="display: inline; height: 1; opacity: ' . $opacity_dec . '; filter: Alpha(Opacity=' . $opacity . ',FinishOpacity=0,Style=1,StartX=0,FinishX=100%);">';
  2388. //$html = '<div style="display:inline;height:1;filter:Alpha(Opacity=' . $opacity . ',FinishOpacity=0,Style=1,StartX=0,FinishX=100%);">';
  2389. return array(
  2390. 'valid' => true,
  2391. 'start' => $html,
  2392. 'end' => '</div>',
  2393. );
  2394. }
  2395. // IE AND HTML 4 ONLY TAGS - BEGIN
  2396. // Let's add a global IF so we can skip them all in once to speed up things...
  2397. // Enable these tags only if you know how to make them work...
  2398. if(($tag === 'glow') || ($tag === 'shadow') || ($tag === 'blur') || ($tag === 'wave') || ($tag === 'fliph') || ($tag === 'flipv'))
  2399. {
  2400. return array(
  2401. 'valid' => true,
  2402. 'start' => '',
  2403. 'end' => '',
  2404. );
  2405. }
  2406. /*
  2407. if(($tag === 'glow') || ($tag === 'shadow') || ($tag === 'blur') || ($tag === 'wave') || ($tag === 'fliph') || ($tag === 'flipv'))
  2408. {
  2409. // GLOW
  2410. if($tag === 'glow')
  2411. {
  2412. $default_color = '#fffffa';
  2413. $color = $this->valid_color((isset($item['params']['param']) ? $item['params']['param'] : (isset($item['params']['color']) ? $item['params']['color'] : $default_color)));
  2414. if($color === false)
  2415. {
  2416. return $error;
  2417. }
  2418. $html = '<div style="display: inline; filter: glow(color=' . $color . '); height: 20px;">';
  2419. return array(
  2420. 'valid' => true,
  2421. 'start' => $html,
  2422. 'end' => '</div>',
  2423. );
  2424. }
  2425. // SHADOW
  2426. if($tag === 'shadow')
  2427. {
  2428. $default_color = '#666666';
  2429. $color = $this->valid_color((isset($item['params']['param']) ? $item['params']['param'] : (isset($item['params']['color']) ? $item['params']['color'] : $default_color)));
  2430. if($color === false)
  2431. {
  2432. return $error;
  2433. }
  2434. $html = '<div style="display: inline; filter: shadow(color=' . $color . '); height: 20;">';
  2435. return array(
  2436. 'valid' => true,
  2437. 'start' => $html,
  2438. 'end' => '</div>',
  2439. );
  2440. }
  2441. // BLUR
  2442. if($tag === 'blur')
  2443. {
  2444. if($this->is_sig && !$config['allow_all_bbcode'])
  2445. {
  2446. return $error;
  2447. }
  2448. if(isset($item['params']['param']))
  2449. {
  2450. $strenght = intval($item['params']['param']);
  2451. if (($strenght > 0) && ($strenght < 101))
  2452. {
  2453. $strenght = $strenght;
  2454. }
  2455. }
  2456. else
  2457. {
  2458. $strenght = '100';
  2459. }
  2460. $strenght_dec = $strenght / 100;
  2461. $html = '<div style="display: inline; width: 100%; height: 20; filter: Blur(add=1,direction=270,strength=' . $strenght . ');">';
  2462. return array(
  2463. 'valid' => true,
  2464. 'start' => $html,
  2465. 'end' => '</div>',
  2466. );
  2467. }
  2468. // WAVE
  2469. if($tag === 'wave')
  2470. {
  2471. if($this->is_sig && !$config['allow_all_bbcode'])
  2472. {
  2473. return $error;
  2474. }
  2475. if(isset($item['params']['param']))
  2476. {
  2477. $strenght = intval($item['params']['param']);
  2478. if (($strenght > 0) && ($strenght < 101))
  2479. {
  2480. $strenght = $strenght;
  2481. }
  2482. }
  2483. else
  2484. {
  2485. $strenght = '100';
  2486. }
  2487. $strenght_dec = $strenght / 100;
  2488. $html = '<div style="display: inline; width: 100%; height: 20; filter: Wave(add=1,direction=270,strength=' . $strenght . ');">';
  2489. return array(
  2490. 'valid' => true,
  2491. 'start' => $html,
  2492. 'end' => '</div>',
  2493. );
  2494. }
  2495. // FLIPH, FLIPV
  2496. if(($tag === 'fliph') || ($tag === 'flipv'))
  2497. {
  2498. if($this->is_sig && !$config['allow_all_bbcode'])
  2499. {
  2500. return $error;
  2501. }
  2502. $html = '<div style="display: inline; filter: ' . $tag . '; height: 1;">';
  2503. return array(
  2504. 'valid' => true,
  2505. 'start' => $html,
  2506. 'end' => '</div>',
  2507. );
  2508. }
  2509. }
  2510. */
  2511. // OLD IE AND HTML 4 ONLY TAGS - END
  2512. // TEX
  2513. if($tag === 'tex')
  2514. {
  2515. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  2516. if (!empty($this->plain_html)) return $error;
  2517. $html = '<img src="cgi-bin/mimetex.cgi?' . $content . '" alt="" border="0" style="vertical-align: middle;" />';
  2518. return array(
  2519. 'valid' => true,
  2520. 'html' => $html,
  2521. 'allow_nested' => false,
  2522. );
  2523. }
  2524. // TABLE
  2525. if($tag === 'table')
  2526. {
  2527. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  2528. if (!empty($this->plain_html)) return $error;
  2529. // additional allowed parameters
  2530. $extras = $this->allow_styling ? array('style', 'class', 'align', 'width', 'height', 'border', 'cellspacing', 'cellpadding') : array('style', 'class', 'align', 'width');
  2531. if(isset($item['params']['param']))
  2532. {
  2533. $table_class = $item['params']['param'];
  2534. }
  2535. else
  2536. {
  2537. $table_class = '';
  2538. }
  2539. for($i = 0; $i < sizeof($extras); $i++)
  2540. {
  2541. if(!empty($item['params'][$extras[$i]]))
  2542. {
  2543. if($extras[$i] === 'style')
  2544. {
  2545. $style = $this->valid_style($item['params']['style']);
  2546. if($style !== false)
  2547. {
  2548. $params['style'] = $style;
  2549. }
  2550. }
  2551. else
  2552. {
  2553. $params[$extras[$i]] = $item['params'][$extras[$i]];
  2554. }
  2555. }
  2556. }
  2557. if (!isset($params['class']))
  2558. {
  2559. $params['class'] = $table_class;
  2560. }
  2561. // generate html
  2562. $html = '<table';
  2563. foreach($params as $var => $value)
  2564. {
  2565. $html .= ' ' . $var . '="' . $this->process_text($value) . '"';
  2566. }
  2567. $html .= ' >' . $content . '</table>';
  2568. return array(
  2569. 'valid' => true,
  2570. 'html' => $html,
  2571. 'allow_nested' => true,
  2572. );
  2573. }
  2574. /*
  2575. // TR
  2576. if($tag === 'tr')
  2577. {
  2578. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  2579. // generate html
  2580. $html = '<tr>' . $content . '</tr>';
  2581. return array(
  2582. 'valid' => true,
  2583. 'html' => $html,
  2584. 'allow_nested' => true,
  2585. );
  2586. }
  2587. // TD
  2588. if($tag === 'td')
  2589. {
  2590. if($this->is_sig && !$config['allow_all_bbcode']) return $error;
  2591. // additional allowed parameters
  2592. $extras = $this->allow_styling ? array('class', 'align', 'width', 'height') : array('class', 'align', 'width', 'height');
  2593. for($i = 0; $i < sizeof($extras); $i++)
  2594. {
  2595. if(!empty($item['params'][$extras[$i]]))
  2596. {
  2597. if($extras[$i] === 'style')
  2598. {
  2599. $style = $this->valid_style($item['params']['style']);
  2600. if($style !== false)
  2601. {
  2602. $params['style'] = $style;
  2603. }
  2604. }
  2605. else
  2606. {
  2607. $params[$extras[$i]] = $item['params'][$extras[$i]];
  2608. }
  2609. }
  2610. }
  2611. // generate html
  2612. $html = '<td';
  2613. foreach($params as $var => $value)
  2614. {
  2615. $html .= ' ' . $var . '="' . $this->process_text($value) . '"';
  2616. }
  2617. $html .= ' >' . $content . '</td>';
  2618. return array(
  2619. 'valid' => true,
  2620. 'html' => $html,
  2621. 'allow_nested' => true,
  2622. );
  2623. }
  2624. */
  2625. // To use IFRAMES you just need to decomment this block of code (and allow the tag on top of this file)... good luck!
  2626. // IFRAME
  2627. //<iframe src="index.html" scrolling="no" width="100%" height="190" frameborder="0" marginheight="0" marginwidth="0"></iframe>
  2628. //[iframe height=100]docs/index.html[/iframe]
  2629. //[iframe src=docs/index.html height=100] [/iframe]
  2630. /*
  2631. if($tag === 'iframe')
  2632. {
  2633. if(isset($item['params']['param']))
  2634. {
  2635. $params['src'] = $item['params']['param'];
  2636. }
  2637. elseif(isset($item['params']['src']))
  2638. {
  2639. $params['src'] = $item['params']['src'];
  2640. }
  2641. elseif(!empty($content))
  2642. {
  2643. $params['src'] = $content;
  2644. }
  2645. if(isset($item['params']['scrolling']) && ($params['scrolling'] == 'no'))
  2646. {
  2647. $params['scrolling'] = 'no';
  2648. //$params['scrolling'] = $item['params']['scrolling'];
  2649. }
  2650. else
  2651. {
  2652. $params['scrolling'] = 'yes';
  2653. }
  2654. if(isset($item['params']['width']))
  2655. {
  2656. $params['width'] = $item['params']['width'];
  2657. }
  2658. else
  2659. {
  2660. $params['width'] = '100%';
  2661. }
  2662. if(isset($item['params']['height']))
  2663. {
  2664. $params['height'] = $item['params']['height'];
  2665. }
  2666. else
  2667. {
  2668. $params['height'] = '600';
  2669. }
  2670. foreach($params as $var => $value)
  2671. {
  2672. if ($this->process_text($value) != '')
  2673. {
  2674. $html .= ' ' . $var . '="' . $this->process_text($value) . '"';
  2675. }
  2676. }
  2677. $extras = $this->allow_styling ? array('style', 'class') : array('class');
  2678. $html = '<iframe' . $html . '>';
  2679. return array(
  2680. 'valid' => true,
  2681. 'start' => $html,
  2682. 'end' => '</iframe>'
  2683. );
  2684. }
  2685. */
  2686. // Invalid tag
  2687. return $error;
  2688. }
  2689. // Check if bbcode tag is valid
  2690. function valid_tag($tag, $is_html)
  2691. {
  2692. if($is_html)
  2693. {
  2694. return (isset($this->allowed_html[$tag]) && preg_match('/^[a-z]+$/', $tag)) ? true : false;
  2695. }
  2696. else
  2697. {
  2698. $tag_ok = false;
  2699. if(($tag === '*') || ($tag === '[*]') || ($tag === '[hr]'))
  2700. {
  2701. $tag_ok = true;
  2702. }
  2703. return (isset($this->allowed_bbcode[$tag]) && (preg_match('/^[a-z]+$/', $tag) || ($tag_ok === true))) ? true : false;
  2704. }
  2705. }
  2706. // Check if parameter name is valid
  2707. function valid_param($param)
  2708. {
  2709. return preg_match('/^[a-z]+$/', $param);
  2710. }
  2711. // Check if color is valid
  2712. function valid_color($color, $hex_only = false)
  2713. {
  2714. if ($color === false)
  2715. {
  2716. return false;
  2717. }
  2718. $color = strtolower($color);
  2719. if(substr($color, 0, 1) === '#')
  2720. {
  2721. // normal color
  2722. if(preg_match('/^[0-9a-f]+$/', substr($color, 1)))
  2723. {
  2724. if ($hex_only == true)
  2725. {
  2726. if(strlen($color) == 7)
  2727. {
  2728. return $color;
  2729. }
  2730. }
  2731. else
  2732. {
  2733. if((strlen($color) == 4) || (strlen($color) == 7))
  2734. {
  2735. return $color;
  2736. }
  2737. }
  2738. }
  2739. return false;
  2740. }
  2741. // color with missing #
  2742. if(preg_match('/^[0-9a-f]+$/', $color))
  2743. {
  2744. if ($hex_only == true)
  2745. {
  2746. if(strlen($color) == 6)
  2747. {
  2748. return '#' . $color;
  2749. }
  2750. }
  2751. else
  2752. {
  2753. if((strlen($color) == 3) || (strlen($color) == 6))
  2754. {
  2755. return '#' . $color;
  2756. }
  2757. }
  2758. }
  2759. if($hex_only == true)
  2760. {
  2761. // We didn't find any valid 6 digits hex color
  2762. return false;
  2763. }
  2764. if(preg_match('/^[a-z]+$/', $color))
  2765. {
  2766. // text color
  2767. return $color;
  2768. }
  2769. // rgb(ddd, ddd, ddd) color
  2770. // OLD RGB FUNCTION
  2771. /*
  2772. if((substr($color, 0, 4) === 'rgb(') && preg_match('/^rgb\([0-9]+,[0-9]+,[0-9]+\)$/', $color))
  2773. {
  2774. $colors = explode(',', substr($color, 4, strlen($color) - 5));
  2775. for($i = 0; $i < 3; $i++)
  2776. {
  2777. if($colors[$i] > 255)
  2778. {
  2779. return false;
  2780. }
  2781. }
  2782. return sprintf('#%02X%02X%02X', $colors[0], $colors[1], $colors[2]);
  2783. }
  2784. */
  2785. if(substr($color, 0, 4) === 'rgb(')
  2786. {
  2787. $valid = preg_replace_callback('#^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$#', 'bbcode::valid_rgb_match', $color);
  2788. return !empty($valid) ? $color : false;
  2789. }
  2790. return false;
  2791. }
  2792. // Check for valid RGB match
  2793. function valid_rgb_match($matches)
  2794. {
  2795. $valid = true;
  2796. if (sizeof($matches) != 4)
  2797. {
  2798. $valid = false;
  2799. }
  2800. else
  2801. {
  2802. $red = (int) $matches[1];
  2803. $green = (int) $matches[2];
  2804. $blue = (int) $matches[3];
  2805. if (($red > 255) || ($green > 255) || ($blue > 255))
  2806. {
  2807. $valid = false;
  2808. }
  2809. }
  2810. return $valid;
  2811. }
  2812. // Parse style
  2813. function valid_style($style, $error = false)
  2814. {
  2815. $style = str_replace(array('\\', '"', '@'), array('', '', ''), $style);
  2816. $str = strtolower($style);
  2817. if((strpos($str, 'expression') !== false) || (strpos($str, 'javascript:') !== false) || (strpos($str, 'vbscript:') !== false) || (strpos($str, 'about:') !== false))
  2818. {
  2819. // attempt to use javascript
  2820. return $error;
  2821. }
  2822. if(strpos($str, '//') !== false)
  2823. {
  2824. // attempt to use external file
  2825. return $error;
  2826. }
  2827. if(strpos($str, '!important') !== false)
  2828. {
  2829. // attempt to completely mess up forum layout?
  2830. return $error;
  2831. }
  2832. return $style;
  2833. }
  2834. // Validate url
  2835. function valid_url($url, $error = '')
  2836. {
  2837. $str = strtolower($url);
  2838. if(substr($str, 0, 11) === 'javascript:')
  2839. {
  2840. // attempt to use javascript
  2841. return $error;
  2842. }
  2843. if(substr($str, 0, 9) === 'vbscript:')
  2844. {
  2845. // attempt to use vbscript
  2846. return $error;
  2847. }
  2848. if(substr($str, 0, 6) === 'about:')
  2849. {
  2850. // attempt to use about: url
  2851. return $error;
  2852. }
  2853. return $url;
  2854. }
  2855. // Add extras
  2856. function add_extras($params, $extras)
  2857. {
  2858. $html = '';
  2859. for($i = 0; $i < sizeof($extras); $i++)
  2860. {
  2861. if(isset($params[$extras[$i]]))
  2862. {
  2863. if($extras[$i] === 'style')
  2864. {
  2865. $style = $this->valid_style($params['style']);
  2866. if($style !== false)
  2867. {
  2868. $html .= ' style="' . htmlspecialchars($style) . '"';
  2869. }
  2870. }
  2871. else
  2872. {
  2873. $html .= ' ' . $extras[$i] . '="' . htmlspecialchars($params[$extras[$i]]) . '"';
  2874. }
  2875. }
  2876. }
  2877. return $html;
  2878. }
  2879. // Splits string to tag and parameters
  2880. function extract_params($tag, $is_html)
  2881. {
  2882. $this->tag = $tag;
  2883. $this->params = array();
  2884. $tag = str_replace("\t", ' ', $tag);
  2885. // get parameters
  2886. $pos_eq = strpos($tag, '=');
  2887. $pos_space = strpos($tag, ' ');
  2888. if(($pos_space !== false) && ($pos_eq !== false) && ($pos_space < $pos_eq))
  2889. {
  2890. // mutiple parameters
  2891. $param_start = 0;
  2892. $param_str = substr($tag, $pos_space + 1);
  2893. $param_len = strlen($param_str);
  2894. $this->tag = strtolower(substr($tag, 0, $pos_space));
  2895. if(!$this->valid_tag($this->tag, $is_html))
  2896. {
  2897. return false;
  2898. }
  2899. while($param_start < $param_len)
  2900. {
  2901. // find entry for '='
  2902. $pos = strpos($param_str, '=', $param_start);
  2903. if($pos === false)
  2904. {
  2905. return false;
  2906. }
  2907. else
  2908. {
  2909. // get parameter name
  2910. $str = substr($param_str, $param_start, $pos - $param_start);
  2911. if(!$this->valid_param($str))
  2912. {
  2913. return false;
  2914. }
  2915. // get value
  2916. $pos++;
  2917. $quoted = false;
  2918. if(substr($param_str, $pos, 1) === '"')
  2919. {
  2920. $pos2 = strpos($param_str, '"', $pos + 1);
  2921. if($pos2 === false)
  2922. {
  2923. // invalid quote. search for space instead
  2924. $pos2 = strpos($param_str, ' ', $pos + 1);
  2925. }
  2926. else
  2927. {
  2928. $pos++;
  2929. $quoted = true;
  2930. }
  2931. }
  2932. else
  2933. {
  2934. $pos2 = strpos($param_str, ' ', $pos);
  2935. }
  2936. // end not found. counting until end of expression
  2937. if($pos2 === false)
  2938. {
  2939. $pos2 = $param_len;
  2940. }
  2941. $this->params[$str] = substr($param_str, $pos, $pos2 - $pos);
  2942. $param_start = $pos2 + 1;
  2943. if($quoted)
  2944. {
  2945. $param_start++;
  2946. }
  2947. }
  2948. }
  2949. }
  2950. elseif($pos_eq !== false)
  2951. {
  2952. // single parameter
  2953. $str = substr($tag, $pos_eq + 1);
  2954. $this->tag = strtolower(substr($tag, 0, $pos_eq));
  2955. if(!$this->valid_tag($this->tag, $is_html))
  2956. {
  2957. return false;
  2958. }
  2959. if(strlen($str) > 1 && substr($str, 0, 1) === '"' && substr($str, strlen($str) - 1) === '"')
  2960. {
  2961. $str = substr($str, 1, strlen($str) - 2);
  2962. }
  2963. if(trim($str) !== $str)
  2964. {
  2965. return false;
  2966. }
  2967. $this->params['param'] = $str;
  2968. }
  2969. else
  2970. {
  2971. // no parameters
  2972. $this->tag = strtolower($tag);
  2973. if(!$this->valid_tag($this->tag, $is_html))
  2974. {
  2975. return false;
  2976. }
  2977. }
  2978. return true;
  2979. }
  2980. // Recursive function that converts text to bbcode tree
  2981. function push($start, $level, $prev_tags)
  2982. {
  2983. //echo '<b>push</b>(', $start, ', ', $level, ', (', implode(',', $prev_tags), '))<br />';
  2984. $items = array();
  2985. $pos_start_bbcode = $this->allow_bbcode ? strpos($this->text, '[', $start) : false;
  2986. $pos_start_html = $this->allow_html ? strpos($this->text, '<', $start) : false;
  2987. while($pos_start_bbcode !== false || $pos_start_html !== false)
  2988. {
  2989. $pos_start = ($pos_start_bbcode === false) ? $pos_start_html : (($pos_start_html === false) ? $pos_start_bbcode : min($pos_start_bbcode, $pos_start_html));
  2990. $is_html = ($pos_start_html === $pos_start) ? true : false;
  2991. $prev_start = $start;
  2992. // found tag. get data.
  2993. $pos_end = strpos($this->text, $is_html ? '>' : ']', $pos_start);
  2994. if($pos_end === false)
  2995. {
  2996. $tag_valid = false;
  2997. }
  2998. else
  2999. {
  3000. $code = substr($this->text, $pos_start, $pos_end - $pos_start + 1);
  3001. // check if tag is valid and get type of tag
  3002. $tag_valid = true;
  3003. $tag_closing = false;
  3004. $tag_self_closing = false;
  3005. if(strlen($code) < 3)
  3006. {
  3007. $tag_valid = false;
  3008. }
  3009. elseif(!$is_html && strpos($code, '[', 1) !== false)
  3010. {
  3011. $tag_valid = false;
  3012. }
  3013. elseif($is_html && strpos($code, '<', 1) !== false)
  3014. {
  3015. $tag_valid = false;
  3016. }
  3017. elseif(!$is_html && strpos($code, "\n") !== false)
  3018. {
  3019. $tag_valid = false;
  3020. }
  3021. elseif(substr($code, 0, 2) === ($is_html ? '</' : '[/'))
  3022. {
  3023. $tag_closing = true;
  3024. $tag = substr($code, 2, strlen($code) - 3);
  3025. }
  3026. elseif(substr($code, strlen($code) - 3) === ($is_html ? ' />' : ' /]'))
  3027. {
  3028. $tag_self_closing = true;
  3029. $tag = substr($code, 1, strlen($code) - 4);
  3030. }
  3031. else
  3032. {
  3033. $tag = substr($code, 1, strlen($code) - 2);
  3034. }
  3035. // do not process tag if it requires too much recursion
  3036. if($level > 12 && (!$tag_closing && !$tag_self_closing))
  3037. {
  3038. $tag_valid = false;
  3039. }
  3040. // special tags
  3041. if(in_array($code, $this->self_closing_tags) != false)
  3042. {
  3043. $tag_self_closing = true;
  3044. }
  3045. }
  3046. if($tag_valid)
  3047. {
  3048. $start = $pos_end;
  3049. $params = array();
  3050. if(!$tag_closing)
  3051. {
  3052. if(!$this->extract_params($tag, $is_html))
  3053. {
  3054. $tag_valid = false;
  3055. }
  3056. else
  3057. {
  3058. $tag = $this->tag;
  3059. $params = $this->params;
  3060. }
  3061. }
  3062. else
  3063. {
  3064. if(strpos($tag, ' autourl=' . AUTOURL . ' nofollow=1'))
  3065. {
  3066. $tag = str_replace(' autourl=' . AUTOURL . ' nofollow=1', '', $tag);
  3067. }
  3068. $tag = strtolower($tag);
  3069. if(!$this->valid_tag($tag, $is_html))
  3070. {
  3071. $tag_valid = false;
  3072. }
  3073. }
  3074. }
  3075. if($tag_valid)
  3076. {
  3077. if($tag_closing)
  3078. {
  3079. // check if this is correct closing tag
  3080. if(in_array($tag, $prev_tags))
  3081. {
  3082. return array(
  3083. 'items' => $items,
  3084. 'tag' => $tag,
  3085. 'pos' => $pos_end,
  3086. 'start' => $pos_start,
  3087. 'len' => strlen($code)
  3088. );
  3089. }
  3090. }
  3091. elseif($tag_self_closing)
  3092. {
  3093. // found self-closing tag
  3094. $items[] = array(
  3095. 'tag' => $tag,
  3096. 'code' => $code,
  3097. 'params' => $params,
  3098. 'start' => $pos_start,
  3099. 'start_len' => strlen($code),
  3100. 'end' => $pos_end + 1,
  3101. 'end_len' => 0,
  3102. 'level' => $level + 1,
  3103. 'iteration' => 0,
  3104. 'self_closing' => 1,
  3105. 'prev' => array(),
  3106. 'next' => array(),
  3107. 'is_html' => $is_html,
  3108. 'items' => array()
  3109. );
  3110. }
  3111. else
  3112. {
  3113. // found correct tag. call recursive search
  3114. $result = $this->push($pos_end, $level + 1, array_merge($prev_tags, array($tag)));
  3115. if($result['tag'] === $tag)
  3116. {
  3117. // found correctly finished tag
  3118. $items[] = array(
  3119. 'tag' => $tag,
  3120. 'code' => $code,
  3121. 'params' => $params,
  3122. 'start' => $pos_start,
  3123. 'start_len' => strlen($code),
  3124. 'end' => $result['start'],
  3125. 'end_len' => $result['len'],
  3126. 'level' => $level + 1,
  3127. 'iteration' => 0,
  3128. 'self_closing' => 2,
  3129. 'prev' => array(),
  3130. 'next' => array(),
  3131. 'is_html' => $is_html,
  3132. 'items' => $result['items']
  3133. );
  3134. $start = $result['pos'];
  3135. }
  3136. else
  3137. {
  3138. $items = array_merge($items, $result['items']);
  3139. return array(
  3140. 'items' => $items,
  3141. 'tag' => $result['tag'],
  3142. 'pos' => !empty($result['pos']) ? $result['pos'] : 0,
  3143. 'start' => !empty($result['start']) ? $result['start'] : 0,
  3144. 'len' => !empty($result['len']) ? $result['len'] : 0
  3145. );
  3146. }
  3147. }
  3148. }
  3149. else
  3150. {
  3151. $start = $pos_start + 1;
  3152. }
  3153. $pos_start_bbcode = $this->allow_bbcode ? strpos($this->text, '[', $start) : false;
  3154. $pos_start_html = $this->allow_html ? strpos($this->text, '<', $start) : false;
  3155. }
  3156. return array(
  3157. 'items' => $items,
  3158. 'tag' => false,
  3159. );
  3160. }
  3161. // Debug fuction. Prints tree of bbcode
  3162. function debug($items)
  3163. {
  3164. for($i = 0; $i < sizeof($items); $i++)
  3165. {
  3166. $item = $items[$i];
  3167. if($item['tag'])
  3168. {
  3169. for($j=0; $j<$item['level']; $j++)
  3170. {
  3171. echo '-';
  3172. }
  3173. echo ' ', $item['tag'], ' (';
  3174. $first = true;
  3175. foreach($item['params'] as $var => $value)
  3176. {
  3177. if(!$first) echo ', ';
  3178. $first = false;
  3179. echo $var, '="', htmlspecialchars($value), '"';
  3180. }
  3181. echo ")<br />\n";
  3182. $this->debug($item['items']);
  3183. }
  3184. }
  3185. }
  3186. // Post-processing. Adds previous/next items to every item.
  3187. function add_pointers(&$items, $prev_tags)
  3188. {
  3189. $tags = array();
  3190. for($i = 0; $i < sizeof($items); $i++)
  3191. {
  3192. $item = &$items[$i];
  3193. $tags[] = array(
  3194. 'tag' => $item['tag'],
  3195. 'item' => &$items[$i]
  3196. );
  3197. $iterations = 0;
  3198. for($j = 0; $j < sizeof($prev_tags); $j++)
  3199. {
  3200. if($prev_tags[$j]['tag'] === $item['tag'])
  3201. {
  3202. $iterations++;
  3203. }
  3204. }
  3205. $item['iteration'] = $iterations;
  3206. $item['prev'] = $prev_tags;
  3207. // todo: check if subitems are allowed
  3208. // parse sub-items
  3209. if(sizeof($item['items']))
  3210. {
  3211. $arr = array(
  3212. 'tag' => $item['tag'],
  3213. 'item' => &$items[$i]
  3214. );
  3215. $item['next'] = $this->add_pointers($item['items'], array_merge($prev_tags, array($arr)));
  3216. $tags = array_merge($tags, $item['next']);
  3217. }
  3218. }
  3219. return $tags;
  3220. }
  3221. // Process text
  3222. function process_text($text, $br = true, $chars = true)
  3223. {
  3224. $search = array(
  3225. '[url autourl=' . AUTOURL . ' nofollow=1]',
  3226. '[/url autourl=' . AUTOURL .' nofollow=1]',
  3227. '[email autourl=' . AUTOURL . ' nofollow=1]',
  3228. '[/email autourl=' . AUTOURL . ' nofollow=1]'
  3229. );
  3230. $replace = array('', '', '', '');
  3231. $text = str_replace($search, $replace, $text);
  3232. if($chars)
  3233. {
  3234. $text = htmlspecialchars($text);
  3235. $text = str_replace('&amp;#', '&#', $text);
  3236. }
  3237. else
  3238. {
  3239. $text = str_replace(
  3240. array('&amp;', '>', '%3E', '<', '%3C', '"', '&amp;#'),
  3241. array('&amp;amp;', '&gt;', '&gt;', '&lt;', '&lt;', '&quot;', '&#'),
  3242. $text
  3243. );
  3244. }
  3245. if($br)
  3246. {
  3247. $text = str_replace("\n", "<br />\n", $text);
  3248. }
  3249. return $text;
  3250. }
  3251. // Process tree
  3252. function process($start, $end, &$items, $clean_tags = false)
  3253. {
  3254. $html = '';
  3255. for($i = 0; $i < sizeof($items); $i++)
  3256. {
  3257. $item = &$items[$i];
  3258. // check code before item
  3259. if($item['start'] > $start)
  3260. {
  3261. $html .= $this->process_text(substr($this->text, $start, $item['start'] - $start));
  3262. }
  3263. if ($clean_tags === true)
  3264. {
  3265. // clean tag
  3266. $result = $this->clean_tag($item);
  3267. }
  3268. else
  3269. {
  3270. // process tag
  3271. $result = $this->process_tag($item);
  3272. }
  3273. if($result['valid'] && !isset($result['html']))
  3274. {
  3275. $html .= $result['start'];
  3276. if(!isset($result['allow_nested']) || $result['allow_nested'])
  3277. {
  3278. // process code inside tag
  3279. $html .= $this->process($item['start'] + $item['start_len'], $item['end'], $item['items'], $clean_tags);
  3280. }
  3281. $html .= $result['end'];
  3282. }
  3283. elseif($result['valid'])
  3284. {
  3285. $html .= $result['html'];
  3286. }
  3287. else
  3288. {
  3289. // invalid tag. show html code for it and process nested tags
  3290. $item['valid'] = false;
  3291. if($item['start_len'])
  3292. {
  3293. $html .= $this->process_text(substr($this->text, $item['start'], $item['start_len']));
  3294. }
  3295. $html .= $this->process($item['start'] + $item['start_len'], $item['end'], $item['items']);
  3296. if($item['end_len'])
  3297. {
  3298. $html .= $this->process_text(substr($this->text, $item['end'], $item['end_len']));
  3299. }
  3300. }
  3301. $start = $item['end'] + $item['end_len'];
  3302. }
  3303. // process code after item
  3304. if($start < $end)
  3305. {
  3306. $html .= $this->process_text(substr($this->text, $start, $end - $start));
  3307. }
  3308. return $html;
  3309. }
  3310. // Prepare smilies list
  3311. function prepare_smilies()
  3312. {
  3313. if(!$this->allow_smilies)
  3314. {
  3315. return;
  3316. }
  3317. $this->replaced_smilies = array();
  3318. for($i = 0; $i < sizeof($this->allowed_smilies); $i++)
  3319. {
  3320. if(strpos($this->text, $this->allowed_smilies[$i]['code']) !== false)
  3321. {
  3322. $this->replaced_smilies[] = $this->allowed_smilies[$i];
  3323. }
  3324. }
  3325. }
  3326. // Parse only smilies
  3327. function parse_only_smilies($text)
  3328. {
  3329. if(!$this->allow_smilies || (sizeof($this->allowed_smilies) == 0))
  3330. {
  3331. return $text;
  3332. }
  3333. $smilies_code = array();
  3334. $smilies_replace = array();
  3335. for($i = 0; $i < sizeof($this->allowed_smilies); $i++)
  3336. {
  3337. $smilies_code_prev[] = ' ' . $this->allowed_smilies[$i]['code'];
  3338. $smilies_code_next[] = $this->allowed_smilies[$i]['code'] . ' ';
  3339. $smilies_replace_prev[] = ' ' . $this->allowed_smilies[$i]['replace'];
  3340. $smilies_replace_next[] = $this->allowed_smilies[$i]['replace'] . ' ';
  3341. }
  3342. $text = str_replace($smilies_code_prev, $smilies_replace_prev, $text);
  3343. $text = str_replace($smilies_code_next, $smilies_replace_next, $text);
  3344. return $text;
  3345. }
  3346. // Process smilies
  3347. function process_smilies()
  3348. {
  3349. $valid_chars_prev = array('', ' ', "\n", "\r", "\t", '>');
  3350. $valid_chars_next = array('', ' ', "\n", "\r", "\t", '<');
  3351. if(!$this->allow_smilies && !sizeof($this->replaced_smilies))
  3352. {
  3353. return;
  3354. }
  3355. for($i = 0; $i < sizeof($this->replaced_smilies); $i++)
  3356. {
  3357. $code = $this->replaced_smilies[$i]['code'];
  3358. $text = $this->replaced_smilies[$i]['replace'];
  3359. $code_len = strlen($code);
  3360. $text_len = strlen($text);
  3361. $pos = strpos($this->html, $code);
  3362. while($pos !== false)
  3363. {
  3364. $valid = false;
  3365. // check previous character
  3366. $prev_char = $pos > 0 ? substr($this->html, $pos - 1, 1) : '';
  3367. if(in_array($prev_char, $valid_chars_prev))
  3368. {
  3369. // check next character
  3370. $next_char = substr($this->html, $pos + $code_len, 1);
  3371. if(in_array($next_char, $valid_chars_next))
  3372. {
  3373. // make sure we aren't inside html code
  3374. $pos1 = strpos($this->html, '<', $pos + $code_len);
  3375. $pos2 = strpos($this->html, '>', $pos + $code_len);
  3376. if($pos2 === false || ($pos1 && $pos1 < $pos2))
  3377. {
  3378. // make sure we aren't inside nosmilies zone
  3379. $pos1 = strpos($this->html, BBCODE_NOSMILIES_START, $pos + $code_len);
  3380. $pos2 = strpos($this->html, BBCODE_NOSMILIES_END, $pos + $code_len);
  3381. if($pos2 === false || ($pos1 && $pos1 < $pos2))
  3382. {
  3383. $valid = true;
  3384. }
  3385. }
  3386. }
  3387. }
  3388. if($valid)
  3389. {
  3390. $this->html = substr($this->html, 0, $pos) . $text . substr($this->html, $pos + $code_len);
  3391. $pos += $text_len;
  3392. }
  3393. else
  3394. {
  3395. $pos++;
  3396. }
  3397. $pos = strpos($this->html, $code, $pos);
  3398. }
  3399. }
  3400. }
  3401. // Make urls clickable
  3402. function process_urls()
  3403. {
  3404. // characters allowed in email
  3405. $chars = array();
  3406. for($i = 224; $i < 256; $i++)
  3407. {
  3408. if($i != 247)
  3409. {
  3410. $chars .= chr($i);
  3411. }
  3412. }
  3413. // search and replace arrays
  3414. $search = array(
  3415. "/([\s>])((https?|ftp):\/\/|www\.)([^ \r\n\(\)\^\$!`\"'\|\[\]\{\}<>]+)/si",
  3416. "/([\s>])([_a-zA-Z0-9\-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9\-{$chars}]+(\.[a-zA-Z0-9\-{$chars}]+)*(\.[a-zA-Z]{2,}))/si",
  3417. );
  3418. $replace = array(
  3419. "\\1[url autourl=" . AUTOURL . " nofollow=1]\\2\\4[/url autourl=" . AUTOURL . " nofollow=1]",
  3420. "\\1[email autourl=" . AUTOURL . " nofollow=1]\\2[/email autourl=" . AUTOURL . " nofollow=1]",
  3421. );
  3422. $this->text = preg_replace($search, $replace, ' ' . $this->text . ' ');
  3423. $this->text = substr($this->text, 1, strlen($this->text) - 2);
  3424. }
  3425. // Remove bbcode_uid from old posts
  3426. function bbcuid_clean($text, $id = false)
  3427. {
  3428. if ($id != false)
  3429. {
  3430. $text = str_replace(':' . $id, '', $text);
  3431. }
  3432. else
  3433. {
  3434. $text = preg_replace("/\:([a-f0-9]{10})/s", '', $text);
  3435. // phpBB 3
  3436. //$text = preg_replace("/\:([a-z0-9]{8})/s", '', $text);
  3437. }
  3438. return $text;
  3439. }
  3440. // Converts text to html code
  3441. function parse($text, $id = false, $light = false, $clean_tags = false)
  3442. {
  3443. if(defined('IN_ICYPHOENIX'))
  3444. {
  3445. // if you have an old phpBB based site with old posts, you may want to enable this BBCode UID strip REG EX Replace
  3446. //$text = preg_replace("/\:([a-f0-9]{10})/s", '', $text);
  3447. $search = array(
  3448. $id ? ':' . $id : '',
  3449. 'code:1]',
  3450. 'list:o]',
  3451. );
  3452. $replace = array(
  3453. '',
  3454. 'code]',
  3455. 'list]',
  3456. );
  3457. $text = str_replace($search, $replace, $text);
  3458. // We need this after having removed bbcode_uid... but don't know why
  3459. $text = $this->undo_htmlspecialchars($text);
  3460. /*
  3461. if($id)
  3462. {
  3463. $text = $this->undo_htmlspecialchars($text);
  3464. }
  3465. */
  3466. }
  3467. // reset variables
  3468. $this->text = $text;
  3469. $this->data = array();
  3470. $this->html = '';
  3471. $this->prepare_smilies();
  3472. if (!$light)
  3473. {
  3474. $this->process_urls();
  3475. }
  3476. $this->code_counter = 0;
  3477. // if bbcode and html are disabled then return unprocessed text
  3478. if(!$this->allow_bbcode && !$this->allow_html)
  3479. {
  3480. // Mighty Gorgon: I had to add htmlspecialchars to text, otherwise users were able to post html by disabling both HTML and BBCodes in topics... still to be fully verified...
  3481. //$this->html = $this->text;
  3482. $this->html = htmlspecialchars($this->text);
  3483. $this->process_smilies();
  3484. return $this->html;
  3485. }
  3486. // convert to tree structure
  3487. $result = $this->push(0, 0, array());
  3488. $this->data = $result['items'];
  3489. /*
  3490. ob_start();
  3491. $this->debug($this->data);
  3492. $str = ob_get_contents();
  3493. ob_end_clean();
  3494. $this->html = 'Debug:<br />' . $str;
  3495. return $this->html;
  3496. */
  3497. // add prev/next pointers and count iterations
  3498. $this->add_pointers($this->data, array());
  3499. if ($clean_tags !== false)
  3500. {
  3501. $clean_tags = true;
  3502. }
  3503. // convert to html
  3504. $this->html = $this->process(0, strlen($this->text), $this->data, $clean_tags);
  3505. $this->process_smilies();
  3506. if(defined('IN_ICYPHOENIX'))
  3507. {
  3508. global $db, $cache, $config, $lang;
  3509. if (!empty($config['enable_custom_bbcodes']))
  3510. {
  3511. $bbcodes = $cache->obtain_bbcodes(true);
  3512. if (!empty($bbcodes))
  3513. {
  3514. $bbcode_regexp = array();
  3515. foreach ($bbcodes as $k => $v)
  3516. {
  3517. $v = array_map('stripslashes', $v);
  3518. $bbcode_regexp = $this->build_regexp($v['bbcode_match'], $v['bbcode_tpl']);
  3519. $this->html = preg_replace($bbcode_regexp['second_pass_match'], $bbcode_regexp['second_pass_replace'], $this->html);
  3520. }
  3521. }
  3522. }
  3523. }
  3524. return $this->html;
  3525. }
  3526. /*
  3527. * Build regular expression for custom bbcode
  3528. */
  3529. function build_regexp(&$bbcode_match, &$bbcode_tpl)
  3530. {
  3531. $bbcode_match = trim($bbcode_match);
  3532. $bbcode_tpl = trim($bbcode_tpl);
  3533. $fp_match = preg_quote($bbcode_match, '!');
  3534. $fp_replace = preg_replace('#^\[(.*?)\]#', '[$1]', $bbcode_match);
  3535. $fp_replace = preg_replace('#\[/(.*?)\]$#', '[/$1]', $fp_replace);
  3536. $sp_match = preg_quote($bbcode_match, '!');
  3537. $sp_match = preg_replace('#^\\\\\[(.*?)\\\\\]#', '\[$1\]', $sp_match);
  3538. $sp_match = preg_replace('#\\\\\[/(.*?)\\\\\]$#', '\[/$1\]', $sp_match);
  3539. $sp_replace = $bbcode_tpl;
  3540. // @todo Make sure to change this too if something changed in message parsing
  3541. $tokens = array(
  3542. 'URL' => array(
  3543. '!(?:(' . str_replace(array('!', '\#'), array('\!', '#'), $this->get_preg_expression('url')) . ')|(' . str_replace(array('!', '\#'), array('\!', '#'), $this->get_preg_expression('www_url')) . '))!ie' => "\$this->bbcode_specialchars(('\$1') ? '\$1' : 'http://\$2')"
  3544. ),
  3545. 'LOCAL_URL' => array(
  3546. '!(' . str_replace(array('!', '\#'), array('\!', '#'), $this->get_preg_expression('relative_url')) . ')!e' => "\$this->bbcode_specialchars('$1')"
  3547. ),
  3548. 'EMAIL' => array(
  3549. '!(' . $this->get_preg_expression('email') . ')!ie' => "\$this->bbcode_specialchars('$1')"
  3550. ),
  3551. 'TEXT' => array(
  3552. '!(.*?)!es' => "str_replace(array(\"\\r\\n\", '\\\"', '\\'', '(', ')'), array(\"\\n\", '\"', '&#39;', '&#40;', '&#41;'), trim('\$1'))"
  3553. ),
  3554. 'SIMPLETEXT' => array(
  3555. '!([a-zA-Z0-9-+.,_ ]+)!' => "$1"
  3556. ),
  3557. 'IDENTIFIER' => array(
  3558. '!([a-zA-Z0-9-_]+)!' => "$1"
  3559. ),
  3560. 'COLOR' => array(
  3561. '!([a-z]+|#[0-9abcdef]+)!i' => '$1'
  3562. ),
  3563. 'NUMBER' => array(
  3564. '!([0-9]+)!' => '$1'
  3565. )
  3566. );
  3567. $sp_tokens = array(
  3568. 'URL' => '(?i)((?:' . str_replace(array('!', '\#'), array('\!', '#'), $this->get_preg_expression('url')) . ')|(?:' . str_replace(array('!', '\#'), array('\!', '#'), $this->get_preg_expression('www_url')) . '))(?-i)',
  3569. 'LOCAL_URL' => '(?i)(' . str_replace(array('!', '\#'), array('\!', '#'), $this->get_preg_expression('relative_url')) . ')(?-i)',
  3570. 'EMAIL' => '(' . $this->get_preg_expression('email') . ')',
  3571. 'TEXT' => '(.*?)',
  3572. 'SIMPLETEXT' => '([a-zA-Z0-9-+.,_ ]+)',
  3573. 'IDENTIFIER' => '([a-zA-Z0-9-_]+)',
  3574. 'COLOR' => '([a-zA-Z]+|#[0-9abcdefABCDEF]+)',
  3575. 'NUMBER' => '([0-9]+)',
  3576. );
  3577. $pad = 0;
  3578. $modifiers = 'i';
  3579. if (preg_match_all('/\{(' . implode('|', array_keys($tokens)) . ')[0-9]*\}/i', $bbcode_match, $m))
  3580. {
  3581. foreach ($m[0] as $n => $token)
  3582. {
  3583. $token_type = $m[1][$n];
  3584. reset($tokens[strtoupper($token_type)]);
  3585. list($match, $replace) = each($tokens[strtoupper($token_type)]);
  3586. // Pad backreference numbers from tokens
  3587. if (preg_match_all('/(?<!\\\\)\$([0-9]+)/', $replace, $repad))
  3588. {
  3589. $repad = $pad + sizeof(array_unique($repad[0]));
  3590. // Updated by Informpro
  3591. /*
  3592. $replace = preg_replace('/(?<!\\\\)\$([0-9]+)/e', "'\${' . (\$1 + \$pad) . '}'", $replace);
  3593. */
  3594. $replace = preg_replace_callback('/(?<!\\\\)\$([0-9]+)/', function ($m) use ($pad) {
  3595. return '${' . ($m[1] + $pad) . '}';
  3596. }, $replace);
  3597. $pad = $repad;
  3598. }
  3599. // Obtain pattern modifiers to use and alter the regex accordingly
  3600. $regex = preg_replace('/!(.*)!([a-z]*)/', '$1', $match);
  3601. $regex_modifiers = preg_replace('/!(.*)!([a-z]*)/', '$2', $match);
  3602. for ($i = 0, $size = strlen($regex_modifiers); $i < $size; ++$i)
  3603. {
  3604. if (strpos($modifiers, $regex_modifiers[$i]) === false)
  3605. {
  3606. $modifiers .= $regex_modifiers[$i];
  3607. if ($regex_modifiers[$i] == 'e')
  3608. {
  3609. $fp_replace = "'" . str_replace("'", "\\'", $fp_replace) . "'";
  3610. }
  3611. }
  3612. if ($regex_modifiers[$i] == 'e')
  3613. {
  3614. $replace = "'.$replace.'";
  3615. }
  3616. }
  3617. $fp_match = str_replace(preg_quote($token, '!'), $regex, $fp_match);
  3618. $fp_replace = str_replace($token, $replace, $fp_replace);
  3619. $sp_match = str_replace(preg_quote($token, '!'), $sp_tokens[$token_type], $sp_match);
  3620. $sp_replace = str_replace($token, '${' . ($n + 1) . '}', $sp_replace);
  3621. }
  3622. $fp_match = '!' . $fp_match . '!' . $modifiers;
  3623. $sp_match = '!' . $sp_match . '!s';
  3624. if (strpos($fp_match, 'e') !== false)
  3625. {
  3626. $fp_replace = str_replace("'.'", '', $fp_replace);
  3627. $fp_replace = str_replace(".''.", '.', $fp_replace);
  3628. }
  3629. }
  3630. else
  3631. {
  3632. // No replacement is present, no need for a second-pass pattern replacement
  3633. // A simple str_replace will suffice
  3634. $fp_match = '!' . $fp_match . '!' . $modifiers;
  3635. $sp_match = $fp_replace;
  3636. $sp_replace = '';
  3637. }
  3638. // Lowercase tags
  3639. $bbcode_tag = preg_replace('/.*?\[([a-z0-9_-]+=?).*/i', '$1', $bbcode_match);
  3640. $bbcode_search = preg_replace('/.*?\[([a-z0-9_-]+)=?.*/i', '$1', $bbcode_match);
  3641. if (!preg_match('/^[a-zA-Z0-9_-]+=?$/', $bbcode_tag))
  3642. {
  3643. return false;
  3644. }
  3645. // Updated by Informpro
  3646. /*
  3647. $fp_match = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $fp_match);
  3648. $fp_replace = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $fp_replace);
  3649. $sp_match = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $sp_match);
  3650. $sp_replace = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $sp_replace);
  3651. */
  3652. $fp_match = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($m) {
  3653. return strtolower($m[0]);
  3654. }, $fp_match);
  3655. $fp_replace = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($m) {
  3656. return strtolower($m[0]);
  3657. }, $fp_replace);
  3658. $sp_match = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($m) {
  3659. return strtolower($m[0]);
  3660. }, $sp_match);
  3661. $sp_replace = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($m) {
  3662. return strtolower($m[0]);
  3663. }, $sp_replace);
  3664. return array(
  3665. 'bbcode_tag' => $bbcode_tag,
  3666. 'first_pass_match' => $fp_match,
  3667. 'first_pass_replace' => $fp_replace,
  3668. 'second_pass_match' => $sp_match,
  3669. 'second_pass_replace' => $sp_replace
  3670. );
  3671. }
  3672. /**
  3673. * This function returns a regular expression pattern for commonly used expressions
  3674. * Use with / as delimiter for email mode and # for url modes
  3675. * mode can be: email|bbcode_htm|url|url_inline|www_url|www_url_inline|relative_url|relative_url_inline
  3676. */
  3677. function get_preg_expression($mode)
  3678. {
  3679. switch ($mode)
  3680. {
  3681. case 'email':
  3682. //return '(?:[a-z0-9\'\.\-_\+\|]++|&amp;)+@[a-z0-9\-]+\.(?:[a-z0-9\-]+\.)*[a-z]+';
  3683. return '([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&amp;)+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)';
  3684. break;
  3685. case 'bbcode_htm':
  3686. return array(
  3687. '#<!\-\- e \-\-><a href="mailto:(.*?)">.*?</a><!\-\- e \-\->#',
  3688. '#<!\-\- l \-\-><a (?:class="[\w-]+" )?href="(.*?)(?:(&amp;|\?)sid=[0-9a-f]{32})?">.*?</a><!\-\- l \-\->#',
  3689. '#<!\-\- ([mw]) \-\-><a (?:class="[\w-]+" )?href="(.*?)">.*?</a><!\-\- \1 \-\->#',
  3690. '#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/.*? \/><!\-\- s\1 \-\->#',
  3691. '#<!\-\- .*? \-\->#s',
  3692. '#<.*?>#s',
  3693. );
  3694. break;
  3695. case 'url':
  3696. case 'url_inline':
  3697. $inline = ($mode == 'url') ? ')' : '';
  3698. $scheme = ($mode == 'url') ? '[a-z\d+\-.]' : '[a-z\d+]'; // avoid automatic parsing of "word" in "last word.http://..."
  3699. // generated with regex generation file in the develop folder
  3700. return "[a-z]$scheme*:/{2}(?:(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?";
  3701. break;
  3702. case 'www_url':
  3703. case 'www_url_inline':
  3704. $inline = ($mode == 'www_url') ? ')' : '';
  3705. return "www\.(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})+(?::\d*)?(?:/(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?";
  3706. break;
  3707. case 'relative_url':
  3708. case 'relative_url_inline':
  3709. $inline = ($mode == 'relative_url') ? ')' : '';
  3710. return "(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*(?:/(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?";
  3711. break;
  3712. }
  3713. return '';
  3714. }
  3715. /**
  3716. * Transform some characters in valid bbcodes
  3717. */
  3718. function bbcode_specialchars($text)
  3719. {
  3720. $str_from = array('<', '>', '[', ']', '.', ':');
  3721. $str_to = array('&lt;', '&gt;', '&#91;', '&#93;', '&#46;', '&#58;');
  3722. return str_replace($str_from, $str_to, $text);
  3723. }
  3724. /**
  3725. * Load rainbow colors
  3726. */
  3727. function load_rainbow_colors()
  3728. {
  3729. return array(
  3730. 1 => 'red',
  3731. 2 => 'orange',
  3732. 3 => 'yellow',
  3733. 4 => 'green',
  3734. 5 => 'blue',
  3735. 6 => 'indigo',
  3736. 7 => 'violet'
  3737. );
  3738. }
  3739. /**
  3740. * Apply rainbow effect
  3741. */
  3742. function rainbow($text)
  3743. {
  3744. // Returns text highlighted in rainbow colours
  3745. $colors = $this->load_rainbow_colors();
  3746. $text = trim($text);
  3747. $length = strlen($text);
  3748. $result = '';
  3749. $color_counter = 0;
  3750. $TAG_OPEN = false;
  3751. for ($i = 0; $i < $length; $i++)
  3752. {
  3753. $char = substr($text, $i, 1);
  3754. // UTF-8 character encoding - BEGIN
  3755. // See http://www.faqs.org/rfcs/rfc2279.html
  3756. $code = ord($char);
  3757. if ($code >= 0x80)
  3758. {
  3759. if ($code < 0xE0)
  3760. {
  3761. // Two byte
  3762. $char = substr($text, $i, 2);
  3763. $i = $i + 1;
  3764. }
  3765. elseif ($code < 0xF0)
  3766. {
  3767. // Three byte
  3768. $char = substr($text, $i, 3);
  3769. $i = $i + 2;
  3770. }
  3771. elseif ($code < 0xF8)
  3772. {
  3773. // Four byte
  3774. $char = substr($text, $i, 4);
  3775. $i = $i + 3;
  3776. }
  3777. elseif ($code < 0xFC)
  3778. {
  3779. // Five byte
  3780. $char = substr($text, $i, 5);
  3781. $i = $i + 4;
  3782. }
  3783. elseif ($code < 0xFE)
  3784. {
  3785. // Six byte
  3786. $char = substr($text, $i, 6);
  3787. $i = $i + 5;
  3788. }
  3789. }
  3790. // UTF-8 character encoding - END
  3791. if (!$TAG_OPEN)
  3792. {
  3793. if ($char == '<')
  3794. {
  3795. $TAG_OPEN = true;
  3796. $result .= $char;
  3797. }
  3798. elseif (preg_match("#\S#i", $char))
  3799. {
  3800. $color_counter++;
  3801. $result .= '<span style="color: ' . $colors[$color_counter] . ';">' . $char . '</span>';
  3802. $color_counter = ($color_counter == 7) ? 0 : $color_counter;
  3803. }
  3804. else
  3805. {
  3806. $result .= $char;
  3807. }
  3808. }
  3809. else
  3810. {
  3811. if ($char == '>')
  3812. {
  3813. $TAG_OPEN = false;
  3814. }
  3815. $result .= $char;
  3816. }
  3817. }
  3818. return $result;
  3819. }
  3820. function rand_color()
  3821. {
  3822. $color_code = mt_rand(0, 255);
  3823. if ($color_code < 16)
  3824. {
  3825. return ('0' . dechex($color_code));
  3826. }
  3827. else
  3828. {
  3829. return dechex($color_code);
  3830. }
  3831. }
  3832. function load_random_colors($iterations = 10)
  3833. {
  3834. $random_color = array();
  3835. for ($i = 0; $i < $iterations; $i++)
  3836. {
  3837. $random_color[$i + 1] = '#' . $this->rand_color() . $this->rand_color() . $this->rand_color();
  3838. }
  3839. return $random_color;
  3840. }
  3841. function load_gradient_colors($color1, $color2, $iterations = 10)
  3842. {
  3843. $col1_array = array();
  3844. $col2_array = array();
  3845. $col_dif_array = array();
  3846. $gradient_color = array();
  3847. $col1_array[0] = hexdec(substr($color1, 1, 2));
  3848. $col1_array[1] = hexdec(substr($color1, 3, 2));
  3849. $col1_array[2] = hexdec(substr($color1, 5, 2));
  3850. $col2_array[0] = hexdec(substr($color2, 1, 2));
  3851. $col2_array[1] = hexdec(substr($color2, 3, 2));
  3852. $col2_array[2] = hexdec(substr($color2, 5, 2));
  3853. $col_dif_array[0] = ($col2_array[0] - $col1_array[0]) / ($iterations - 1);
  3854. $col_dif_array[1] = ($col2_array[1] - $col1_array[1]) / ($iterations - 1);
  3855. $col_dif_array[2] = ($col2_array[2] - $col1_array[2]) / ($iterations - 1);
  3856. for ($i = 0; $i < $iterations; $i++)
  3857. {
  3858. $part1 = round($col1_array[0] + ($col_dif_array[0] * $i));
  3859. $part2 = round($col1_array[1] + ($col_dif_array[1] * $i));
  3860. $part3 = round($col1_array[2] + ($col_dif_array[2] * $i));
  3861. $part1 = ($part1 < 16) ? ('0' . dechex($part1)) : (dechex($part1));
  3862. $part2 = ($part2 < 16) ? ('0' . dechex($part2)) : (dechex($part2));
  3863. $part3 = ($part3 < 16) ? ('0' . dechex($part3)) : (dechex($part3));
  3864. $gradient_color[$i + 1] = '#' . $part1 . $part2 . $part3;
  3865. }
  3866. return $gradient_color;
  3867. }
  3868. function gradient($text, $color1, $color2, $mode = 'random', $iterations = 10)
  3869. {
  3870. // Returns text highlighted in random gradient colours
  3871. if ($mode == 'random')
  3872. {
  3873. $colors = $this->load_random_colors();
  3874. }
  3875. else
  3876. {
  3877. $colors = $this->load_gradient_colors($color1, $color2, $iterations);
  3878. }
  3879. $text = trim(stripslashes($text));
  3880. $length = strlen($text);
  3881. $result = '';
  3882. $color_counter = 0;
  3883. $TAG_OPEN = false;
  3884. for ($i = 0; $i < $length; $i++)
  3885. {
  3886. $char = substr($text, $i, 1);
  3887. // UTF-8 character encoding - BEGIN
  3888. // See http://www.faqs.org/rfcs/rfc2279.html
  3889. $code = ord($char);
  3890. if ($code >= 0x80)
  3891. {
  3892. if ($code < 0xE0)
  3893. {
  3894. // Two byte
  3895. $char = substr($text, $i, 2);
  3896. $i = $i + 1;
  3897. }
  3898. elseif ($code < 0xF0)
  3899. {
  3900. // Three byte
  3901. $char = substr($text, $i, 3);
  3902. $i = $i + 2;
  3903. }
  3904. elseif ($code < 0xF8)
  3905. {
  3906. // Four byte
  3907. $char = substr($text, $i, 4);
  3908. $i = $i + 3;
  3909. }
  3910. elseif ($code < 0xFC)
  3911. {
  3912. // Five byte
  3913. $char = substr($text, $i, 5);
  3914. $i = $i + 4;
  3915. }
  3916. elseif ($code < 0xFE)
  3917. {
  3918. // Six byte
  3919. $char = substr($text, $i, 6);
  3920. $i = $i + 5;
  3921. }
  3922. }
  3923. // UTF-8 character encoding - END
  3924. if (!$TAG_OPEN)
  3925. {
  3926. if ($char == '<')
  3927. {
  3928. $TAG_OPEN = true;
  3929. $result .= $char;
  3930. }
  3931. elseif (preg_match("#\S#i", $char))
  3932. {
  3933. $color_counter++;
  3934. $result .= '<span style="color: ' . $colors[$color_counter] . ';">' . $char . '</span>';
  3935. $color_counter = ($color_counter == $iterations) ? 0 : $color_counter;
  3936. }
  3937. else
  3938. {
  3939. $result .= $char;
  3940. }
  3941. }
  3942. else
  3943. {
  3944. if ($char == '>')
  3945. {
  3946. $TAG_OPEN = false;
  3947. }
  3948. $result .= $char;
  3949. }
  3950. }
  3951. return $result;
  3952. }
  3953. /*
  3954. * Strip only specified tags
  3955. * $tags array of tags
  3956. * $strip_content if set to true, also text within the specified tag is removed
  3957. */
  3958. function strip_only($text, $tags, $strip_content = false)
  3959. {
  3960. if (empty($text) || empty($tags))
  3961. {
  3962. return $text;
  3963. }
  3964. $content = '';
  3965. if(!is_array($tags))
  3966. {
  3967. $tags = array($tags);
  3968. }
  3969. foreach($tags as $tag)
  3970. {
  3971. if ($strip_content)
  3972. {
  3973. $content = '(.+</' . $tag . '[^>]*>|)';
  3974. }
  3975. $text = preg_replace('#</?' . $tag . '[^>]*>' . $content . '#is', '', $text);
  3976. }
  3977. return $text;
  3978. }
  3979. /*
  3980. * Undo HTML special chars
  3981. */
  3982. function html2txt($text)
  3983. {
  3984. $search = array(
  3985. '@<script[^>]*?>.*?</script>@si', // Strip out javascript
  3986. '@<[\/\!]*?[^<>]*?>@si', // Strip out HTML tags
  3987. '@<style[^>]*?>.*?</style>@siU', // Strip style tags properly
  3988. '@<![\s\S]*?--[ \t\n\r]*>@' // Strip multi-line comments including CDATA
  3989. );
  3990. $text = preg_replace($search, '', $text);
  3991. return $text;
  3992. }
  3993. /*
  3994. * Undo HTML special chars
  3995. */
  3996. function undo_htmlspecialchars($input, $full_undo = false)
  3997. {
  3998. if($full_undo)
  3999. {
  4000. $input = str_replace('&nbsp;', '', $input);
  4001. }
  4002. $input = preg_replace("/&gt;/i", ">", $input);
  4003. $input = preg_replace("/&lt;/i", "<", $input);
  4004. $input = preg_replace("/&quot;/i", "\"", $input);
  4005. $input = preg_replace("/&amp;/i", "&", $input);
  4006. if($full_undo)
  4007. {
  4008. if(preg_match_all('/&\#([0-9]+);/', $input, $matches) && sizeof($matches))
  4009. {
  4010. $list = array();
  4011. for($i = 0; $i < sizeof($matches[1]); $i++)
  4012. {
  4013. $list[$matches[1][$i]] = true;
  4014. }
  4015. $search = array();
  4016. $replace = array();
  4017. foreach($list as $var => $value)
  4018. {
  4019. $search[] = '&#' . $var . ';';
  4020. $replace[] = chr($var);
  4021. }
  4022. $input = str_replace($search, $replace, $input);
  4023. }
  4024. }
  4025. return $input;
  4026. }
  4027. /*
  4028. * This function will strip common BBCodes tags, but some of them will be left there (such as CODE or QUOTE)
  4029. */
  4030. function bbcode_killer($text, $id = false)
  4031. {
  4032. // Pad it with a space so we can distinguish between FALSE and matching the 1st char (index 0).
  4033. // This is important; bbencode_quote(), bbencode_list(), and bbencode_code() all depend on it.
  4034. $text = " " . $text;
  4035. // First: If there isn't a "[" and a "]" in the message, don't bother.
  4036. if (!(strpos($text, "[") && strpos($text, "]")))
  4037. {
  4038. // Remove padding, return.
  4039. $text = substr($text, 1);
  4040. return $text;
  4041. }
  4042. // Stripping out old bbcode_uid
  4043. if (!empty($id))
  4044. {
  4045. $text = preg_replace("/\:(([a-z0-9]:)?)" . $id . "/s", "", $text);
  4046. }
  4047. // Strip simple tags
  4048. $look_up_array = array(
  4049. //"[code]", "[/code]",
  4050. //"[php]","[/php]",
  4051. //"[cpp]","[/cpp]",
  4052. "[b]", "[/b]",
  4053. "[u]", "[/u]",
  4054. "[tt]", "[/tt]",
  4055. "[i]", "[/i]",
  4056. "[list]", "[/list]",
  4057. "[list=1]",
  4058. "[list=a]",
  4059. "[*]",
  4060. "[url]", "[/url]",
  4061. "[email]", "[/email]",
  4062. "[img]", "[img align=left]", "[img align=right]", "[/img]",
  4063. "[imgl]", "[/imgl]",
  4064. "[imgr]", "[/imgr]",
  4065. "[albumimg]", "[/albumimg]",
  4066. "[albumimgl]", "[/albumimgl]",
  4067. "[albumimgr]", "[/albumimgr]",
  4068. "[blur]", "[/blur]",
  4069. "[fade]", "[/fade]",
  4070. "[rainbow]", "[/rainbow]",
  4071. "[gradient]", "[/gradient]",
  4072. "[jiggle]", "[/jiggle]",
  4073. "[pulse]", "[/pulse]",
  4074. "[neon]", "[/neon]",
  4075. "[updown]", "[/updown]",
  4076. "[flipv]", "[/flipv]",
  4077. "[fliph]", "[/fliph]",
  4078. "[wave]", "[/wave]",
  4079. "[offtopic]", "[/offtopic]",
  4080. "[strike]", "[/strike]",
  4081. "[sup]", "[/sup]",
  4082. "[sub]", "[/sub]",
  4083. "[spoil]", "[/spoil]",
  4084. "[spoiler]", "[/spoiler]",
  4085. "[table]", "[/table]",
  4086. "[tr]", "[/tr]",
  4087. "[td]", "[/td]",
  4088. "[em]", "[/em]",
  4089. "[strong]", "[/strong]",
  4090. "[center]", "[/center]",
  4091. "[hide]", "[/hide]",
  4092. //"[]", "[/]",
  4093. "[hr]",
  4094. );
  4095. $text = str_replace($look_up_array, "", $text);
  4096. // Colours
  4097. $color_code = "(\#[0-9A-F]{6}|[a-z]+)";
  4098. $look_up_array = array(
  4099. "/\[color=" . $color_code . "\]/si", "/\[\/color\]/si",
  4100. "/\[glow=" . $color_code . "\]/si", "/\[\/glow\]/si",
  4101. "/\[shadow=" . $color_code . "\]/si", "/\[\/shadow\]/si",
  4102. "/\[highlight=" . $color_code . "\]/si", "/\[\/highlight\]/si",
  4103. "/\[size=([\-\+]?[1-3]?[0-9])\]/si", "/\[\/size\]/si",
  4104. "/\[url=([a-z0-9\-\.,\?!%\*_\/:;~\\&$@\/=\+]+)\]/si", "/\[\/url\]/si",
  4105. "/\[web=([a-z0-9\-\.,\?!%\*_\/:;~\\&$@\/=\+]+)\]/si", "/\[\/web\]/si",
  4106. "/\[font=(Arial|Arial Black|Arial Bold|Arial Bold Italic|Arial Italic|Comic Sans MS|Comic Sans MS Bold|Courier New|Courier New Bold|Courier New Bold Italic|Courier New Italic|Impact|Lucida Console|Lucida Sans Unicode|Microsoft Sans Serif|Symbol|Tahoma|Tahoma Bold|Times New Roman|Times New Roman Bold|Times New Roman Bold Italic|Times New Roman Italic|Traditional Arabic|Trebuchet MS|Trebuchet MS Bold|Trebuchet MS Bold Italic|Trebuchet MS Italic|Verdana|Verdana Bold|Verdana Bold Italic|Verdana Italic|Webdings|Wingdings|)\]/si", "/\[\/font\]/si",
  4107. "/\[font=\"(Arial|Arial Black|Arial Bold|Arial Bold Italic|Arial Italic|Comic Sans MS|Comic Sans MS Bold|Courier New|Courier New Bold|Courier New Bold Italic|Courier New Italic|Impact|Lucida Console|Lucida Sans Unicode|Microsoft Sans Serif|Symbol|Tahoma|Tahoma Bold|Times New Roman|Times New Roman Bold|Times New Roman Bold Italic|Times New Roman Italic|Traditional Arabic|Trebuchet MS|Trebuchet MS Bold|Trebuchet MS Bold Italic|Trebuchet MS Italic|Verdana|Verdana Bold|Verdana Bold Italic|Verdana Italic|Webdings|Wingdings|)\"\]/si", "/\[\/font\]/si",
  4108. "/\[marq=(left|right|up|down)\]/si", "/\[\/marq\]/si",
  4109. "/\[marquee direction=(left|right|up|down)\]/si", "/\[\/marquee\]/si",
  4110. "/\[align=(left|center|right|justify)\]/si", "/\[\/align\]/si",
  4111. );
  4112. $text = preg_replace($look_up_array, "", $text);
  4113. // [QUOTE] and [/QUOTE]
  4114. /*
  4115. $text = str_replace("[quote]","", $text);
  4116. $text = str_replace("[/quote]", "", $text);
  4117. $text = preg_replace("/\[quote=(?:\"?([^\"]*)\"?)\]/si", "", $text);
  4118. */
  4119. // Remove our padding from the string..
  4120. $text = substr($text, 1);
  4121. return $text;
  4122. }
  4123. /*
  4124. * This function will strip from a message some BBCodes, all BBCodes $uid, and some other formattings.
  4125. * The result will be suitable for email sendings.
  4126. */
  4127. function plain_message($text, $id = false)
  4128. {
  4129. $text = $this->bbcode_killer($text, $id);
  4130. //$text = preg_replace("/\r\n/", "<br />", $text);
  4131. $text = preg_replace("/\r\n/", "\n", $text);
  4132. $text = str_replace('<br />', "\n", $text);
  4133. return $text;
  4134. }
  4135. /*
  4136. * This function will strip all specified BBCodes tags or all BBCodes tags
  4137. */
  4138. function bbcode_clean($text, &$tags)
  4139. {
  4140. if (is_array($tags) && (sizeof($tags) > 0))
  4141. {
  4142. for ($i = 0; $i < sizeof($tags); $i++)
  4143. {
  4144. $tags[$i] = ($tags[$i] == '*') ? '\*' : $tags[$i];
  4145. $text = preg_replace("/\[" . $tags[$i] . "[^]^[]*\]/", '', $text);
  4146. $text = preg_replace("/\[(/?)[^]^[]" . $tags[$i] . "\]/", '', $text);
  4147. }
  4148. }
  4149. else
  4150. {
  4151. $text = preg_replace("/\[(/?)[^]^[]*\]/", '', $text);
  4152. }
  4153. $text = nl2br($text);
  4154. return $text;
  4155. }
  4156. function acronym_sort($a, $b)
  4157. {
  4158. if (strlen($a['acronym']) == strlen($b['acronym']))
  4159. {
  4160. return 0;
  4161. }
  4162. return (strlen($a['acronym']) > strlen($b['acronym'])) ? -1 : 1;
  4163. }
  4164. function acronym_pass($text)
  4165. {
  4166. if (!defined('IS_ICYPHOENIX'))
  4167. {
  4168. return $text;
  4169. }
  4170. static $orig, $repl;
  4171. // Mighty Gorgon: acronyms are not working any more with PHP 7, so we need to fix them
  4172. //return $text;
  4173. if(!isset($orig))
  4174. {
  4175. global $db, $config;
  4176. $orig = $repl = array();
  4177. $sql = 'SELECT * FROM ' . ACRONYMS_TABLE;
  4178. $db->sql_return_on_error(true);
  4179. $result = $db->sql_query($sql, 0, 'acronyms_', TOPICS_CACHE_FOLDER);
  4180. $db->sql_return_on_error(false);
  4181. if (!$result)
  4182. {
  4183. return $text;
  4184. }
  4185. while ($row = $db->sql_fetchrow($result))
  4186. {
  4187. $acronyms[] = $row;
  4188. }
  4189. $db->sql_freeresult($result);
  4190. if(sizeof($acronyms))
  4191. {
  4192. //usort($acronyms, 'acronym_sort');
  4193. // This use acronym_sort calling it from within BBCode object
  4194. usort($acronyms, array('BBCode', 'acronym_sort'));
  4195. }
  4196. for ($i = 0; $i < sizeof($acronyms); $i++)
  4197. {
  4198. /* OLD CODE FOR ACRONYMS
  4199. $orig[] = '#\b(' . phpbb_preg_quote($acronyms[$i]['acronym'], "/") . ')\b#';
  4200. $orig[] = "/(?<=.\W|\W.|^\W)" . phpbb_preg_quote($acronyms[$i]['acronym'], "/") . "(?=.\W|\W.|\W$)/";
  4201. */
  4202. $orig[] = '#\b(' . str_replace('\*', '\w*?', preg_quote(stripslashes($acronyms[$i]['acronym']), '#')) . ')\b#i';
  4203. $repl[] = '<abbr title="' . $acronyms[$i]['description'] . '">' . $acronyms[$i]['acronym'] . '</abbr>'; ;
  4204. }
  4205. }
  4206. if(sizeof($orig))
  4207. {
  4208. $segments = preg_split('#(<abbr.+?>.+?</abbr>|<.+?>)#s' , $text, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
  4209. //<?php
  4210. //Insert for formating purpose
  4211. /*
  4212. print_r($segments);
  4213. print_r(htmlspecialchars($text));
  4214. die('DEBUG');
  4215. */
  4216. $text = '';
  4217. foreach($segments as $seg)
  4218. {
  4219. if(($seg[0] != '<') && ($seg[0] != '['))
  4220. {
  4221. // Mighty Gorgon: we need to check if this fix is correct!
  4222. /*
  4223. // OLD VERSION working with PHP 5.6
  4224. $text .= str_replace('\"', '"', substr(preg_replace('#(\>(((?>([^><]+|(?R)))*)\<))#se', "preg_replace(\$orig, \$repl, '\\0')", '>' . $seg . '<'), 1, -1));
  4225. */
  4226. // New version working with PHP 7.3
  4227. $text .= str_replace('\"', '"', substr(preg_replace('#(\>(((?>([^><]+|(?R)))*)\<))#s', preg_replace($orig, $repl, '>' . $seg . '<'), '>' . $seg . '<'), 1, -1));
  4228. // Test without internal REGEX
  4229. //$text .= str_replace('\"', '"', substr(preg_replace($orig, $repl, '>' . $seg . '<'), 1, -1));
  4230. }
  4231. else
  4232. {
  4233. $text .= $seg;
  4234. }
  4235. }
  4236. }
  4237. return $text;
  4238. }
  4239. // Autolinks - BEGIN
  4240. //
  4241. // Obtain list of autolink words and build preg style replacement arrays for use by the calling script, note that the vars are passed as references this just makes it easier to return both sets of arrays
  4242. //
  4243. function obtain_autolinks_list($forum_id)
  4244. {
  4245. global $db;
  4246. $where = ($forum_id) ? ' WHERE link_forum = 0 OR link_forum IN (' . $forum_id . ')' : ' WHERE link_forum = -1';
  4247. $sql = "SELECT * FROM " . AUTOLINKS . $where;
  4248. $result = $db->sql_query($sql, 0, 'autolinks_', TOPICS_CACHE_FOLDER);
  4249. $autolinks = array();
  4250. while($row = $db->sql_fetchrow($result))
  4251. {
  4252. // Munge word boundaries to stop autolinks from linking to themselves or other autolinks in step 2 in the function below.
  4253. $row['link_url'] = preg_replace('/(\b)/', '\\1ALSPACEHOLDER', $row['link_url']);
  4254. $row['link_comment'] = preg_replace('/(\b)/', '\\1ALSPACEHOLDER', $row['link_comment']);
  4255. if($row['link_style'])
  4256. {
  4257. $row['link_style'] = preg_replace('/(\b)/', '\\1ALSPACEHOLDER', $row['link_style']);
  4258. $style = ' style="' . htmlspecialchars($row['link_style']) . '" ';
  4259. }
  4260. else
  4261. {
  4262. $style = ' ';
  4263. }
  4264. $autolinks['match'][] = '/(?<![\/\w@\.:-])(?!\.\w)(' . phpbb_preg_quote($row['link_keyword'], '/') . ')(?![\/\w@:-])(?!\.\w)/i';
  4265. if($row['link_int'])
  4266. {
  4267. $autolinks['replace'][] = '<a href="' . append_sid(htmlspecialchars($row['link_url'])) . '" target="_self"' . $style . 'title="' . htmlspecialchars($row['link_comment']) . '">' . htmlspecialchars($row['link_title']) . '</a>';
  4268. }
  4269. else
  4270. {
  4271. $autolinks['replace'][] = '<a href="' . htmlspecialchars($row['link_url']) . '" target="_blank"' . $style . 'title="' . htmlspecialchars($row['link_comment']) . '">' . htmlspecialchars($row['link_title']) . '</a>';
  4272. }
  4273. }
  4274. $db->sql_freeresult($result);
  4275. return $autolinks;
  4276. }
  4277. /**
  4278. * Autolinks
  4279. * Original Author - Jim McDonald - Edited by Mighty Gorgon
  4280. */
  4281. function autolink_text($text, $forum_id = '')
  4282. {
  4283. static $autolinks;
  4284. if (empty($text))
  4285. {
  4286. return $text;
  4287. }
  4288. if (!isset($autolinks) || !is_array($autolinks))
  4289. {
  4290. $autolinks = $this->obtain_autolinks_list($forum_id);
  4291. }
  4292. if (sizeof($autolinks))
  4293. {
  4294. global $config;
  4295. // Step 1 - move all tags out of the text and replace them with placeholders
  4296. preg_match_all('/(<a\s+.*?\/a>|<[^>]+>)/i', $text, $matches);
  4297. $matchnum = sizeof($matches[1]);
  4298. for($i = 0; $i < $matchnum; $i++)
  4299. {
  4300. $text = preg_replace('/' . preg_quote($matches[1][$i], '/') . '/', " ALPLACEHOLDER{$i}PH", $text, 1);
  4301. }
  4302. // Step 2 - s/r of the remaining text
  4303. if($config['autolink_first'])
  4304. {
  4305. $text = preg_replace($autolinks['match'], $autolinks['replace'], $text, 1);
  4306. }
  4307. else
  4308. {
  4309. $text = preg_replace($autolinks['match'], $autolinks['replace'], $text);
  4310. }
  4311. // Step 3 - replace the spaces we munged in step 1
  4312. $text = preg_replace('/ALSPACEHOLDER/', '', $text);
  4313. // Step 4 - replace the HTML tags that we removed in step 1
  4314. for($i = 0; $i < $matchnum; $i++)
  4315. {
  4316. $text = preg_replace("/ ALPLACEHOLDER{$i}PH/", $matches[1][$i], $text, 1);
  4317. }
  4318. }
  4319. return $text;
  4320. }
  4321. // Autolinks - END
  4322. /*
  4323. * Generate bbcode uid
  4324. */
  4325. function make_bbcode_uid()
  4326. {
  4327. // Unique ID for this message..
  4328. $uid = unique_id();
  4329. $uid = substr($uid, 0, BBCODE_UID_LEN);
  4330. return $uid;
  4331. }
  4332. /*
  4333. * Make a link clickable
  4334. */
  4335. function make_clickable($text)
  4336. {
  4337. $text = preg_replace('#(script|about|applet|activex|chrome):#is', "\\1:", $text);
  4338. $text = preg_replace('#(script|about|applet|activex|chrome):#is', "\\1&#058;", $text);
  4339. // pad it with a space so we can match things at the start of the 1st line.
  4340. $ret = ' ' . $text;
  4341. // matches an "xxxx://yyyy" URL at the start of a line, or after a space.
  4342. // xxxx can only be alpha characters.
  4343. // yyyy is anything up to the first space, newline, comma, double quote or <
  4344. $ret = preg_replace("#(^|[\n ])([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)#is", "\\1<a href=\"\\2\" target=\"_blank\">\\2</a>", $ret);
  4345. // matches a "www|ftp.xxxx.yyyy[/zzzz]" kinda lazy URL thing
  4346. // Must contain at least 2 dots. xxxx contains either alphanum, or "-"
  4347. // zzzz is optional.. will contain everything up to the first space, newline,
  4348. // comma, double quote or <.
  4349. $ret = preg_replace("#(^|[\n ])((www|ftp)\.[\w\#$%&~/.\-;:=,?@\[\]+]*)#is", "\\1<a href=\"http://\\2\" target=\"_blank\">\\2</a>", $ret);
  4350. // matches an email@domain type address at the start of a line, or after a space.
  4351. // Note: Only the followed chars are valid; alphanums, "-", "_" and or ".".
  4352. $ret = preg_replace("#(^|[\n ])([a-z0-9&\-_.]+?)@([\w\-]+\.([\w\-\.]+\.)*[\w]+)#i", "\\1<a href=\"mailto:\\2@\\3\">\\2@\\3</a>", $ret);
  4353. // Remove our padding..
  4354. $ret = substr($ret, 1);
  4355. return($ret);
  4356. }
  4357. }
  4358. $bbcode = new bbcode();
  4359. if (defined('SMILIES_TABLE'))
  4360. {
  4361. $bbcode->allowed_smilies = array();
  4362. $bbcode->allowed_smilies = $cache->obtain_smileys(false);
  4363. }
  4364. ?>