PageRenderTime 44ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/bbpress/includes/admin/parser.php

https://github.com/bfay/maniacal-kitten
PHP | 2073 lines | 1227 code | 12 blank | 834 comment | 120 complexity | 18517e9f6a18f12a063ec3fe2dd124a2 MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0, AGPL-1.0, LGPL-3.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. This is a compressed copy of NBBC. Do not edit!
  4. Copyright (c) 2008-9, the Phantom Inker. All rights reserved.
  5. Portions Copyright (c) 2004-2008 AddedBytes.com
  6. Redistribution and use in source and binary forms, with or without
  7. modification, are permitted provided that the following conditions
  8. are met:
  9. * Redistributions of source code must retain the above copyright
  10. notice, this list of conditions and the following disclaimer.
  11. * Redistributions in binary form must reproduce the above copyright
  12. notice, this list of conditions and the following disclaimer in
  13. the documentation and/or other materials provided with the
  14. distribution.
  15. THIS SOFTWARE IS PROVIDED BY THE PHANTOM INKER "AS IS" AND ANY EXPRESS
  16. OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  17. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  19. LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  20. CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  21. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  22. BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  23. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  24. OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  25. IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. define("BBCODE_VERSION", "1.4.5");
  28. define("BBCODE_RELEASE", "2010-09-17");
  29. define("BBCODE_VERBATIM", 2);
  30. define("BBCODE_REQUIRED", 1);
  31. define("BBCODE_OPTIONAL", 0);
  32. define("BBCODE_PROHIBIT", -1);
  33. define("BBCODE_CHECK", 1);
  34. define("BBCODE_OUTPUT", 2);
  35. define("BBCODE_ENDTAG", 5);
  36. define("BBCODE_TAG", 4);
  37. define("BBCODE_TEXT", 3);
  38. define("BBCODE_NL", 2);
  39. define("BBCODE_WS", 1);
  40. define("BBCODE_EOI", 0);
  41. define("BBCODE_LEXSTATE_TEXT", 0);
  42. define("BBCODE_LEXSTATE_TAG", 1);
  43. define("BBCODE_MODE_SIMPLE", 0);
  44. define("BBCODE_MODE_CALLBACK", 1);
  45. define("BBCODE_MODE_INTERNAL", 2);
  46. define("BBCODE_MODE_LIBRARY", 3);
  47. define("BBCODE_MODE_ENHANCED", 4);
  48. define("BBCODE_STACK_TOKEN", 0);
  49. define("BBCODE_STACK_TEXT", 1);
  50. define("BBCODE_STACK_TAG", 2);
  51. define("BBCODE_STACK_CLASS", 3);
  52. if (!function_exists('str_split')) {
  53. function str_split($string, $split_length = 1) {
  54. $array = explode("\r\n", chunk_split($string, $split_length));
  55. array_pop($array);
  56. return $array;
  57. }
  58. }
  59. $BBCode_SourceDir = dirname(__FILE__);
  60. class BBCodeLexer {
  61. var $token;
  62. var $text;
  63. var $tag;
  64. var $state;
  65. var $input;
  66. var $ptr;
  67. var $unget;
  68. var $verbatim;
  69. var $debug;
  70. var $tagmarker;
  71. var $end_tagmarker;
  72. var $pat_main;
  73. var $pat_comment;
  74. var $pat_comment2;
  75. var $pat_wiki;
  76. function BBCodeLexer($string, $tagmarker = '[') {
  77. $regex_beginmarkers = Array( '[' => '\[', '<' => '<', '{' => '\{', '(' => '\(' );
  78. $regex_endmarkers = Array( '[' => '\]', '<' => '>', '{' => '\}', '(' => '\)' );
  79. $endmarkers = Array( '[' => ']', '<' => '>', '{' => '}', '(' => ')' );
  80. if (!isset($regex_endmarkers[$tagmarker])) $tagmarker = '[';
  81. $e = $regex_endmarkers[$tagmarker];
  82. $b = $regex_beginmarkers[$tagmarker];
  83. $this->tagmarker = $tagmarker;
  84. $this->end_tagmarker = $endmarkers[$tagmarker];
  85. $this->pat_main = "/( "
  86. . "{$b}"
  87. . "(?! -- | ' | !-- | {$b}{$b} )"
  88. . "(?: [^\\n\\r{$b}{$e}] | \\\" [^\\\"\\n\\r]* \\\" | \\' [^\\'\\n\\r]* \\' )*"
  89. . "{$e}"
  90. . "| {$b}{$b} (?: [^{$e}\\r\\n] | {$e}[^{$e}\\r\\n] )* {$e}{$e}"
  91. . "| {$b} (?: -- | ' ) (?: [^{$e}\\n\\r]* ) {$e}"
  92. . "| {$b}!-- (?: [^-] | -[^-] | --[^{$e}] )* --{$e}"
  93. . "| -----+"
  94. . "| \\x0D\\x0A | \\x0A\\x0D | \\x0D | \\x0A"
  95. . "| [\\x00-\\x09\\x0B-\\x0C\\x0E-\\x20]+(?=[\\x0D\\x0A{$b}]|-----|$)"
  96. . "| (?<=[\\x0D\\x0A{$e}]|-----|^)[\\x00-\\x09\\x0B-\\x0C\\x0E-\\x20]+"
  97. . " )/Dx";
  98. $this->input = preg_split($this->pat_main, $string, -1, PREG_SPLIT_DELIM_CAPTURE);
  99. $this->pat_comment = "/^ {$b} (?: -- | ' ) /Dx";
  100. $this->pat_comment2 = "/^ {$b}!-- (?: [^-] | -[^-] | --[^{$e}] )* --{$e} $/Dx";
  101. $this->pat_wiki = "/^ {$b}{$b} ([^\\|]*) (?:\\|(.*))? {$e}{$e} $/Dx";
  102. $this->ptr = 0;
  103. $this->unget = false;
  104. $this->state = BBCODE_LEXSTATE_TEXT;
  105. $this->verbatim = false;
  106. $this->token = BBCODE_EOI;
  107. $this->tag = false;
  108. $this->text = "";
  109. }
  110. function GuessTextLength() {
  111. $length = 0;
  112. $ptr = 0;
  113. $state = BBCODE_LEXSTATE_TEXT;
  114. while ($ptr < count($this->input)) {
  115. $text = $this->input[$ptr++];
  116. if ($state == BBCODE_LEXSTATE_TEXT) {
  117. $state = BBCODE_LEXSTATE_TAG;
  118. $length += strlen($text);
  119. }
  120. else {
  121. switch (ord(substr($this->text, 0, 1))) {
  122. case 10:
  123. case 13:
  124. $state = BBCODE_LEXSTATE_TEXT;
  125. $length++;
  126. break;
  127. default:
  128. $state = BBCODE_LEXSTATE_TEXT;
  129. $length += strlen($text);
  130. break;
  131. case 40:
  132. case 60:
  133. case 91:
  134. case 123:
  135. $state = BBCODE_LEXSTATE_TEXT;
  136. break;
  137. }
  138. }
  139. }
  140. return $length;
  141. }
  142. function NextToken() {
  143. if ($this->unget) {
  144. $this->unget = false;
  145. return $this->token;
  146. }
  147. while (true) {
  148. if ($this->ptr >= count($this->input)) {
  149. $this->text = "";
  150. $this->tag = false;
  151. return $this->token = BBCODE_EOI;
  152. }
  153. $this->text = preg_replace("/[\\x00-\\x08\\x0B-\\x0C\\x0E-\\x1F]/", "",
  154. $this->input[$this->ptr++]);
  155. if ($this->verbatim) {
  156. $this->tag = false;
  157. if ($this->state == BBCODE_LEXSTATE_TEXT) {
  158. $this->state = BBCODE_LEXSTATE_TAG;
  159. $token_type = BBCODE_TEXT;
  160. }
  161. else {
  162. $this->state = BBCODE_LEXSTATE_TEXT;
  163. switch (ord(substr($this->text, 0, 1))) {
  164. case 10:
  165. case 13:
  166. $token_type = BBCODE_NL;
  167. break;
  168. default:
  169. $token_type = BBCODE_WS;
  170. break;
  171. case 45:
  172. case 40:
  173. case 60:
  174. case 91:
  175. case 123:
  176. $token_type = BBCODE_TEXT;
  177. break;
  178. }
  179. }
  180. if (strlen($this->text) > 0)
  181. return $this->token = $token_type;
  182. }
  183. else if ($this->state == BBCODE_LEXSTATE_TEXT) {
  184. $this->state = BBCODE_LEXSTATE_TAG;
  185. $this->tag = false;
  186. if (strlen($this->text) > 0)
  187. return $this->token = BBCODE_TEXT;
  188. }
  189. else {
  190. switch (ord(substr($this->text, 0, 1))) {
  191. case 10:
  192. case 13:
  193. $this->tag = false;
  194. $this->state = BBCODE_LEXSTATE_TEXT;
  195. return $this->token = BBCODE_NL;
  196. case 45:
  197. if (preg_match("/^-----/", $this->text)) {
  198. $this->tag = Array('_name' => 'rule', '_endtag' => false, '_default' => '');
  199. $this->state = BBCODE_LEXSTATE_TEXT;
  200. return $this->token = BBCODE_TAG;
  201. }
  202. else {
  203. $this->tag = false;
  204. $this->state = BBCODE_LEXSTATE_TEXT;
  205. if (strlen($this->text) > 0)
  206. return $this->token = BBCODE_TEXT;
  207. continue;
  208. }
  209. default:
  210. $this->tag = false;
  211. $this->state = BBCODE_LEXSTATE_TEXT;
  212. return $this->token = BBCODE_WS;
  213. case 40:
  214. case 60:
  215. case 91:
  216. case 123:
  217. if (preg_match($this->pat_comment, $this->text)) {
  218. $this->state = BBCODE_LEXSTATE_TEXT;
  219. continue;
  220. }
  221. if (preg_match($this->pat_comment2, $this->text)) {
  222. $this->state = BBCODE_LEXSTATE_TEXT;
  223. continue;
  224. }
  225. if (preg_match($this->pat_wiki, $this->text, $matches)) {
  226. $this->tag = Array('_name' => 'wiki', '_endtag' => false,
  227. '_default' => @$matches[1], 'title' => @$matches[2]);
  228. $this->state = BBCODE_LEXSTATE_TEXT;
  229. return $this->token = BBCODE_TAG;
  230. }
  231. $this->tag = $this->Internal_DecodeTag($this->text);
  232. $this->state = BBCODE_LEXSTATE_TEXT;
  233. return $this->token = ($this->tag['_end'] ? BBCODE_ENDTAG : BBCODE_TAG);
  234. }
  235. }
  236. }
  237. }
  238. function UngetToken() {
  239. if ($this->token !== BBCODE_EOI)
  240. $this->unget = true;
  241. }
  242. function PeekToken() {
  243. $result = $this->NextToken();
  244. if ($this->token !== BBCODE_EOI)
  245. $this->unget = true;
  246. return $result;
  247. }
  248. function SaveState() {
  249. return Array(
  250. 'token' => $this->token,
  251. 'text' => $this->text,
  252. 'tag' => $this->tag,
  253. 'state' => $this->state,
  254. 'input' => $this->input,
  255. 'ptr' => $this->ptr,
  256. 'unget' => $this->unget,
  257. 'verbatim' => $this->verbatim
  258. );
  259. }
  260. function RestoreState($state) {
  261. if (!is_array($state)) return;
  262. $this->token = @$state['token'];
  263. $this->text = @$state['text'];
  264. $this->tag = @$state['tag'];
  265. $this->state = @$state['state'];
  266. $this->input = @$state['input'];
  267. $this->ptr = @$state['ptr'];
  268. $this->unget = @$state['unget'];
  269. $this->verbatim = @$state['verbatim'];
  270. }
  271. function Internal_StripQuotes($string) {
  272. if (preg_match("/^\\\"(.*)\\\"$/", $string, $matches))
  273. return $matches[1];
  274. else if (preg_match("/^\\'(.*)\\'$/", $string, $matches))
  275. return $matches[1];
  276. else return $string;
  277. }
  278. function Internal_ClassifyPiece($ptr, $pieces) {
  279. if ($ptr >= count($pieces)) return -1;
  280. $piece = $pieces[$ptr];
  281. if ($piece == '=') return '=';
  282. else if (preg_match("/^[\\'\\\"]/", $piece)) return '"';
  283. else if (preg_match("/^[\\x00-\\x20]+$/", $piece)) return ' ';
  284. else return 'A';
  285. }
  286. function Internal_DecodeTag($tag) {
  287. $result = Array('_tag' => $tag, '_endtag' => '', '_name' => '',
  288. '_hasend' => false, '_end' => false, '_default' => false);
  289. $tag = substr($tag, 1, strlen($tag)-2);
  290. $ch = ord(substr($tag, 0, 1));
  291. if ($ch >= 0 && $ch <= 32) return $result;
  292. $pieces = preg_split("/(\\\"[^\\\"]+\\\"|\\'[^\\']+\\'|=|[\\x00-\\x20]+)/",
  293. $tag, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
  294. $ptr = 0;
  295. if (count($pieces) < 1) return $result;
  296. if (@substr($pieces[$ptr], 0, 1) == '/') {
  297. $result['_name'] = strtolower(substr($pieces[$ptr++], 1));
  298. $result['_end'] = true;
  299. }
  300. else {
  301. $result['_name'] = strtolower($pieces[$ptr++]);
  302. $result['_end'] = false;
  303. }
  304. while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ')
  305. $ptr++;
  306. $params = Array();
  307. if ($type != '=') {
  308. $result['_default'] = false;
  309. $params[] = Array('key' => '', 'value' => '');
  310. }
  311. else {
  312. $ptr++;
  313. while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ')
  314. $ptr++;
  315. if ($type == "\"")
  316. $value = $this->Internal_StripQuotes($pieces[$ptr++]);
  317. else {
  318. $after_space = false;
  319. $start = $ptr;
  320. while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) != -1) {
  321. if ($type == ' ') $after_space = true;
  322. if ($type == '=' && $after_space) break;
  323. $ptr++;
  324. }
  325. if ($type == -1) $ptr--;
  326. if ($type == '=') {
  327. $ptr--;
  328. while ($ptr > $start && $this->Internal_ClassifyPiece($ptr, $pieces) == ' ')
  329. $ptr--;
  330. while ($ptr > $start && $this->Internal_ClassifyPiece($ptr, $pieces) != ' ')
  331. $ptr--;
  332. }
  333. $value = "";
  334. for (; $start <= $ptr; $start++) {
  335. if ($this->Internal_ClassifyPiece($start, $pieces) == ' ')
  336. $value .= " ";
  337. else $value .= $this->Internal_StripQuotes($pieces[$start]);
  338. }
  339. $value = trim($value);
  340. $ptr++;
  341. }
  342. $result['_default'] = $value;
  343. $params[] = Array('key' => '', 'value' => $value);
  344. }
  345. while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) != -1) {
  346. while ($type == ' ') {
  347. $ptr++;
  348. $type = $this->Internal_ClassifyPiece($ptr, $pieces);
  349. }
  350. if ($type == 'A' || $type == '"')
  351. $key = strtolower($this->Internal_StripQuotes(@$pieces[$ptr++]));
  352. else if ($type == '=') {
  353. $ptr++;
  354. continue;
  355. }
  356. else if ($type == -1) break;
  357. while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ')
  358. $ptr++;
  359. if ($type != '=')
  360. $value = $this->Internal_StripQuotes($key);
  361. else {
  362. $ptr++;
  363. while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ')
  364. $ptr++;
  365. if ($type == '"') {
  366. $value = $this->Internal_StripQuotes($pieces[$ptr++]);
  367. }
  368. else if ($type != -1) {
  369. $value = $pieces[$ptr++];
  370. while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) != -1
  371. && $type != ' ')
  372. $value .= $pieces[$ptr++];
  373. }
  374. else $value = "";
  375. }
  376. if (substr($key, 0, 1) != '_')
  377. $result[$key] = $value;
  378. $params[] = Array('key' => $key, 'value' => $value);
  379. }
  380. $result['_params'] = $params;
  381. return $result;
  382. }
  383. }
  384. class BBCodeLibrary {
  385. var $default_smileys = Array(
  386. ':)' => 'smile.gif', ':-)' => 'smile.gif',
  387. '=)' => 'smile.gif', '=-)' => 'smile.gif',
  388. ':(' => 'frown.gif', ':-(' => 'frown.gif',
  389. '=(' => 'frown.gif', '=-(' => 'frown.gif',
  390. ':D' => 'bigsmile.gif', ':-D' => 'bigsmile.gif',
  391. '=D' => 'bigsmile.gif', '=-D' => 'bigsmile.gif',
  392. '>:('=> 'angry.gif', '>:-('=> 'angry.gif',
  393. '>=('=> 'angry.gif', '>=-('=> 'angry.gif',
  394. 'D:' => 'angry.gif', 'D-:' => 'angry.gif',
  395. 'D=' => 'angry.gif', 'D-=' => 'angry.gif',
  396. '>:)'=> 'evil.gif', '>:-)'=> 'evil.gif',
  397. '>=)'=> 'evil.gif', '>=-)'=> 'evil.gif',
  398. '>:D'=> 'evil.gif', '>:-D'=> 'evil.gif',
  399. '>=D'=> 'evil.gif', '>=-D'=> 'evil.gif',
  400. '>;)'=> 'sneaky.gif', '>;-)'=> 'sneaky.gif',
  401. '>;D'=> 'sneaky.gif', '>;-D'=> 'sneaky.gif',
  402. 'O:)' => 'saint.gif', 'O:-)' => 'saint.gif',
  403. 'O=)' => 'saint.gif', 'O=-)' => 'saint.gif',
  404. ':O' => 'surprise.gif', ':-O' => 'surprise.gif',
  405. '=O' => 'surprise.gif', '=-O' => 'surprise.gif',
  406. ':?' => 'confuse.gif', ':-?' => 'confuse.gif',
  407. '=?' => 'confuse.gif', '=-?' => 'confuse.gif',
  408. ':s' => 'worry.gif', ':-S' => 'worry.gif',
  409. '=s' => 'worry.gif', '=-S' => 'worry.gif',
  410. ':|' => 'neutral.gif', ':-|' => 'neutral.gif',
  411. '=|' => 'neutral.gif', '=-|' => 'neutral.gif',
  412. ':I' => 'neutral.gif', ':-I' => 'neutral.gif',
  413. '=I' => 'neutral.gif', '=-I' => 'neutral.gif',
  414. ':/' => 'irritated.gif', ':-/' => 'irritated.gif',
  415. '=/' => 'irritated.gif', '=-/' => 'irritated.gif',
  416. ':\\' => 'irritated.gif', ':-\\' => 'irritated.gif',
  417. '=\\' => 'irritated.gif', '=-\\' => 'irritated.gif',
  418. ':P' => 'tongue.gif', ':-P' => 'tongue.gif',
  419. '=P' => 'tongue.gif', '=-P' => 'tongue.gif',
  420. 'X-P' => 'tongue.gif',
  421. '8)' => 'bigeyes.gif', '8-)' => 'bigeyes.gif',
  422. 'B)' => 'cool.gif', 'B-)' => 'cool.gif',
  423. ';)' => 'wink.gif', ';-)' => 'wink.gif',
  424. ';D' => 'bigwink.gif', ';-D' => 'bigwink.gif',
  425. '^_^'=> 'anime.gif', '^^;' => 'sweatdrop.gif',
  426. '>_>'=> 'lookright.gif', '>.>' => 'lookright.gif',
  427. '<_<'=> 'lookleft.gif', '<.<' => 'lookleft.gif',
  428. 'XD' => 'laugh.gif', 'X-D' => 'laugh.gif',
  429. ';D' => 'bigwink.gif', ';-D' => 'bigwink.gif',
  430. ':3' => 'smile3.gif', ':-3' => 'smile3.gif',
  431. '=3' => 'smile3.gif', '=-3' => 'smile3.gif',
  432. ';3' => 'wink3.gif', ';-3' => 'wink3.gif',
  433. '<g>' => 'teeth.gif', '<G>' => 'teeth.gif',
  434. 'o.O' => 'boggle.gif', 'O.o' => 'boggle.gif',
  435. ':blue:' => 'blue.gif',
  436. ':zzz:' => 'sleepy.gif',
  437. '<3' => 'heart.gif',
  438. ':star:' => 'star.gif',
  439. );
  440. var $default_tag_rules = Array(
  441. 'b' => Array(
  442. 'simple_start' => "<b>",
  443. 'simple_end' => "</b>",
  444. 'class' => 'inline',
  445. 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),
  446. 'plain_start' => "<b>",
  447. 'plain_end' => "</b>",
  448. ),
  449. 'i' => Array(
  450. 'simple_start' => "<i>",
  451. 'simple_end' => "</i>",
  452. 'class' => 'inline',
  453. 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),
  454. 'plain_start' => "<i>",
  455. 'plain_end' => "</i>",
  456. ),
  457. 'u' => Array(
  458. 'simple_start' => "<u>",
  459. 'simple_end' => "</u>",
  460. 'class' => 'inline',
  461. 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),
  462. 'plain_start' => "<u>",
  463. 'plain_end' => "</u>",
  464. ),
  465. 's' => Array(
  466. 'simple_start' => "<strike>",
  467. 'simple_end' => "</strike>",
  468. 'class' => 'inline',
  469. 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),
  470. 'plain_start' => "<i>",
  471. 'plain_end' => "</i>",
  472. ),
  473. 'font' => Array(
  474. 'mode' => BBCODE_MODE_LIBRARY,
  475. 'allow' => Array('_default' => '/^[a-zA-Z0-9._ -]+$/'),
  476. 'method' => 'DoFont',
  477. 'class' => 'inline',
  478. 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),
  479. ),
  480. 'color' => Array(
  481. 'mode' => BBCODE_MODE_ENHANCED,
  482. 'allow' => Array('_default' => '/^#?[a-zA-Z0-9._ -]+$/'),
  483. 'template' => '<span style="color:{$_default/tw}">{$_content/v}</span>',
  484. 'class' => 'inline',
  485. 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),
  486. ),
  487. 'size' => Array(
  488. 'mode' => BBCODE_MODE_LIBRARY,
  489. 'allow' => Array('_default' => '/^[0-9.]+$/D'),
  490. 'method' => 'DoSize',
  491. 'class' => 'inline',
  492. 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),
  493. ),
  494. 'sup' => Array(
  495. 'simple_start' => "<sup>",
  496. 'simple_end' => "</sup>",
  497. 'class' => 'inline',
  498. 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),
  499. ),
  500. 'sub' => Array(
  501. 'simple_start' => "<sub>",
  502. 'simple_end' => "</sub>",
  503. 'class' => 'inline',
  504. 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),
  505. ),
  506. 'spoiler' => Array(
  507. 'simple_start' => "<span class=\"bbcode_spoiler\">",
  508. 'simple_end' => "</span>",
  509. 'class' => 'inline',
  510. 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),
  511. ),
  512. 'acronym' => Array(
  513. 'mode' => BBCODE_MODE_ENHANCED,
  514. 'template' => '<span class="bbcode_acronym" title="{$_default/e}">{$_content/v}</span>',
  515. 'class' => 'inline',
  516. 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),
  517. ),
  518. 'url' => Array(
  519. 'mode' => BBCODE_MODE_LIBRARY,
  520. 'method' => 'DoURL',
  521. 'class' => 'link',
  522. 'allow_in' => Array('listitem', 'block', 'columns', 'inline'),
  523. 'content' => BBCODE_REQUIRED,
  524. 'plain_start' => "<a href=\"{\$link}\">",
  525. 'plain_end' => "</a>",
  526. 'plain_content' => Array('_content', '_default'),
  527. 'plain_link' => Array('_default', '_content'),
  528. ),
  529. 'email' => Array(
  530. 'mode' => BBCODE_MODE_LIBRARY,
  531. 'method' => 'DoEmail',
  532. 'class' => 'link',
  533. 'allow_in' => Array('listitem', 'block', 'columns', 'inline'),
  534. 'content' => BBCODE_REQUIRED,
  535. 'plain_start' => "<a href=\"mailto:{\$link}\">",
  536. 'plain_end' => "</a>",
  537. 'plain_content' => Array('_content', '_default'),
  538. 'plain_link' => Array('_default', '_content'),
  539. ),
  540. 'wiki' => Array(
  541. 'mode' => BBCODE_MODE_LIBRARY,
  542. 'method' => "DoWiki",
  543. 'class' => 'link',
  544. 'allow_in' => Array('listitem', 'block', 'columns', 'inline'),
  545. 'end_tag' => BBCODE_PROHIBIT,
  546. 'content' => BBCODE_PROHIBIT,
  547. 'plain_start' => "<b>[",
  548. 'plain_end' => "]</b>",
  549. 'plain_content' => Array('title', '_default'),
  550. 'plain_link' => Array('_default', '_content'),
  551. ),
  552. 'img' => Array(
  553. 'mode' => BBCODE_MODE_LIBRARY,
  554. 'method' => "DoImage",
  555. 'class' => 'image',
  556. 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),
  557. 'end_tag' => BBCODE_REQUIRED,
  558. 'content' => BBCODE_REQUIRED,
  559. 'plain_start' => "[image]",
  560. 'plain_content' => Array(),
  561. ),
  562. 'rule' => Array(
  563. 'mode' => BBCODE_MODE_LIBRARY,
  564. 'method' => "DoRule",
  565. 'class' => 'block',
  566. 'allow_in' => Array('listitem', 'block', 'columns'),
  567. 'end_tag' => BBCODE_PROHIBIT,
  568. 'content' => BBCODE_PROHIBIT,
  569. 'before_tag' => "sns",
  570. 'after_tag' => "sns",
  571. 'plain_start' => "\n-----\n",
  572. 'plain_end' => "",
  573. 'plain_content' => Array(),
  574. ),
  575. 'br' => Array(
  576. 'mode' => BBCODE_MODE_SIMPLE,
  577. 'simple_start' => "<br />\n",
  578. 'simple_end' => "",
  579. 'class' => 'inline',
  580. 'allow_in' => Array('listitem', 'block', 'columns', 'inline', 'link'),
  581. 'end_tag' => BBCODE_PROHIBIT,
  582. 'content' => BBCODE_PROHIBIT,
  583. 'before_tag' => "s",
  584. 'after_tag' => "s",
  585. 'plain_start' => "\n",
  586. 'plain_end' => "",
  587. 'plain_content' => Array(),
  588. ),
  589. 'left' => Array(
  590. 'simple_start' => "\n<div class=\"bbcode_left\" style=\"text-align:left\">\n",
  591. 'simple_end' => "\n</div>\n",
  592. 'allow_in' => Array('listitem', 'block', 'columns'),
  593. 'before_tag' => "sns",
  594. 'after_tag' => "sns",
  595. 'before_endtag' => "sns",
  596. 'after_endtag' => "sns",
  597. 'plain_start' => "\n",
  598. 'plain_end' => "\n",
  599. ),
  600. 'right' => Array(
  601. 'simple_start' => "\n<div class=\"bbcode_right\" style=\"text-align:right\">\n",
  602. 'simple_end' => "\n</div>\n",
  603. 'allow_in' => Array('listitem', 'block', 'columns'),
  604. 'before_tag' => "sns",
  605. 'after_tag' => "sns",
  606. 'before_endtag' => "sns",
  607. 'after_endtag' => "sns",
  608. 'plain_start' => "\n",
  609. 'plain_end' => "\n",
  610. ),
  611. 'center' => Array(
  612. 'simple_start' => "\n<div class=\"bbcode_center\" style=\"text-align:center\">\n",
  613. 'simple_end' => "\n</div>\n",
  614. 'allow_in' => Array('listitem', 'block', 'columns'),
  615. 'before_tag' => "sns",
  616. 'after_tag' => "sns",
  617. 'before_endtag' => "sns",
  618. 'after_endtag' => "sns",
  619. 'plain_start' => "\n",
  620. 'plain_end' => "\n",
  621. ),
  622. 'indent' => Array(
  623. 'simple_start' => "\n<div class=\"bbcode_indent\" style=\"margin-left:4em\">\n",
  624. 'simple_end' => "\n</div>\n",
  625. 'allow_in' => Array('listitem', 'block', 'columns'),
  626. 'before_tag' => "sns",
  627. 'after_tag' => "sns",
  628. 'before_endtag' => "sns",
  629. 'after_endtag' => "sns",
  630. 'plain_start' => "\n",
  631. 'plain_end' => "\n",
  632. ),
  633. 'columns' => Array(
  634. 'simple_start' => "\n<table class=\"bbcode_columns\"><tbody><tr><td class=\"bbcode_column bbcode_firstcolumn\">\n",
  635. 'simple_end' => "\n</td></tr></tbody></table>\n",
  636. 'class' => 'columns',
  637. 'allow_in' => Array('listitem', 'block', 'columns'),
  638. 'end_tag' => BBCODE_REQUIRED,
  639. 'content' => BBCODE_REQUIRED,
  640. 'before_tag' => "sns",
  641. 'after_tag' => "sns",
  642. 'before_endtag' => "sns",
  643. 'after_endtag' => "sns",
  644. 'plain_start' => "\n",
  645. 'plain_end' => "\n",
  646. ),
  647. 'nextcol' => Array(
  648. 'simple_start' => "\n</td><td class=\"bbcode_column\">\n",
  649. 'class' => 'nextcol',
  650. 'allow_in' => Array('columns'),
  651. 'end_tag' => BBCODE_PROHIBIT,
  652. 'content' => BBCODE_PROHIBIT,
  653. 'before_tag' => "sns",
  654. 'after_tag' => "sns",
  655. 'before_endtag' => "sns",
  656. 'after_endtag' => "sns",
  657. 'plain_start' => "\n",
  658. 'plain_end' => "",
  659. ),
  660. 'code' => Array(
  661. 'mode' => BBCODE_MODE_ENHANCED,
  662. 'template' => "\n<div class=\"bbcode_code\">\n<div class=\"bbcode_code_head\">Code:</div>\n<div class=\"bbcode_code_body\" style=\"white-space:pre\">{\$_content/v}</div>\n</div>\n",
  663. 'class' => 'code',
  664. 'allow_in' => Array('listitem', 'block', 'columns'),
  665. 'content' => BBCODE_VERBATIM,
  666. 'before_tag' => "sns",
  667. 'after_tag' => "sn",
  668. 'before_endtag' => "sn",
  669. 'after_endtag' => "sns",
  670. 'plain_start' => "\n<b>Code:</b>\n",
  671. 'plain_end' => "\n",
  672. ),
  673. 'quote' => Array(
  674. 'mode' => BBCODE_MODE_LIBRARY,
  675. 'method' => "DoQuote",
  676. 'allow_in' => Array('listitem', 'block', 'columns'),
  677. 'before_tag' => "sns",
  678. 'after_tag' => "sns",
  679. 'before_endtag' => "sns",
  680. 'after_endtag' => "sns",
  681. 'plain_start' => "\n<b>Quote:</b>\n",
  682. 'plain_end' => "\n",
  683. ),
  684. 'list' => Array(
  685. 'mode' => BBCODE_MODE_LIBRARY,
  686. 'method' => 'DoList',
  687. 'class' => 'list',
  688. 'allow_in' => Array('listitem', 'block', 'columns'),
  689. 'before_tag' => "sns",
  690. 'after_tag' => "sns",
  691. 'before_endtag' => "sns",
  692. 'after_endtag' => "sns",
  693. 'plain_start' => "\n",
  694. 'plain_end' => "\n",
  695. ),
  696. '*' => Array(
  697. 'simple_start' => "<li>",
  698. 'simple_end' => "</li>\n",
  699. 'class' => 'listitem',
  700. 'allow_in' => Array('list'),
  701. 'end_tag' => BBCODE_OPTIONAL,
  702. 'before_tag' => "s",
  703. 'after_tag' => "s",
  704. 'before_endtag' => "sns",
  705. 'after_endtag' => "sns",
  706. 'plain_start' => "\n * ",
  707. 'plain_end' => "\n",
  708. ),
  709. );
  710. function DoURL($bbcode, $action, $name, $default, $params, $content) {
  711. if ($action == BBCODE_CHECK) return true;
  712. $url = is_string($default) ? $default : $bbcode->UnHTMLEncode(strip_tags($content));
  713. if ($bbcode->IsValidURL($url)) {
  714. if ($bbcode->debug)
  715. print "ISVALIDURL<br />";
  716. if ($bbcode->url_targetable !== false && isset($params['target']))
  717. $target = " target=\"" . htmlspecialchars($params['target']) . "\"";
  718. else $target = "";
  719. if ($bbcode->url_target !== false)
  720. if (!($bbcode->url_targetable == 'override' && isset($params['target'])))
  721. $target = " target=\"" . htmlspecialchars($bbcode->url_target) . "\"";
  722. return '<a href="' . htmlspecialchars($url) . '" class="bbcode_url"' . $target . '>' . $content . '</a>';
  723. }
  724. else return htmlspecialchars($params['_tag']) . $content . htmlspecialchars($params['_endtag']);
  725. }
  726. function DoEmail($bbcode, $action, $name, $default, $params, $content) {
  727. if ($action == BBCODE_CHECK) return true;
  728. $email = is_string($default) ? $default : $bbcode->UnHTMLEncode(strip_tags($content));
  729. if ($bbcode->IsValidEmail($email))
  730. return '<a href="mailto:' . htmlspecialchars($email) . '" class="bbcode_email">' . $content . '</a>';
  731. else return htmlspecialchars($params['_tag']) . $content . htmlspecialchars($params['_endtag']);
  732. }
  733. function DoSize($bbcode, $action, $name, $default, $params, $content) {
  734. switch ($default) {
  735. case '0': $size = '.5em'; break;
  736. case '1': $size = '.67em'; break;
  737. case '2': $size = '.83em'; break;
  738. default:
  739. case '3': $size = '1.0em'; break;
  740. case '4': $size = '1.17em'; break;
  741. case '5': $size = '1.5em'; break;
  742. case '6': $size = '2.0em'; break;
  743. case '7': $size = '2.5em'; break;
  744. }
  745. return "<span style=\"font-size:$size\">$content</span>";
  746. }
  747. function DoFont($bbcode, $action, $name, $default, $params, $content) {
  748. $fonts = explode(",", $default);
  749. $result = "";
  750. $special_fonts = Array(
  751. 'serif' => 'serif',
  752. 'sans-serif' => 'sans-serif',
  753. 'sans serif' => 'sans-serif',
  754. 'sansserif' => 'sans-serif',
  755. 'sans' => 'sans-serif',
  756. 'cursive' => 'cursive',
  757. 'fantasy' => 'fantasy',
  758. 'monospace' => 'monospace',
  759. 'mono' => 'monospace',
  760. );
  761. foreach ($fonts as $font) {
  762. $font = trim($font);
  763. if (isset($special_fonts[$font])) {
  764. if (strlen($result) > 0) $result .= ",";
  765. $result .= $special_fonts[$font];
  766. }
  767. else if (strlen($font) > 0) {
  768. if (strlen($result) > 0) $result .= ",";
  769. $result .= "'$font'";
  770. }
  771. }
  772. return "<span style=\"font-family:$result\">$content</span>";
  773. }
  774. function DoWiki($bbcode, $action, $name, $default, $params, $content) {
  775. $name = $bbcode->Wikify($default);
  776. if ($action == BBCODE_CHECK)
  777. return strlen($name) > 0;
  778. $title = trim(@$params['title']);
  779. if (strlen($title) <= 0) $title = trim($default);
  780. return "<a href=\"{$bbcode->wiki_url}$name\" class=\"bbcode_wiki\">"
  781. . htmlspecialchars($title) . "</a>";
  782. }
  783. function DoImage($bbcode, $action, $name, $default, $params, $content) {
  784. if ($action == BBCODE_CHECK) return true;
  785. $content = trim($bbcode->UnHTMLEncode(strip_tags($content)));
  786. if (preg_match("/\\.(?:gif|jpeg|jpg|jpe|png)$/", $content)) {
  787. if (preg_match("/^[a-zA-Z0-9_][^:]+$/", $content)) {
  788. if (!preg_match("/(?:\\/\\.\\.\\/)|(?:^\\.\\.\\/)|(?:^\\/)/", $content)) {
  789. $info = @getimagesize("{$bbcode->local_img_dir}/{$content}");
  790. if ($info[2] == IMAGETYPE_GIF || $info[2] == IMAGETYPE_JPEG || $info[2] == IMAGETYPE_PNG) {
  791. return "<img src=\""
  792. . htmlspecialchars("{$bbcode->local_img_url}/{$content}") . "\" alt=\""
  793. . htmlspecialchars(basename($content)) . "\" width=\""
  794. . htmlspecialchars($info[0]) . "\" height=\""
  795. . htmlspecialchars($info[1]) . "\" class=\"bbcode_img\" />";
  796. }
  797. }
  798. }
  799. else if ($bbcode->IsValidURL($content, false)) {
  800. return "<img src=\"" . htmlspecialchars($content) . "\" alt=\""
  801. . htmlspecialchars(basename($content)) . "\" class=\"bbcode_img\" />";
  802. }
  803. }
  804. return htmlspecialchars($params['_tag']) . htmlspecialchars($content) . htmlspecialchars($params['_endtag']);
  805. }
  806. function DoRule($bbcode, $action, $name, $default, $params, $content) {
  807. if ($action == BBCODE_CHECK) return true;
  808. else return $bbcode->rule_html;
  809. }
  810. function DoQuote($bbcode, $action, $name, $default, $params, $content) {
  811. if ($action == BBCODE_CHECK) return true;
  812. if (isset($params['name'])) {
  813. $title = htmlspecialchars(trim($params['name'])) . " wrote";
  814. if (isset($params['date']))
  815. $title .= " on " . htmlspecialchars(trim($params['date']));
  816. $title .= ":";
  817. if (isset($params['url'])) {
  818. $url = trim($params['url']);
  819. if ($bbcode->IsValidURL($url))
  820. $title = "<a href=\"" . htmlspecialchars($params['url']) . "\">" . $title . "</a>";
  821. }
  822. }
  823. else if (!is_string($default))
  824. $title = "Quote:";
  825. else $title = htmlspecialchars(trim($default)) . " wrote:";
  826. return "\n<div class=\"bbcode_quote\">\n<div class=\"bbcode_quote_head\">"
  827. . $title . "</div>\n<div class=\"bbcode_quote_body\">"
  828. . $content . "</div>\n</div>\n";
  829. }
  830. function DoList($bbcode, $action, $name, $default, $params, $content) {
  831. $list_styles = Array(
  832. '1' => 'decimal',
  833. '01' => 'decimal-leading-zero',
  834. 'i' => 'lower-roman',
  835. 'I' => 'upper-roman',
  836. 'a' => 'lower-alpha',
  837. 'A' => 'upper-alpha',
  838. );
  839. $ci_list_styles = Array(
  840. 'circle' => 'circle',
  841. 'disc' => 'disc',
  842. 'square' => 'square',
  843. 'greek' => 'lower-greek',
  844. 'armenian' => 'armenian',
  845. 'georgian' => 'georgian',
  846. );
  847. $ul_types = Array(
  848. 'circle' => 'circle',
  849. 'disc' => 'disc',
  850. 'square' => 'square',
  851. );
  852. $default = trim($default);
  853. if ($action == BBCODE_CHECK) {
  854. if (!is_string($default) || strlen($default) == "") return true;
  855. else if (isset($list_styles[$default])) return true;
  856. else if (isset($ci_list_styles[strtolower($default)])) return true;
  857. else return false;
  858. }
  859. if (!is_string($default) || strlen($default) == "") {
  860. $elem = 'ul';
  861. $type = '';
  862. }
  863. else if ($default == '1') {
  864. $elem = 'ol';
  865. $type = '';
  866. }
  867. else if (isset($list_styles[$default])) {
  868. $elem = 'ol';
  869. $type = $list_styles[$default];
  870. }
  871. else {
  872. $default = strtolower($default);
  873. if (isset($ul_types[$default])) {
  874. $elem = 'ul';
  875. $type = $ul_types[$default];
  876. }
  877. else if (isset($ci_list_styles[$default])) {
  878. $elem = 'ol';
  879. $type = $ci_list_styles[$default];
  880. }
  881. }
  882. if (strlen($type))
  883. return "\n<$elem class=\"bbcode_list\" style=\"list-style-type:$type\">\n$content</$elem>\n";
  884. else return "\n<$elem class=\"bbcode_list\">\n$content</$elem>\n";
  885. }
  886. }
  887. class BBCodeEmailAddressValidator {
  888. function check_email_address($strEmailAddress) {
  889. if (preg_match('/[\x00-\x1F\x7F-\xFF]/', $strEmailAddress)) {
  890. return false;
  891. }
  892. $intAtSymbol = strrpos($strEmailAddress, '@');
  893. if ($intAtSymbol === false) {
  894. return false;
  895. }
  896. $arrEmailAddress[0] = substr($strEmailAddress, 0, $intAtSymbol);
  897. $arrEmailAddress[1] = substr($strEmailAddress, $intAtSymbol + 1);
  898. $arrTempAddress[0] = preg_replace('/"[^"]+"/'
  899. ,''
  900. ,$arrEmailAddress[0]);
  901. $arrTempAddress[1] = $arrEmailAddress[1];
  902. $strTempAddress = $arrTempAddress[0] . $arrTempAddress[1];
  903. if (strrpos($strTempAddress, '@') !== false) {
  904. return false;
  905. }
  906. if (!$this->check_local_portion($arrEmailAddress[0])) {
  907. return false;
  908. }
  909. if (!$this->check_domain_portion($arrEmailAddress[1])) {
  910. return false;
  911. }
  912. return true;
  913. }
  914. function check_local_portion($strLocalPortion) {
  915. if (!$this->check_text_length($strLocalPortion, 1, 64)) {
  916. return false;
  917. }
  918. $arrLocalPortion = explode('.', $strLocalPortion);
  919. for ($i = 0, $max = sizeof($arrLocalPortion); $i < $max; $i++) {
  920. if (!preg_match('.^('
  921. . '([A-Za-z0-9!#$%&\'*+/=?^_`{|}~-]'
  922. . '[A-Za-z0-9!#$%&\'*+/=?^_`{|}~-]{0,63})'
  923. .'|'
  924. . '("[^\\\"]{0,62}")'
  925. .')$.'
  926. ,$arrLocalPortion[$i])) {
  927. return false;
  928. }
  929. }
  930. return true;
  931. }
  932. function check_domain_portion($strDomainPortion) {
  933. if (!$this->check_text_length($strDomainPortion, 1, 255)) {
  934. return false;
  935. }
  936. if (preg_match('/^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])'
  937. .'(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}$/'
  938. ,$strDomainPortion) ||
  939. preg_match('/^\[(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])'
  940. .'(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}\]$/'
  941. ,$strDomainPortion)) {
  942. return true;
  943. } else {
  944. $arrDomainPortion = explode('.', $strDomainPortion);
  945. if (sizeof($arrDomainPortion) < 2) {
  946. return false;
  947. }
  948. for ($i = 0, $max = sizeof($arrDomainPortion); $i < $max; $i++) {
  949. if (!$this->check_text_length($arrDomainPortion[$i], 1, 63)) {
  950. return false;
  951. }
  952. if (!preg_match('/^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|'
  953. .'([A-Za-z0-9]+))$/', $arrDomainPortion[$i])) {
  954. return false;
  955. }
  956. }
  957. }
  958. return true;
  959. }
  960. function check_text_length($strText, $intMinimum, $intMaximum) {
  961. $intTextLength = strlen($strText);
  962. if (($intTextLength < $intMinimum) || ($intTextLength > $intMaximum)) {
  963. return false;
  964. } else {
  965. return true;
  966. }
  967. }
  968. }
  969. class BBCode {
  970. var $tag_rules;
  971. var $defaults;
  972. var $current_class;
  973. var $root_class;
  974. var $lost_start_tags;
  975. var $start_tags;
  976. var $allow_ampersand;
  977. var $tag_marker;
  978. var $ignore_newlines;
  979. var $plain_mode;
  980. var $detect_urls;
  981. var $url_pattern;
  982. var $output_limit;
  983. var $text_length;
  984. var $was_limited;
  985. var $limit_tail;
  986. var $limit_precision;
  987. var $smiley_dir;
  988. var $smiley_url;
  989. var $smileys;
  990. var $smiley_regex;
  991. var $enable_smileys;
  992. var $wiki_url;
  993. var $local_img_dir;
  994. var $local_img_url;
  995. var $url_targetable;
  996. var $url_target;
  997. var $rule_html;
  998. var $pre_trim;
  999. var $post_trim;
  1000. var $debug;
  1001. /* ADDED */
  1002. // singleton instance
  1003. private static $instance;
  1004. // private constructor function
  1005. // to prevent external instantiation
  1006. private function __construct()
  1007. {
  1008. $this->defaults = new BBCodeLibrary;
  1009. $this->tag_rules = $this->defaults->default_tag_rules;
  1010. $this->smileys = $this->defaults->default_smileys;
  1011. $this->enable_smileys = true;
  1012. $this->smiley_regex = false;
  1013. $this->smiley_dir = $this->GetDefaultSmileyDir();
  1014. $this->smiley_url = $this->GetDefaultSmileyURL();
  1015. $this->wiki_url = $this->GetDefaultWikiURL();
  1016. $this->local_img_dir = $this->GetDefaultLocalImgDir();
  1017. $this->local_img_url = $this->GetDefaultLocalImgURL();
  1018. $this->rule_html = $this->GetDefaultRuleHTML();
  1019. $this->pre_trim = "";
  1020. $this->post_trim = "";
  1021. $this->root_class = 'block';
  1022. $this->lost_start_tags = Array();
  1023. $this->start_tags = Array();
  1024. $this->tag_marker = '[';
  1025. $this->allow_ampsersand = false;
  1026. $this->current_class = $this->root_class;
  1027. $this->debug = false;
  1028. $this->ignore_newlines = false;
  1029. $this->output_limit = 0;
  1030. $this->plain_mode = false;
  1031. $this->was_limited = false;
  1032. $this->limit_tail = "...";
  1033. $this->limit_precision = 0.15;
  1034. $this->detect_urls = false;
  1035. $this->url_pattern = '<a href="{$url/h}">{$text/h}</a>';
  1036. $this->url_targetable = false;
  1037. $this->url_target = false;
  1038. }
  1039. // getInstance method
  1040. public static function getInstance()
  1041. {
  1042. if(!self::$instance)
  1043. {
  1044. self::$instance = new self();
  1045. }
  1046. return self::$instance;
  1047. }
  1048. /* ADDED */
  1049. function SetPreTrim($trim = "a") { $this->pre_trim = $trim; }
  1050. function GetPreTrim() { return $this->pre_trim; }
  1051. function SetPostTrim($trim = "a") { $this->post_trim = $trim; }
  1052. function GetPostTrim() { return $this->post_trim; }
  1053. function SetRoot($class = 'block') { $this->root_class = $class; }
  1054. function SetRootInline() { $this->root_class = 'inline'; }
  1055. function SetRootBlock() { $this->root_class = 'block'; }
  1056. function GetRoot() { return $this->root_class; }
  1057. function SetDebug($enable = true) { $this->debug = $enable; }
  1058. function GetDebug() { return $this->debug; }
  1059. function SetAllowAmpersand($enable = true) { $this->allow_ampersand = $enable; }
  1060. function GetAllowAmpersand() { return $this->allow_ampersand; }
  1061. function SetTagMarker($marker = '[') { $this->tag_marker = $marker; }
  1062. function GetTagMarker() { return $this->tag_marker; }
  1063. function SetIgnoreNewlines($ignore = true) { $this->ignore_newlines = $ignore; }
  1064. function GetIgnoreNewlines() { return $this->ignore_newlines; }
  1065. function SetLimit($limit = 0) { $this->output_limit = $limit; }
  1066. function GetLimit() { return $this->output_limit; }
  1067. function SetLimitTail($tail = "...") { $this->limit_tail = $tail; }
  1068. function GetLimitTail() { return $this->limit_tail; }
  1069. function SetLimitPrecision($prec = 0.15) { $this->limit_precision = $prec; }
  1070. function GetLimitPrecision() { return $this->limit_precision; }
  1071. function WasLimited() { return $this->was_limited; }
  1072. function SetPlainMode($enable = true) { $this->plain_mode = $enable; }
  1073. function GetPlainMode() { return $this->plain_mode; }
  1074. function SetDetectURLs($enable = true) { $this->detect_urls = $enable; }
  1075. function GetDetectURLs() { return $this->detect_urls; }
  1076. function SetURLPattern($pattern) { $this->url_pattern = $pattern; }
  1077. function GetURLPattern() { return $this->url_pattern; }
  1078. function SetURLTargetable($enable) { $this->url_targetable = $enable; }
  1079. function GetURLTargetable() { return $this->url_targetable; }
  1080. function SetURLTarget($target) { $this->url_target = $target; }
  1081. function GetURLTarget() { return $this->url_target; }
  1082. function AddRule($name, $rule) { $this->tag_rules[$name] = $rule; }
  1083. function RemoveRule($name) { unset($this->tag_rules[$name]); }
  1084. function GetRule($name) { return isset($this->tag_rules[$name])
  1085. ? $this->tag_rules[$name] : false; }
  1086. function ClearRules() { $this->tag_rules = Array(); }
  1087. function GetDefaultRule($name) { return isset($this->defaults->default_tag_rules[$name])
  1088. ? $this->defaults->default_tag_rules[$name] : false; }
  1089. function SetDefaultRule($name) { if (isset($this->defaults->default_tag_rules[$name]))
  1090. $this->AddRule($name, $this->defaults->default_tag_rules[$name]);
  1091. else $this->RemoveRule($name); }
  1092. function GetDefaultRules() { return $this->defaults->default_tag_rules; }
  1093. function SetDefaultRules() { $this->tag_rules = $this->defaults->default_tag_rules; }
  1094. function SetWikiURL($url) { $this->wiki_url = $url; }
  1095. function GetWikiURL($url) { return $this->wiki_url; }
  1096. function GetDefaultWikiURL() { return '/?page='; }
  1097. function SetLocalImgDir($path) { $this->local_img_dir = $path; }
  1098. function GetLocalImgDir() { return $this->local_img_dir; }
  1099. function GetDefaultLocalImgDir() { return "img"; }
  1100. function SetLocalImgURL($path) { $this->local_img_url = $path; }
  1101. function GetLocalImgURL() { return $this->local_img_url; }
  1102. function GetDefaultLocalImgURL() { return "img"; }
  1103. function SetRuleHTML($html) { $this->rule_html = $html; }
  1104. function GetRuleHTML() { return $this->rule_html; }
  1105. function GetDefaultRuleHTML() { return "\n<hr class=\"bbcode_rule\" />\n"; }
  1106. function AddSmiley($code, $image) { $this->smileys[$code] = $image; $this->smiley_regex = false; }
  1107. function RemoveSmiley($code) { unset($this->smileys[$code]); $this->smiley_regex = false; }
  1108. function GetSmiley($code) { return isset($this->smileys[$code])
  1109. ? $this->smileys[$code] : false; }
  1110. function ClearSmileys() { $this->smileys = Array(); $this->smiley_regex = false; }
  1111. function GetDefaultSmiley($code) { return isset($this->defaults->default_smileys[$code])
  1112. ? $this->defaults->default_smileys[$code] : false; }
  1113. function SetDefaultSmiley($code) { $this->smileys[$code] = @$this->defaults->default_smileys[$code];
  1114. $this->smiley_regex = false; }
  1115. function GetDefaultSmileys() { return $this->defaults->default_smileys; }
  1116. function SetDefaultSmileys() { $this->smileys = $this->defaults->default_smileys;
  1117. $this->smiley_regex = false; }
  1118. function SetSmileyDir($path) { $this->smiley_dir = $path; }
  1119. function GetSmileyDir() { return $this->smiley_dir; }
  1120. function GetDefaultSmileyDir() { return "smileys"; }
  1121. function SetSmileyURL($path) { $this->smiley_url = $path; }
  1122. function GetSmileyURL() { return $this->smiley_url; }
  1123. function GetDefaultSmileyURL() { return "smileys"; }
  1124. function SetEnableSmileys($enable = true) { $this->enable_smileys = $enable; }
  1125. function GetEnableSmileys() { return $this->enable_smileys; }
  1126. function nl2br($string) {
  1127. return preg_replace("/\\x0A|\\x0D|\\x0A\\x0D|\\x0D\\x0A/", "<br />\n", $string);
  1128. }
  1129. function UnHTMLEncode($string) {
  1130. if (function_exists("html_entity_decode"))
  1131. return html_entity_decode($string);
  1132. $string = preg_replace('~&#x([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $string);
  1133. $string = preg_replace('~&#([0-9]+);~e', 'chr("\\1")', $string);
  1134. $trans_tbl = get_html_translation_table(HTML_ENTITIES);
  1135. $trans_tbl = array_flip($trans_tbl);
  1136. return strtr($string, $trans_tbl);
  1137. }
  1138. function Wikify($string) {
  1139. return rawurlencode(str_replace(" ", "_",
  1140. trim(preg_replace("/[!?;@#\$%\\^&*<>=+`~\\x00-\\x20_-]+/", " ", $string))));
  1141. }
  1142. function IsValidURL($string, $email_too = true) {
  1143. if (preg_match("/^
  1144. (?:https?|ftp):\\/\\/
  1145. (?:
  1146. (?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+
  1147. [a-zA-Z0-9]
  1148. (?:[a-zA-Z0-9-]*[a-zA-Z0-9])?
  1149. |
  1150. \\[
  1151. (?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}
  1152. (?:
  1153. 25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:
  1154. (?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21-\\x5A\\x53-\\x7F]
  1155. |\\\\[\\x01-\\x09\\x0B\\x0C\\x0E-\\x7F])+
  1156. )
  1157. \\]
  1158. )
  1159. (?::[0-9]{1,5})?
  1160. (?:[\\/\\?\\#][^\\n\\r]*)?
  1161. $/Dx", $string)) return true;
  1162. if (preg_match("/^[^:]+([\\/\\\\?#][^\\r\\n]*)?$/D", $string))
  1163. return true;
  1164. if ($email_too)
  1165. if (substr($string, 0, 7) == "mailto:")
  1166. return $this->IsValidEmail(substr($string, 7));
  1167. return false;
  1168. }
  1169. function IsValidEmail($string) {
  1170. $validator = new BBCodeEmailAddressValidator;
  1171. return $validator->check_email_address($string);
  1172. /*
  1173. return preg_match("/^
  1174. (?:
  1175. [a-z0-9\\!\\#\\\$\\%\\&\\'\\*\\+\\/=\\?\\^_`\\{\\|\\}~-]+
  1176. (?:\.[a-z0-9\\!\\#\\\$\\%\\&\\'\\*\\+\\/=\\?\\^_`\\{\\|\\}~-]+)*
  1177. |
  1178. \"(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]
  1179. |\\\\[\\x01-\\x09\\x0B\\x0C\\x0E-\\x7F])*\"
  1180. )
  1181. @
  1182. (?:
  1183. (?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+
  1184. [a-z0-9]
  1185. (?:[a-z0-9-]*[a-z0-9])?
  1186. |
  1187. \\[
  1188. (?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}
  1189. (?:
  1190. 25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:
  1191. (?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21-\\x5A\\x53-\\x7F]
  1192. |\\\\[\\x01-\\x09\\x0B\\x0C\\x0E-\\x7F])+
  1193. )
  1194. \\]
  1195. )
  1196. $/Dx", $string);
  1197. */
  1198. }
  1199. function HTMLEncode($string) {
  1200. if (!$this->allow_ampersand)
  1201. return htmlspecialchars($string);
  1202. else return str_replace(Array('<', '>', '"'),
  1203. Array('&lt;', '&gt;', '&quot;'), $string);
  1204. }
  1205. function FixupOutput($string) {
  1206. if (!$this->detect_urls) {
  1207. $output = $this->Internal_ProcessSmileys($string);
  1208. }
  1209. else {
  1210. $chunks = $this->Internal_AutoDetectURLs($string);
  1211. $output = Array();
  1212. if (count($chunks)) {
  1213. $is_a_url = false;
  1214. foreach ($chunks as $index => $chunk) {
  1215. if (!$is_a_url) {
  1216. $chunk = $this->Internal_ProcessSmileys($chunk);
  1217. }
  1218. $output[] = $chunk;
  1219. $is_a_url = !$is_a_url;
  1220. }
  1221. }
  1222. $output = implode("", $output);
  1223. }
  1224. return $output;
  1225. }
  1226. function Internal_ProcessSmileys($string) {
  1227. if (!$this->enable_smileys || $this->plain_mode) {
  1228. $output = $this->HTMLEncode($string);
  1229. }
  1230. else {
  1231. if ($this->smiley_regex === false) {
  1232. $this->Internal_RebuildSmileys();
  1233. }
  1234. $tokens = preg_split($this->smiley_regex, $string, -1, PREG_SPLIT_DELIM_CAPTURE);
  1235. if (count($tokens) <= 1) {
  1236. $output = $this->HTMLEncode($string);
  1237. }
  1238. else {
  1239. $output = "";
  1240. $is_a_smiley = false;
  1241. foreach ($tokens as $token) {
  1242. if (!$is_a_smiley) {
  1243. $output .= $this->HTMLEncode($token);
  1244. }
  1245. else {
  1246. if (isset($this->smiley_info[$token])) {
  1247. $info = $this->smiley_info[$token];
  1248. }
  1249. else {
  1250. $info = @getimagesize($this->smiley_dir . '/' . $this->smileys[$token]);
  1251. $this->smiley_info[$token] = $info;
  1252. }
  1253. $alt = htmlspecialchars($token);
  1254. $output .= "<img src=\"" . htmlspecialchars($this->smiley_url . '/' . $this->smileys[$token])
  1255. . "\" width=\"{$info[0]}\" height=\"{$info[1]}\""
  1256. . " alt=\"$alt\" title=\"$alt\" class=\"bbcode_smiley\" />";
  1257. }
  1258. $is_a_smiley = !$is_a_smiley;
  1259. }
  1260. }
  1261. }
  1262. return $output;
  1263. }
  1264. function Internal_RebuildSmileys() {
  1265. $regex = Array("/(?<![\\w])(");
  1266. $first = true;
  1267. foreach ($this->smileys as $code => $filename) {
  1268. if (!$first) $regex[] = "|";
  1269. $regex[] = preg_quote("$code", '/');
  1270. $first = false;
  1271. }
  1272. $regex[] = ")(?![\\w])/";
  1273. $this->smiley_regex = implode("", $regex);
  1274. }
  1275. function Internal_AutoDetectURLs($string) {
  1276. $output = preg_split("/( (?:
  1277. (?:https?|ftp) : \\/*
  1278. (?:
  1279. (?: (?: [a-zA-Z0-9-]{2,} \\. )+
  1280. (?: arpa | com | org | net | edu | gov | mil | int | [a-z]{2}
  1281. | aero | biz | coop | info | museum | name | pro
  1282. | example | invalid | localhost | test | local | onion | swift ) )
  1283. | (?: [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} )
  1284. | (?: [0-9A-Fa-f:]+ : [0-9A-Fa-f]{1,4} )
  1285. )
  1286. (?: : [0-9]+ )?
  1287. (?! [a-zA-Z0-9.:-] )
  1288. (?:
  1289. \\/
  1290. [^&?#\\(\\)\\[\\]\\{\\}<>\\'\\\"\\x00-\\x20\\x7F-\\xFF]*
  1291. )?
  1292. (?:
  1293. [?#]
  1294. [^\\(\\)\\[\\]\\{\\}<>\\'\\\"\\x00-\\x20\\x7F-\\xFF]+
  1295. )?
  1296. ) | (?:
  1297. (?:
  1298. (?: (?: [a-zA-Z0-9-]{2,} \\. )+
  1299. (?: arpa | com | org | net | edu | gov | mil | int | [a-z]{2}
  1300. | aero | biz | coop | info | museum | name | pro
  1301. | example | invalid | localhost | test | local | onion | swift ) )
  1302. | (?: [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} )
  1303. )
  1304. (?: : [0-9]+ )?
  1305. (?! [a-zA-Z0-9.:-] )
  1306. (?:
  1307. \\/
  1308. [^&?#\\(\\)\\[\\]\\{\\}<>\\'\\\"\\x00-\\x20\\x7F-\\xFF]*
  1309. )?
  1310. (?:
  1311. [?#]
  1312. [^\\(\\)\\[\\]\\{\\}<>\\'\\\"\\x00-\\x20\\x7F-\\xFF]+
  1313. )?
  1314. ) | (?:
  1315. [a-zA-Z0-9._-]{2,} @
  1316. (?:
  1317. (?: (?: [a-zA-Z0-9-]{2,} \\. )+
  1318. (?: arpa | com | org | net | edu | gov | mil | int | [a-z]{2}
  1319. | aero | biz | coop | info | museum | name | pro
  1320. | example | invalid | localhost | test | local | onion | swift ) )
  1321. | (?: [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} )
  1322. )
  1323. ) )/Dx", $string, -1, PREG_SPLIT_DELIM_CAPTURE);
  1324. if (count($output) > 1) {
  1325. $is_a_url = false;
  1326. foreach ($output as $index => $token) {
  1327. if ($is_a_url) {
  1328. if (preg_match("/^[a-zA-Z0-9._-]{2,}@/", $token)) {
  1329. $url = "mailto:" . $token;
  1330. }
  1331. else if (preg_match("/^(https?:|ftp:)\\/*([^\\/&?#]+)\\/*(.*)\$/", $token, $matches)) {
  1332. $url = $matches[1] . '/' . '/' . $matches[2] . "/" . $matches[3];
  1333. }
  1334. else {
  1335. preg_match("/^([^\\/&?#]+)\\/*(.*)\$/", $token, $matches);
  1336. $url = "http:/" . "/" . $matches[1] . "/" . $matches[2];
  1337. }
  1338. $params = @parse_url($url);
  1339. if (!is_array($params)) $params = Array();
  1340. $params['url'] = $url;
  1341. $params['link'] = $url;
  1342. $params['text'] = $token;
  1343. $output[$index] = $this->FillTemplate($this->url_pattern, $params);
  1344. }
  1345. $is_a_url = !$is_a_url;
  1346. }
  1347. }
  1348. return $output;
  1349. }
  1350. function FillTemplate($template, $insert_array, $default_array = Array()) {
  1351. $pieces = preg_split('/(\{\$[a-zA-Z0-9_.:\/-]+\})/', $template,
  1352. -1, PREG_SPLIT_DELIM_CAPTURE);
  1353. if (count($pieces) <= 1)
  1354. return $template;
  1355. $result = Array();
  1356. $is_an_insert = false;
  1357. foreach ($pieces as $piece) {
  1358. if (!$is_an_insert) {
  1359. $result[] = $piece;
  1360. }
  1361. else if (!preg_match('/\{\$([a-zA-Z0-9_:-]+)((?:\\.[a-zA-Z0-9_:-]+)*)(?:\/([a-zA-Z0-9_:-]+))?\}/', $piece, $matches)) {
  1362. $result[] = $piece;
  1363. }
  1364. else {
  1365. if (isset($insert_array[$matches[1]]))
  1366. $value = @$insert_array[$matches[1]];
  1367. else $value = @$default_array[$matches[1]];
  1368. if (strlen(@$matches[2])) {
  1369. foreach (split(".", substr($matches[2], 1)) as $index) {
  1370. if (is_array($value))
  1371. $value = @$value[$index];
  1372. else if (is_object($value)) {
  1373. $value = (array)$value;
  1374. $value = @$value[$index];
  1375. }
  1376. else $value = "";
  1377. }
  1378. }
  1379. switch (gettype($value)) {
  1380. case 'boolean': $value = $value ? "true" : "false"; break;
  1381. case 'integer': $value = (string)$value; break;
  1382. case 'double': $value = (string)$value; break;
  1383. case 'string': break;
  1384. default: $value = ""; break;
  1385. }
  1386. if (strlen(@$matches[3]))
  1387. $flags = array_flip(str_split($matches[3]));
  1388. else $flags = Array();
  1389. if (!isset($flags['v'])) {
  1390. if (isset($flags['w']))
  1391. $value = preg_replace("/[\\x00-\\x09\\x0B-\x0C\x0E-\\x20]+/", " ", $value);
  1392. if (isset($flags['t'])) $value = trim($value);
  1393. if (isset($flags['b'])) $value = basename($value);
  1394. if (isset($flags['e'])) $value = $this->HTMLEncode($value);
  1395. else if (isset($flags['k'])) $value = $this->Wikify($value);
  1396. else if (isset($flags['h'])) $value = htmlspecialchars($value);
  1397. else if (isset($flags['u'])) $value = urlencode($value);
  1398. if (isset($flags['n'])) $value = $this->nl2br($value);
  1399. }
  1400. $result[] = $value;
  1401. }
  1402. $is_an_insert = !$is_an_insert;
  1403. }
  1404. return implode("", $result);
  1405. }
  1406. function Internal_CollectText($array, $start = 0) {
  1407. ob_start();
  1408. for ($start = intval($start), $end = count($array); $start < $end; $start++)
  1409. print $array[$start][BBCODE_STACK_TEXT];
  1410. $output = ob_get_contents();
  1411. ob_end_clean();
  1412. return $output;
  1413. }
  1414. function Internal_CollectTextReverse($array, $start = 0, $end = 0) {
  1415. ob_start();
  1416. for ($start = intval($start); $start >= $end; $start--)
  1417. print $array[$start][BBCODE_STACK_TEXT];
  1418. $output = ob_get_contents();
  1419. ob_end_clean();
  1420. return $output;
  1421. }
  1422. function Internal_GenerateOutput($pos) {
  1423. $output = Array();
  1424. while (count($this->stack) > $pos) {
  1425. $token = array_pop($this->stack);
  1426. if ($token[BBCODE_STACK_TOKEN] != BBCODE_TAG) {
  1427. $output[] = $token;
  1428. }
  1429. else {
  1430. $name = @$token[BBCODE_STACK_TAG]['_name'];
  1431. $rule = @$this->tag_rules[$name];
  1432. $end_tag = @$rule['end_tag'];
  1433. if (!isset($rule['end_tag'])) $end_tag = BBCODE_REQUIRED;
  1434. else $end_tag = $rule['end_tag'];
  1435. array_pop($this->start_tags[$name]);
  1436. if ($end_tag == BBCODE_PROHIBIT) {
  1437. $output[] = Array(
  1438. BBCODE_STACK_TOKEN => BBCODE_TEXT,
  1439. BBCODE_STACK_TAG => false,
  1440. BBCODE_STACK_TEXT => $token[BBCODE_STACK_TEXT],
  1441. BBCODE_STACK_CLASS => $this->current_class,
  1442. );
  1443. }
  1444. else {
  1445. if ($end_tag == BBCODE_REQUIRED)
  1446. @$this->lost_start_tags[$name] += 1;
  1447. $end = $this->Internal_CleanupWSByIteratingPointer(@$rule['before_endtag'], 0, $output);
  1448. $this->Internal_CleanupWSByPoppingStack(@$rule['after_tag'], $output);
  1449. $tag_body = $this->Internal_CollectTextReverse($output, count($output)-1, $end);
  1450. $this->Internal_CleanupWSByPoppingStack(@$rule['before_tag'], $this->stack);
  1451. $this->Internal_UpdateParamsForMissingEndTag(@$token[BBCODE_STACK_TAG]);
  1452. $tag_output = $this->DoTag(BBCODE_OUTPUT, $name,
  1453. @$token[BBCODE_STACK_TAG]['_default'], @$token[BBCODE_STACK_TAG], $tag_body);
  1454. $output = Array(Array(
  1455. BBCODE_STACK_TOKEN => BBCODE_TEXT,
  1456. BBCODE_STACK_TAG => false,
  1457. BBCODE_STACK_TEXT => $tag_output,
  1458. BBCODE_STACK_CLASS => $this->current_class
  1459. ));
  1460. }
  1461. }
  1462. }
  1463. $this->Internal_ComputeCurrentClass();
  1464. return $output;
  1465. }
  1466. function Internal_RewindToClass($class_list) {
  1467. $pos = count($this->stack) - 1;
  1468. while ($pos >= 0 && !in_array($this->stack[$pos][BBCODE_STACK_CLASS], $class_list))
  1469. $pos--;
  1470. if ($pos < 0) {
  1471. if (!in_array($this->root_class, $class_list))
  1472. return false;
  1473. }
  1474. $output = $this->Internal_GenerateOutput($pos+1);
  1475. while (count($output)) {
  1476. $token = array_pop($output);
  1477. $token[BBCODE_STACK_CLASS] = $this->current_class;
  1478. $this->stack[] = $token;
  1479. }
  1480. return true;
  1481. }
  1482. function Internal_FinishTag($tag_name) {
  1483. if (strlen($tag_name) <= 0)
  1484. return false;
  1485. if (isset($this->start_tags[$tag_name])
  1486. && count($this->start_tags[$tag_name]))
  1487. $pos = array_pop($this->start_tags[$tag_name]);
  1488. else $pos = -1;
  1489. if ($pos < 0) return false;
  1490. $newpos = $this->Internal_CleanupWSByIteratingPointer(@$this->tag_rules[$tag_name]['after_tag'],
  1491. $pos+1, $this->stack);
  1492. $delta = $newpos - ($pos+1);
  1493. $output = $this->Internal_GenerateOutput($newpos);
  1494. $newend = $this->Internal_CleanupWSByIteratingPointer(@$this->tag_rules[$tag_name]['before_endtag'],
  1495. 0, $output);
  1496. $output = $this->Internal_CollectTextReverse($output, count($output) - 1, $newend);
  1497. while ($delta-- > 0)
  1498. array_pop($this->stack);
  1499. $this->Internal_ComputeCurrentClass();
  1500. return $output;
  1501. }
  1502. function Internal_ComputeCurrentClass() {
  1503. if (count($this->stack) > 0)
  1504. $this->current_class = $this->stack[count($this->stack)-1][BBCODE_STACK_CLASS];
  1505. else $this->current_class = $this->root_class;
  1506. }
  1507. function Internal_DumpStack($array = false, $raw = false) {
  1508. if (!$raw) $string = "<span style='color: #00C;'>";
  1509. else $string = "";
  1510. if ($array === false)
  1511. $array = $this->stack;
  1512. foreach ($array as $item) {
  1513. switch (@$item[BBCODE_STACK_TOKEN]) {
  1514. case BBCODE_TEXT:
  1515. $string .= "\"" . htmlspecialchars(@$item[BBCODE_STACK_TEXT]) . "\" ";
  1516. break;
  1517. case BBCODE_WS:
  1518. $string .= "WS ";
  1519. break;
  1520. case BBCODE_NL:
  1521. $string .= "NL ";
  1522. break;
  1523. case BBCODE_TAG:
  1524. $string .= "[" . htmlspecialchars(@$item[BBCODE_STACK_TAG]['_name']) . "] ";
  1525. break;
  1526. default:
  1527. $string .= "unknown ";
  1528. break;
  1529. }
  1530. }
  1531. if (!$raw) $string .= "</span>";
  1532. return $string;
  1533. }
  1534. function Internal_CleanupWSByPoppingStack($pattern, &$array) {
  1535. if (strlen($pattern) <= 0) return;
  1536. $oldlen = count($array);
  1537. foreach (str_split($pattern) as $char) {
  1538. switch ($char) {
  1539. case 's':
  1540. while (count($array) > 0 && $array[count($array)-1][BBCODE_STACK_TOKEN] == BBCODE_WS)
  1541. array_pop($array);
  1542. break;
  1543. case 'n':
  1544. if (count($array) > 0 && $array[count($array)-1][BBCODE_STACK_TOKEN] == BBCODE_NL)
  1545. array_pop($array);
  1546. break;
  1547. case 'a':
  1548. while (count($array) > 0
  1549. && (($token = $array[count($array)-1][BBCODE_STACK_TOKEN]) == BBCODE_WS
  1550. || $token == BBCODE_NL))
  1551. array_pop($array);
  1552. break;
  1553. }
  1554. }
  1555. if (count($array) != $oldlen) {
  1556. $this->Internal_ComputeCurrentClass();
  1557. }
  1558. }
  1559. function Internal_CleanupWSByEatingInput($pattern) {
  1560. if (strlen($pattern) <= 0) return;
  1561. foreach (str_split($pattern) as $char) {
  1562. switch ($char) {
  1563. case 's':
  1564. $token_type = $this->lexer->NextToken();
  1565. while ($token_type == BBCODE_WS) {
  1566. $token_type = $this->lexer->NextToken();
  1567. }
  1568. $this->lexer->UngetToken();
  1569. break;
  1570. case 'n':
  1571. $token_type = $this->lexer->NextToken();
  1572. if ($token_type != BBCODE_NL)
  1573. $this->lexer->UngetToken();
  1574. break;
  1575. case 'a':
  1576. $token_type = $this->lexer->NextToken();
  1577. while ($token_type == BBCODE_WS || $token_type == BBCODE_NL) {
  1578. $token_type = $this->lexer->NextToken();
  1579. }
  1580. $this->lexer->UngetToken();
  1581. break;
  1582. }
  1583. }
  1584. }
  1585. function Internal_CleanupWSByIteratingPointer($pattern, $pos, $array) {
  1586. if (strlen($pattern) <= 0) return $pos;
  1587. foreach (str_split($pattern) as $char) {
  1588. switch ($char) {
  1589. case 's':
  1590. while ($pos < count($array) && $array[$pos][BBCODE_STACK_TOKEN] == BBCODE_WS)
  1591. $pos++;
  1592. break;
  1593. case 'n':
  1594. if ($pos < count($array) && $array[$pos][BBCODE_STACK_TOKEN] == BBCODE_NL)
  1595. $pos++;
  1596. break;
  1597. case 'a':
  1598. while ($pos < count($array)
  1599. && (($token = $array[$pos][BBCODE_STACK_TOKEN]) == BBCODE_WS || $token == BBCODE_NL))
  1600. $pos++;
  1601. break;
  1602. }
  1603. }
  1604. return $pos;
  1605. }
  1606. function Internal_LimitText($string, $limit) {
  1607. $chunks…

Large files files are truncated, but you can click here to view the full file