PageRenderTime 55ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/shared/codes.php

https://github.com/altatof/altashop
PHP | 4537 lines | 2349 code | 800 blank | 1388 comment | 419 complexity | f92ed821b33a69f7ff4014c9e52ef3da MD5 | raw file

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

  1. <?php
  2. /**
  3. * Transform some text containing UBB-like code sequences.
  4. *
  5. * @todo CDATA for proxy http://javascript.about.com/library/blxhtml.htm
  6. * @todo &#91;files] - most recent files, in a compact list
  7. * @todo &#91;files=section:&lt;id>] - files attached in the given section
  8. * @todo &#91;links] - most recent links, in a compact list
  9. * @todo &#91;links=section:&lt;id>] - links attached in the given section
  10. * @todo for [read, add hits aside
  11. * @todo add a code to link images with clickable maps
  12. * @todo replace marquee with our own customizable scroller
  13. * @todo WiKi rendering for lists
  14. *
  15. * This module uses the Skin class for the actual rendering.
  16. *
  17. * Basic codes, demonstrated into [link]codes/basic.php[/link]:
  18. * - **...** - wiki bold text
  19. * - &#91;b]...[/b] - bold text
  20. * - //...// - italics
  21. * - &#91;i]...[/i] - italics
  22. * - __...__ - underlined
  23. * - &#91;u]...[/u] - underlined
  24. * - ##...## - monospace
  25. * - &#91;code]...[/code] - a short sample of fixed-size text (e.g. a file name)
  26. * - &#91;color]...[/color] - change font color
  27. * - &#91;tiny]...[/tiny] - tiny size
  28. * - &#91;small]...[/small] - small size
  29. * - &#91;big]...[/big] - big size
  30. * - &#91;huge]...[/huge] - huge size
  31. * - &#91;subscript]...[/subscript] - subscript
  32. * - &#91;superscript]...[/superscript] - superscript
  33. * - ++...++ - inserted
  34. * - &#91;inserted]...[/inserted] - inserted
  35. * - --...-- - deleted
  36. * - &#91;deleted]...[/deleted] - deleted
  37. * - &#91;flag]...[/flag] - draw attention
  38. * - &#91;lang=xy]...[/lang] - show some text only on matching language
  39. * - &#91;style=sans-serif]...[/style] - use a sans-serif font
  40. * - &#91;style=serif]...[/style] - use a serif font
  41. * - &#91;style=cursive]...[/style] - mimic hand writing
  42. * - &#91;style=comic]...[/style] - make it funny
  43. * - &#91;style=fantasy]...[/style] - guess what will appear
  44. * - &#91;style=my_style]...[/style] - translated to &lt;span class="my_style"&gt;...&lt;/span&gt;
  45. *
  46. * @see codes/basic.php
  47. *
  48. * Block codes, demonstrated in [link]codes/blocks.php[/link]:
  49. * - &#91;indent]...[/indent] - shift text to the right
  50. * - &#91;center]...[/center] - some centered text
  51. * - &#91;right]...[/right] - some right-aligned text
  52. * - &#91;decorated]...[/decorated] - some pretty paragraphs
  53. * - &#91;caution]...[/caution] - a warning paragraph
  54. * - &#91;note]...[/note] - a noticeable paragraph
  55. * - &#91;php]...[/php] - a snippet of php
  56. * - &#91;snippet]...[/snippet] - a snippet of fixed font data
  57. * - &#91;quote]...[/quote] - a block of quoted text
  58. * - &#91;folded]...[/folded] - click to view its content, or to fold it away
  59. * - &#91;folded=foo bar]...[/folded] - with title 'foo bar'
  60. * - &#91;unfolded]...[/unfolded] - click to fold
  61. * - &#91;unfolded=foo bar]...[/unfolded] - with title 'foo bar'
  62. * - &#91;sidebar]...[/sidebar] - a nice box aside
  63. * - &#91;sidebar=foo bar]...[/sidebar] - with title 'foo bar'
  64. * - &#91;scroller]...[/scroller] - some scrolling text
  65. *
  66. * @see codes/blocks.php
  67. *
  68. * List codes, demonstrated in [link]codes/lists.php[/link]:
  69. * - &#91;*] - for simple lists
  70. * - &#91;list]...[/list] - bulleted list
  71. * - &#91;list=1]...[/list] - numbered list, use numbers
  72. * - &#91;list=a]...[/list] - numbered list, use letters
  73. * - &#91;list=A]...[/list] - numbered list, use capital letters
  74. * - &#91;list=i]...[/list] - numbered list, use roman numbers
  75. * - &#91;list=I]...[/list] - numbered list, use upper case roman numbers
  76. *
  77. * @see codes/lists.php
  78. *
  79. * Codes for links, demonstrated in [link]codes/links.php[/link]:
  80. * - &lt;url&gt; - &lt;a href="url">url&lt;/a> or &lt;a href="url" class="external">url&lt;/a>
  81. * - &#91;link]&lt;url&gt;[/link] - &lt;a href="url">url&lt;/a> or &lt;a href="url" class="external">url&lt;/a>
  82. * - &#91;&lt;label&gt;|&lt;url&gt;] - &lt;a href="url">label&lt;/a> or &lt;a href="url" class="external">label&lt;/a>
  83. * - &#91;link=&lt;label&gt;]&lt;url&gt;[/link] - &lt;a href="url">label&lt;/a> or &lt;a href="url" class="external">label&lt;/a>
  84. * - &#91;url]&lt;url&gt;[/url] - deprecated by &#91;link]
  85. * - &#91;url=&lt;url&gt;]&lt;label&gt;[/url] - deprecated by &#91;link]
  86. * - &#91;button=&lt;label&gt;|&lt;url&gt;] - build simple buttons with css
  87. * - &#91;click=&lt;label&gt;|&lt;url&gt;] - a button that counts clicks
  88. * - &#91;clicks=&lt;url&gt;] - lists people who have clicked
  89. * - &lt;address&gt; - &lt;a href="mailto:address" class="email">address&lt;/a>
  90. * - &#91;email]&lt;address&gt;[/email] - &lt;a href="mailto:address" class="email">address&lt;/a>
  91. * - &#91;email=&lt;name&gt;]&lt;address&gt;[/email] - &lt;a href="mailto:address" class="email">name&lt;/a>
  92. * - &#91;go=&lt;name&gt;, &lt;label&gt;] - trigger the selector on 'name'
  93. * - &#91;&#91;&lt;name&gt;, &lt;label&gt;]] - Wiki selector
  94. * - &#91;article=&lt;id>] - use article title as link label
  95. * - &#91;article=&lt;id>, foo bar] - with label 'foo bar'
  96. * - &#91;article.description=&lt;id>] - insert article description
  97. * - &#91;form=&lt;id>] - use form title as link label
  98. * - &#91;form=&lt;id>, foo bar] - with label 'foo bar'
  99. * - &#91;next=&lt;id>] - shortcut to next article
  100. * - &#91;next=&lt;id>, foo bar] - with label 'foo bar'
  101. * - &#91;previous=&lt;id>] - shortcut to previous article
  102. * - &#91;previous=&lt;id>, foo bar] - with label 'foo bar'
  103. * - &#91;random] - pick up one page randomly
  104. * - &#91;random=&lt;section:id>] - one page in this section
  105. * - &#91;section=&lt;id>] - use section title as link label
  106. * - &#91;section=&lt;id>, foo bar] - with label 'foo bar'
  107. * - &#91;category=&lt;id>] - use category title as link label
  108. * - &#91;category=&lt;id>, foo bar] - with label 'foo bar'
  109. * - &#91;category.description=&lt;id>] - insert category description
  110. * - &#91;decision=&lt;id>] - use decision id in link label
  111. * - &#91;decision=&lt;id>, foo bar] - with label 'foo bar'
  112. * - &#91;user=&lt;id>] - use nick name as link label
  113. * - &#91;user=&lt;id>, foo bar] - with label 'foo bar'
  114. * - &#91;server=&lt;id>] - use server title as link label
  115. * - &#91;server=&lt;id>, foo bar] - with label 'foo bar'
  116. * - &#91;file=&lt;id>] - use file title as link label
  117. * - &#91;file=&lt;id>, foo bar] - with label 'foo bar'
  118. * - &#91;download=&lt;id>] - a link to download a file
  119. * - &#91;download=&lt;id>, foo bar] - with label 'foo bar'
  120. * - &#91;comment=&lt;id>] - use comment id in link label
  121. * - &#91;comment=&lt;id>, foo bar] - with label 'foo bar'
  122. * - &#91;script]&lt;path/script.php&gt;[/script] - to the phpDoc page for script 'path/script.php'
  123. * - &#91;search] - a search form
  124. * - &#91;search=&lt;word&gt;] - hit Enter to search for 'word'
  125. * - &#91;action=&lt;id>] - use action title as link label
  126. * - &#91;action=&lt;id>, foo bar] - with label 'foo bar'
  127. * - &#91;wikipedia=&lt;keyword] - search Wikipedia
  128. * - &#91;wikipedia=&lt;keyword, foo bar] - search Wikipedia, with label 'foo bar'
  129. *
  130. * @see codes/links.php
  131. *
  132. * Titles and questions, demonstrated in [link]codes/titles.php[/link]:
  133. * - &#91;toc] - table of contents
  134. * - ==...== - a level 1 headline
  135. * - &#91;title]...[/title] - a level 1 headline, put in the table of contents
  136. * - ===...=== - a level 2 headline
  137. * - &#91;subtitle]...[/subtitle] - a level 2 headline
  138. * - &#91;header1]...[/header1] - a level 1 headline
  139. * - &#91;header2]...[/header2] - a level 2 headline
  140. * - &#91;header3]...[/header3] - a level 3 headline
  141. * - &#91;header4]...[/header4] - a level 4 headline
  142. * - &#91;header5]...[/header5] - a level 5 headline
  143. * - &#91;toq] - the table of questions for this page
  144. * - &#91;question]...[/question] - a question-title
  145. * - &#91;question] - a simple question
  146. * - &#91;answer] - some answer in a FAQ
  147. *
  148. * @see codes/titles.php
  149. *
  150. * Tables, demonstrated in [link]codes/tables.php[/link]:
  151. * - &#91;table]...[/table] - one simple table
  152. * - &#91;table=grid]...[/table] - add a grid
  153. * - &#91;table].[body].[/table] - a table with headers
  154. * - &#91;csv]...[/csv] - import some data from Excel
  155. * - &#91;csv=;]...[/csv] - import some data from Excel
  156. * - &#91;table.json] - format a table as json
  157. *
  158. * @see codes/tables.php
  159. *
  160. * Live codes, demonstrated in [link]codes/live.php[/link]:
  161. * - &#91;sections] - site map
  162. * - &#91;sections=section:&lt;id>] - sub-sections
  163. * - &#91;sections=self] - sections assigned to current surfer
  164. * - &#91;sections=user:&lt;id>] - sections assigned to given user
  165. * - &#91;categories] - category tree
  166. * - &#91;categories=category:&lt;id>] - sub-categories
  167. * - &#91;categories=self] - categories assigned to current surfer
  168. * - &#91;categories=user:&lt;id>] - categories assigned to given user
  169. * - &#91;published] - most recent published pages, in a compact list
  170. * - &#91;published=section:&lt;id>] - articles published most recently in the given section
  171. * - &#91;published=category:&lt;id>] - articles published most recently in the given category
  172. * - &#91;published=user:&lt;id>] - articles published most recently created by given user
  173. * - &#91;published.decorated=self, 20] - 20 most recent pages from current surfer, as a decorated list
  174. * - &#91;updated] - most recent updated pages, in a compact list
  175. * - &#91;updated=section:&lt;id>] - articles updated most recently in the given section
  176. * - &#91;updated=category:&lt;id>] - articles updated most recently in the given category
  177. * - &#91;updated=user:&lt;id>] - articles updated most recently created by given user
  178. * - &#91;updated.simple=self, 12] - articles updated most recently created by current surfer, as a simple list
  179. * - &#91;read] - most read articles, in a compact list
  180. * - &#91;read=section:&lt;id>] - articles of fame in the given section
  181. * - &#91;read=self] - personal hits
  182. * - &#91;read=user:&lt;id>] - personal hits
  183. * - &#91;voted] - most voted articles, in a compact list
  184. * - &#91;voted=section:&lt;id>] - articles of fame in the given section
  185. * - &#91;voted=self] - personal hits
  186. * - &#91;voted=user:&lt;id>] - personal hits
  187. * - &#91;collections] - list available collections
  188. * - &#91;users=present] - list of users present on site
  189. *
  190. * @see codes/live.php
  191. *
  192. * Widgets, demonstrated in [link]codes/widgets.php[/link]:
  193. * - &#91;newsfeed=url] - integrate a newsfeed dynamically
  194. * - &#91;newsfeed.embed=url] - integrate a newsfeed dynamically
  195. * - &#91;twitter=id] - twitter updates of one person
  196. * - &#91;tsearch=token] - twitter search on a given topic
  197. * - &#91;iframe=&lt;width&gt;, &lt;height&gt;]&lt;url&gt;[/iframe] - include some external page
  198. * - &#91;freemind] - a Freemind map of site content
  199. * - &#91;freemind=section:&lt;id>] - a Freemind map of a section and its content
  200. * - &#91;freemind=section:&lt;id>, width, height] - a Freemind map of a section and its content
  201. * - &#91;cloud] - the tags used at this site
  202. * - &#91;cloud=12] - maximum count of tags used at this site
  203. * - &#91;calendar] - events for this month
  204. * - &#91;calendar=section:&lt;id>] - dates in one section
  205. * - &#91;locations=all] - newest locations
  206. * - &#91;locations=users] - map user locations on Google maps
  207. * - &#91;location=latitude, longitude, label] - to build a dynamic map
  208. *
  209. * @see codes/widgets.php
  210. *
  211. * Miscellaneous codes, demonstrated in [link]codes/misc.php[/link]:
  212. * - &#91;chart]...[/chart] - draw a dynamic chart
  213. * - &#91;hint=&lt;help popup]...[/hint] - &lt;acronym tite="help popup">...&lt;/acronym>
  214. * - &#91;nl] - new line
  215. * - ----... - line break
  216. * - &#91;---] or &#91;___] - horizontal rule
  217. * - &#91;new] - something new
  218. * - &#91;popular] - people love it
  219. * - &#91;be] - country flag
  220. * - &#91;ca] - country flag
  221. * - &#91;ch] - country flag
  222. * - &#91;de] - country flag
  223. * - &#91;en] - country flag
  224. * - &#91;es] - country flag
  225. * - &#91;fr] - country flag
  226. * - &#91;gb] - country flag
  227. * - &#91;gr] - country flag
  228. * - &#91;it] - country flag
  229. * - &#91;pt] - country flag
  230. * - &#91;us] - country flag
  231. *
  232. * @see codes/misc.php
  233. *
  234. * In-line elements:
  235. * - &#91;embed=&lt;id>, &lt;width>, &lt;height>, &lt;flashparams>] - embed a multimedia file
  236. * - &#91;embed=&lt;id>, window] - render a multimedia file in a separate window
  237. * - &#91;freemind=&lt;id>] - a Freemind map out of given file
  238. * - &#91;sound=&lt;id>] - play a sound
  239. * - &#91;image=&lt;id>] - an inline image
  240. * - &#91;image=&lt;id>,left] - a left-aligned image
  241. * - &#91;image=&lt;id>,center] - a centered image
  242. * - &#91;image=&lt;id>,right] - a right-aligned image
  243. * - &#91;image]src[/image]
  244. * - &#91;image=&lt;alt>]src[/image]
  245. * - &#91;images=&lt;id1>, &lt;id2>, ...] - a stack of images
  246. * - &#91;img]src[/img] (deprecated)
  247. * - &#91;img=&lt;alt>]src[/img] (deprecated)
  248. * - &#91;table=&lt;id>] - an inline table
  249. * - &#91;location=&lt;id>] - embed a map
  250. * - &#91;location=&lt;id>, foo bar] - with label 'foo bar'
  251. * - &#91;clear] - to introduce breaks after floating elements
  252. *
  253. * @link http://www.estvideo.com/dew/index/2005/02/16/370-player-flash-mp3-leger-comme-une-plume the dewplayer page
  254. *
  255. * Other codes:
  256. * - &#91;menu=label]url[/menu] -> one of the main menu command
  257. * - &#91;submenu=label]url[/submenu] -> one of the second-level menu commands
  258. * - &#91;escape]...[/escape]
  259. * - &#91;anonymous]...[/anonymous] -> for non-logged people only
  260. * - &#91;restricted]...[/restricted] -> for logged members only
  261. * - &#91;hidden]...[/hidden] -> for associates only
  262. * - &#91;parameter=name] -> value of one attribute of the global context
  263. *
  264. *
  265. * This script attempts to fight bbCode code injections by filtering strings to be used
  266. * as [code]src[/code] or as [code]href[/code] attributes (Thank you Mordread).
  267. *
  268. * @author Bernard Paques
  269. * @author Mordread Wallas
  270. * @author GnapZ
  271. * @author Alain Lesage (Lasares)
  272. * @tester Viviane Zaniroli
  273. * @tester Agnes
  274. * @tester Pat
  275. * @tester Guillaume Perez
  276. * @tester Fw_crocodile
  277. * @tester Christian Piercot
  278. * @tester Christian Loubechine
  279. * @reference
  280. * @license http://www.gnu.org/copyleft/lesser.txt GNU Lesser General Public License
  281. */
  282. Class Codes {
  283. /**
  284. * beautify some text for final rendering
  285. *
  286. * This function is used to transform some text before sending it back to the browser.
  287. * It actually performs following analysis:
  288. * - implicit formatting
  289. * - formatting codes
  290. * - smileys
  291. *
  292. * If the keyword [escape][formatted][/escape] appears at the first line of text,
  293. * or if options have the keyword ##formatted##, no implicit formatting is performed.
  294. *
  295. * If the keyword [escape][hardcoded][/escape] appears at the first line of text,
  296. * or if options have the keyword ##hardcoded##, the only transformation is is new lines to breaks.
  297. *
  298. * If options feature the keyword ##compact##, then YACS codes that may
  299. * generate big objects are removed, such as [escape][table]...[/table][/escape]
  300. * and [escape][location][/escape].
  301. *
  302. * @param string the text to beautify
  303. * @param string the set of options that apply to this text
  304. * @return the beautified text
  305. *
  306. * @see articles/view.php
  307. */
  308. function &beautify($text, $options='') {
  309. global $context;
  310. // save CPU cycles
  311. $text = trim($text);
  312. if(!$text)
  313. return $text;
  314. //
  315. // looking for compact content
  316. //
  317. if(preg_match('/\bcompact\b/i', $options))
  318. $text = preg_replace(array('/\[table.+?\/table\]/', '/\[location.+?\]/'), '', $text);
  319. //
  320. // implicit formatting
  321. //
  322. // new lines will have to be checked
  323. $new_lines = 'proceed';
  324. // text is already formatted
  325. if(!strncmp($text, '[formatted]', 11)) {
  326. $new_lines = 'none';
  327. $text = substr($text, 11);
  328. // text is already formatted (through options)
  329. } elseif(preg_match('/\bformatted\b/i', $options))
  330. $new_lines = 'none';
  331. // newlines are hard coded
  332. elseif(!strncmp($text, '[hardcoded]', 11)) {
  333. $new_lines = 'hardcoded';
  334. $text = substr($text, 11);
  335. // newlines are hard coded (through options)
  336. } elseif(preg_match('/\bhardcoded\b/i', $options))
  337. $new_lines = 'hardcoded';
  338. // implicit formatting
  339. else
  340. $text =& Codes::beautify_implied($text, 'text');
  341. //
  342. // translate codes
  343. //
  344. // render codes
  345. $text =& Codes::render($text);
  346. // render smileys after codes, else it will break escaped strings
  347. if(is_callable(array('Smileys', 'render_smileys')))
  348. $text =& Smileys::render_smileys($text);
  349. // relocate images
  350. $text = str_replace('"skins/', '"'.$context['path_to_root'].'skins/', $text);
  351. //
  352. // adjust end of lines
  353. //
  354. // newlines are hard coded
  355. if($new_lines == 'hardcoded')
  356. $text = nl2br($text);
  357. // implicit formatting
  358. elseif($new_lines == 'proceed')
  359. $text =& Codes::beautify_implied($text, 'newlines');
  360. return $text;
  361. }
  362. /**
  363. * beautify some text in the extra panel
  364. *
  365. * @param string the text to beautify
  366. * @return the beautified text
  367. *
  368. * @see articles/view.php
  369. */
  370. function &beautify_extra($text) {
  371. global $context;
  372. $search = array();
  373. $replace = array();
  374. // [box.extra=title]...[/box]
  375. $search[] = '/\[box\.(extra)=([^\]]+?)\](.*?)\[\/box\]/ise';
  376. $replace[] = "Skin::build_box(stripslashes('$2'), stripslashes('$3'), '$1')";
  377. // [box.navigation=title]...[/box]
  378. $search[] = '/\[box\.(navigation)=([^\]]+?)\](.*?)\[\/box\]/ise';
  379. $replace[] = "Skin::build_box(stripslashes('$2'), stripslashes('$3'), '$1')";
  380. // process all codes
  381. $text = preg_replace($search, $replace, $text);
  382. // regular rendering
  383. $text =& Codes::beautify($text);
  384. return $text;
  385. }
  386. /**
  387. * render some basic formatting
  388. *
  389. * - suppress multiple newlines
  390. * - render empty lines
  391. * - render simple bulleted lines
  392. * - make URL clickable (http://..., www.foo.bar, foo.bar@foo.com)
  393. *
  394. * Now this function looks for the keyword &#91;escape] in order
  395. * to avoid for formatting pre-formatted areas.
  396. *
  397. * For example, if you type:
  398. * [snippet]
  399. * hello
  400. * world
  401. *
  402. * how are
  403. * you doing?
  404. *
  405. * - my first item
  406. * - my second item
  407. *
  408. * > quoted from
  409. * > a previous message
  410. * [/snippet]
  411. *
  412. * This will be rendered visually in the browser as:
  413. * [snippet]
  414. * hello world
  415. *
  416. * how are you doing?
  417. *
  418. * - my first item
  419. * - my second item
  420. *
  421. * > quoted from
  422. * > a previous message
  423. * [/snippet]
  424. *
  425. * @param string the text to transform
  426. * @param sring either 'text' or 'newlines'
  427. * @return the modified string
  428. */
  429. function &beautify_implied($text, $variant='text') {
  430. // streamline newlines, even if this has been done elsewhere
  431. $text = str_replace(array("\r\n", "\r"), "\n", $text);
  432. // only change end of lines
  433. if($variant == 'newlines') {
  434. // formatting patterns
  435. $search = array(
  436. "|<br\s*/>\n+|i", /* don't insert additional \n after <br /> */
  437. "|\n\n+|i" /* force an html space between paragraphs */
  438. );
  439. $replace = array(
  440. BR,
  441. BR.BR
  442. );
  443. // change everything, except new lines
  444. } else {
  445. // formatting patterns
  446. $search = array(
  447. "|</h1>\n+|i", /* strip \n after title */
  448. "|</h2>\n+|i",
  449. "|</h3>\n+|i",
  450. "|</h4>\n+|i",
  451. '/http:\/\/www\.youtube\.com\/watch\?v=([a-zA-Z0-9]+)/i', // YouTube link
  452. "#^([a-z]+?)://([a-z0-9_\-\.\~\/@&;:=%$\?]+)#ie", /* make URL clickable */
  453. "#([\n\t ])([a-z]+?)://([a-z0-9_\-\.\~\/@&;:=%$\?]+)#ie", /* make URL clickable */
  454. "#([\n\t \(])www\.([a-z0-9\-]+)\.([a-z0-9_\-\.\~]+)((?:/[^,< \r\n\)]*)?)#ie", /* web server */
  455. "/^\<p\>(-|\*)\s+(.+)\<\/p\>$/im", /* lists hard-coded with -, *, ¤, or • -- no space ahead */
  456. "/^(-|\*)\s+(.+)$/m", /* lists hard-coded with -, *, ¤, or • -- no space ahead */
  457. "/\n[ \t]*(From|To|cc|bcc|Subject|Date):(\s*)/i", /* common message headers */
  458. "|\n[ \t]*>(\s*)|i", /* quoted by > */
  459. "|\n[ \t]*\|(\s*)|i", /* quoted by | */
  460. "#([\n\t ])(mailto:|)([a-z0-9_\-\.\~]+?)@([a-z0-9_\-\.\~]+\.[a-z0-9_\-\.\~]+)([\n\t ]*)#ie" /* mail address*/
  461. );
  462. $replace = array(
  463. "</h1>",
  464. "</h2>",
  465. "</h3>",
  466. "</h4>",
  467. '<iframe class="youtube-player" type="text/html" width="445" height="364" src="http://www.youtube.com/embed/$1" frameborder="0"></iframe>', // YouTube link
  468. "Skin::build_link('$1://$2', '$1://$2')",
  469. "'$1'.Skin::build_link('$2://$3', '$2://$3')",
  470. "'$1'.Skin::build_link('http://www.$2.$3$4', 'www.$2.$3$4')",
  471. "<ul><li>$2</li></ul>",
  472. "<ul><li>$2</li></ul>",
  473. BR."$1:$2",
  474. BR.">$1",
  475. BR."|$1",
  476. "'$1'.Skin::build_link('mailto:$3@$4', '$3@$4', 'email').'$5'"
  477. );
  478. }
  479. // preserve escaped areas
  480. $text = str_replace(array('[escape]', '[/escape]', '[list]', '[/list]', '[php]', '[/php]', '[snippet]', '[/snippet]'),
  481. array('<escape>', '</escape>', '<list>', '</list>', '<php>', '</php>', '<snippet>', '</snippet>'), $text);
  482. // locate pre-formatted areas
  483. $areas = preg_split('/<(code|escape|list|php|snippet|pre)>(.*?)<\/\1>/is', trim($text), -1, PREG_SPLIT_DELIM_CAPTURE);
  484. // format only adequate areas
  485. $index = 0;
  486. $formatted = '';
  487. $inside = FALSE;
  488. $target = '';
  489. foreach($areas as $area) {
  490. switch($index%3) {
  491. case 0: // area to be formatted
  492. // do not rewrite tags
  493. $items = preg_split('/<(.+?)>/is', $area, -1, PREG_SPLIT_DELIM_CAPTURE);
  494. $where = 0;
  495. foreach($items as $item) {
  496. switch($where%2) {
  497. case 0: // outside a tag
  498. if($inside)
  499. $target .= $item;
  500. else
  501. $formatted .= preg_replace($search, $replace, $item);
  502. break;
  503. case 1: // inside a tag
  504. // inside or outside a link
  505. if($inside && !strncmp($item, '/a', 2)) {
  506. $formatted .= preg_replace($search, $replace, $target).'<'.$item.'>';
  507. $target = '';
  508. $inside = FALSE;
  509. } elseif($inside)
  510. $target .= '<'.$item.'>';
  511. elseif(!strncmp($item, 'a ', 2)) {
  512. $formatted .= '<'.$item.'>';
  513. $inside = TRUE;
  514. } else
  515. $formatted .= '<'.$item.'>';
  516. break;
  517. }
  518. $where++;
  519. }
  520. break;
  521. case 1: // area boundary
  522. $tag = $area;
  523. break;
  524. case 2: // pre-formatted area - left unmodified
  525. // inside a link, or regular text
  526. if($inside)
  527. $target .= '<'.$tag.'>'.$area.'</'.$tag.'>';
  528. else
  529. $formatted .= '<'.$tag.'>'.$area.'</'.$tag.'>';
  530. break;
  531. }
  532. $index++;
  533. }
  534. // post-optimization
  535. if($variant == 'text')
  536. $formatted = preg_replace('#</ul>\n{0,1}<ul>#', '', $formatted);
  537. $formatted = preg_replace('#\n\n+<ul#', "\n<ul", $formatted);
  538. // restore escaped areas
  539. $formatted = str_replace(array('<escape>', '</escape>', '<list>', '</list>', '<php>', '</php>', '<snippet>', '</snippet>'),
  540. array('[escape]', '[/escape]', '[list]', '[/list]', '[php]', '[/php]', '[snippet]', '[/snippet]'), $formatted);
  541. return $formatted;
  542. }
  543. /**
  544. * format an introduction
  545. *
  546. * @param string raw introduction
  547. * @return string finalized title
  548. */
  549. function &beautify_introduction($text) {
  550. // render codes
  551. $output =& Codes::render($text);
  552. // render smileys after codes, else it will break escaped strings
  553. if(is_callable(array('Smileys', 'render_smileys')))
  554. $output =& Smileys::render_smileys($output);
  555. // return by reference
  556. return $output;
  557. }
  558. /**
  559. * format a title
  560. *
  561. * New lines and images are the only things accepted in titles.
  562. * The goal is to provide a faster service than beautify()
  563. *
  564. * @param string raw title
  565. * @return string finalized title
  566. */
  567. function &beautify_title($text) {
  568. // suppress pairing codes
  569. $output =& Codes::strip($text);
  570. // the only code transformed in titles
  571. $output = str_replace(array('[nl]', '[NL]'), '<br />', $output);
  572. // remove everything, except links, breaks and images, and selected tags
  573. $output = strip_tags($output, '<a><abbr><acronym><b><big><br><code><del><div><dfn><em><i><img><ins><p><q><small><span><strong><sub><sup><tt><u>');
  574. // return by reference
  575. return $output;
  576. }
  577. /**
  578. * determine if a code is already in some text
  579. *
  580. * @param string the text to check
  581. * @param string code to check (e.g., 'embed')
  582. * @param int the id of the object
  583. * @return boolean TRUE if the code is present, false otherwise
  584. */
  585. function check_embedded($text, $code, $id) {
  586. // we check the string of digits
  587. $id = strval($id);
  588. // parse the full string
  589. $count = strlen($text);
  590. $position = 0;
  591. // look for '[embed' or similar
  592. while(($position = strpos($text, '['.$code, $position)) !== FALSE) {
  593. $position += 1+strlen($code);
  594. // parse remaining chars
  595. while($position < $count) {
  596. // digits just follow the '=' sign
  597. if($text[$position] == '=') {
  598. $position++;
  599. // exact match
  600. if(($position + 2 + strlen($id) < $count) && !strcmp(substr($text, $position, strlen($id)), $id))
  601. return TRUE;
  602. // not in this code, look at next one
  603. break;
  604. // malformed code
  605. } elseif($text[$position] == ']') {
  606. $position++;
  607. break;
  608. }
  609. // next char
  610. $position++;
  611. }
  612. }
  613. // not found
  614. return FALSE;
  615. }
  616. /**
  617. * delete a code if it is present in some text
  618. *
  619. * @param string the text to check
  620. * @param string code to check (e.g., 'embed')
  621. * @param int the id of the object
  622. * @return string the resulting string
  623. */
  624. function delete_embedded($text, $code, $id) {
  625. // we check the string of digits
  626. $id = strval($id);
  627. // parse the full string
  628. $count = strlen($text);
  629. $position = 0;
  630. // look for '[embed' or similar
  631. while(($position = strpos($text, '['.$code, $position)) !== FALSE) {
  632. // we have to take everything before that point
  633. $prefix = $position;
  634. // next char
  635. $position += 1+strlen($code);
  636. // parse remaining chars
  637. while($position < $count) {
  638. // digits just follow the '=' sign
  639. if($text[$position] == '=') {
  640. $position++;
  641. // exact match
  642. if(($position + strlen($id) <= $count) && !strcmp(substr($text, $position, strlen($id)), $id)) {
  643. $position += strlen($id);
  644. // look for ']'
  645. while($position < $count) {
  646. if($text[$position] == ']') {
  647. $position++;
  648. break;
  649. }
  650. $position++;
  651. }
  652. // do the deletion
  653. $modified = '';
  654. if($prefix > 0)
  655. $modified .= substr($text, 0, $prefix);
  656. if($position < $count)
  657. $modified .= substr($text, $position, $count-$position);
  658. return $modified;
  659. }
  660. // not in this code, look at next one
  661. break;
  662. // malformed code
  663. } elseif($text[$position] == ']') {
  664. $position++;
  665. break;
  666. }
  667. // next char
  668. $position++;
  669. }
  670. }
  671. // not found
  672. return $text;
  673. }
  674. /**
  675. * fix line breaks introduced by FCKEditor
  676. *
  677. * This function moves unclosed tags to the beginning of content.
  678. *
  679. * @param string input
  680. * @return string original or modified content
  681. */
  682. function &fix_tags($text) {
  683. // look for opening tag at content end
  684. $last_open = strrpos($text, '<p>');
  685. $last_close = strrpos($text, '</p');
  686. if($last_open && (($last_close === FALSE) || ($last_open > $last_close))) {
  687. // trail
  688. $trail = '';
  689. if(strlen($text) > $last_open + 3)
  690. $trail = substr($text, $last_open + 3);
  691. // move it to content start to restore pairing tags
  692. $text = '<p>'.substr($text, 0, $last_open).$trail;
  693. }
  694. // also fix broken img tags, if any
  695. $text = preg_replace('/\<(img[^\<\/]+)\>/i', '<\\1 />', $text);
  696. // remove slashes added by preg_replace -- only for double quotes
  697. $text = str_replace('\"', '"', $text);
  698. // done
  699. return $text;
  700. }
  701. /**
  702. * get the value of one global parameter
  703. *
  704. * @param string name of the parameter
  705. * @param mixed default value, if any
  706. * @return the actual value of this parameter, else the default value, else ''
  707. */
  708. function &get_parameter($name, $default='') {
  709. global $context;
  710. if(isset($context[$name])) {
  711. $output =& $context[$name];
  712. return $output;
  713. }
  714. $output = $default;
  715. return $output;
  716. }
  717. /**
  718. * reset global variables used for rendering
  719. *
  720. * This function should be called between the processing of different articles in a loop
  721. *
  722. * @param string the target URL for this rendering (e.g., 'articles/view.php/123')
  723. */
  724. function initialize($main_target=NULL) {
  725. global $context;
  726. if($main_target)
  727. $context['self_url'] = $context['url_to_root'].$main_target;
  728. }
  729. /**
  730. * list all ids matching some code
  731. *
  732. * @param string the text to check
  733. * @param string code to check (e.g., 'embed')
  734. * @return array the list of matching ids
  735. */
  736. function list_embedded($text, $code='embed') {
  737. // all ids we have found
  738. $ids = array();
  739. // parse the full string
  740. $count = strlen($text);
  741. $position = 0;
  742. // look for '[embed' or similar
  743. while(($position = strpos($text, '['.$code, $position)) !== FALSE) {
  744. $position += 1+strlen($code);
  745. // parse remaining chars
  746. while($position < $count) {
  747. // digits just follow the '=' sign
  748. if($text[$position] == '=') {
  749. $position++;
  750. // capture all digits
  751. $id = '';
  752. while($position < $count) {
  753. if(($text[$position] >= '0') && ($text[$position] <= '9')) {
  754. $id .= $text[$position];
  755. $position++;
  756. } else
  757. break;
  758. }
  759. // save this id
  760. if(strlen($id))
  761. $ids[] = $id;
  762. // look at next code
  763. break;
  764. // malformed code
  765. } elseif($text[$position] == ']') {
  766. $position++;
  767. break;
  768. }
  769. // next char
  770. $position++;
  771. }
  772. }
  773. // job done
  774. return $ids;
  775. }
  776. /**
  777. * transform codes to html
  778. *
  779. * [php]
  780. * // build the page
  781. * $context['text'] .= ...
  782. *
  783. * // transform codes
  784. * $context['text'] = Codes::render($context['text']);
  785. *
  786. * // final rendering
  787. * render_skin();
  788. * [/php]
  789. *
  790. * @param string the input string
  791. * @return string the transformed string
  792. */
  793. function &render($text) {
  794. global $context;
  795. // streamline newlines, even if this has been done elsewhere
  796. $text = str_replace(array("\r\n", "\r"), "\n", $text);
  797. // prevent wysiwyg editors to bracket our own tags
  798. $text = preg_replace('/^<p>(\[.+\])<\/p>$/m', '\\1', $text);
  799. // initialize only once
  800. static $pattern;
  801. if(!isset($pattern)) {
  802. // $pattern[] = ;
  803. // $replace[] = ;
  804. //
  805. // $pattern[] = ;
  806. // $replace[] = ;
  807. //
  808. // $pattern[] = ;
  809. // $replace[] = ;
  810. //
  811. // $pattern[] = ;
  812. // $replace[] = ;
  813. //
  814. // $pattern[] = ;
  815. // $replace[] = ;
  816. $pattern = array(
  817. "|<!-- .* -->|i", // remove HTML comments
  818. '/\[escape\](.*?)\[\/escape\]/ise', // [escape]...[/escape] (before everything)
  819. '/\[php\](.*?)\[\/php\]/ise', // [php]...[/php]
  820. '/\[snippet\](.*?)\[\/snippet\]/ise', // [snippet]...[/snippet]
  821. '/(\[page\].*)$/is', // [page] (provide only the first one)
  822. '/\[hidden\](.*?)\[\/hidden\]/ise', // [hidden]...[/hidden] (save some cycles if at the beginning)
  823. '/\[restricted\](.*?)\[\/restricted\]/ise', // [restricted]...[/restricted] (save some cycles if at the beginning)
  824. '/\[anonymous\](.*?)\[\/anonymous\]/ise', // [anonymous]...[/anonymous] (save some cycles if at the beginning)
  825. '/\[parameter=([^\]]+?)\]/ise', // [parameter=<name>]
  826. '/\[lang=([^\]]+?)\](.*?)\[\/lang\]/ise', // [lang=xy]...[/lang]
  827. '/\[csv=(.)\](.*?)\[\/csv\]/ise', // [csv=;]...[/csv] (before [table])
  828. '/\[csv\](.*?)\[\/csv\]/ise', // [csv]...[/csv] (before [table])
  829. '/\[table=([^\]]+?)\](.*?)\[\/table\]/ise', // [table=variant]...[/table]
  830. '/\[table\](.*?)\[\/table\]/ise', // [table]...[/table]
  831. '/\[images=([^\]]+?)\]/ie', // [images=<ids>] (before other links)
  832. '/\[image\](.*?)\[\/image\]/ise', // [image]src[/image]
  833. '/\[image=([^\]]+?)\](.*?)\[\/image\]/ise', // [image=alt]src[/image]
  834. '/\[img\](.*?)\[\/img\]/ise', // [img]src[/img]
  835. '/\[img=([^\]]+?)\](.*?)\[\/img\]/ise', // [img=alt]src[/img]
  836. '/\[image=([^\]]+?)\]/ie', // [image=<id>]
  837. '/##(\S.*?\S)##/is', // ##...##
  838. '/\[code\](.*?)\[\/code\]/is', // [code]...[/code]
  839. '/\[indent\](.*?)\[\/indent\]/ise', // [indent]...[/indent]
  840. '/\[quote\](.*?)\[\/quote\]/ise', // [quote]...[/quote]
  841. '/\[folded=([^\]]+?)\](.*?)\[\/folded\]\s*/ise', // [folded=...]...[/folded]
  842. '/\[folded\](.*?)\[\/folded\]\s*/ise', // [folded]...[/folded]
  843. '/\[folder=([^\]]+?)\](.*?)\[\/folder\]\s*/ise', // [folder=...]...[/folder]
  844. '/\[folder\](.*?)\[\/folder\]\s*/ise', // [folder]...[/folder]
  845. '/\[unfolded=([^\]]+?)\](.*?)\[\/unfolded\]\s*/ise', // [unfolded=...]...[/unfolded]
  846. '/\[unfolded\](.*?)\[\/unfolded\]\s*/ise', // [unfolded]...[/unfolded]
  847. '/\[sidebar=([^\]]+?)\](.*?)\[\/sidebar\]\s*/ise', // [sidebar=...]...[/sidebar]
  848. '/\[sidebar\](.*?)\[\/sidebar\]\s*/ise', // [sidebar]...[/sidebar]
  849. '/\[note\](.*?)\[\/note\]\s*/ise', // [note]...[/note]
  850. '/\[caution\](.*?)\[\/caution\]\s*/ise', // [caution]...[/caution]
  851. '/\[search=([^\]]+?)\]/ise', // [search=words]
  852. '/\[search\]/ise', // [search]
  853. '/\[cloud=(\d+?)\]/ise', // [cloud=12]
  854. '/\[cloud\]/ise', // [cloud]
  855. '/\[collections\]/ise', // [collections]
  856. '/\[login=([^\]]+?)\]/is', // [login=words] --obsoleted
  857. '/\[login\]/is', // [login] --obsoleted
  858. '/\[center\](.*?)\[\/center\]/ise', // [center]...[/center]
  859. '/\[right\](.*?)\[\/right\]/ise', // [right]...[/right]
  860. '/\[decorated\](.*?)\[\/decorated\]/ise',// [decorated]...[/decorated]
  861. '/\[style=([^\]]+?)\](.*?)\[\/style\]/ise', // [style=variant]...[/style]
  862. '/\[hint=([^\]]+?)\](.*?)\[\/hint\]/is', // [hint=help]...[/hint]
  863. '/\[tiny\](.*?)\[\/tiny\]/ise', // [tiny]...[/tiny]
  864. '/\[small\](.*?)\[\/small\]/ise', // [small]...[/small]
  865. '/\[big\](.*?)\[\/big\]/ise', // [big]...[/big]
  866. '/\[huge\](.*?)\[\/huge\]/ise', // [huge]...[/huge]
  867. '/\[subscript\](.*?)\[\/subscript\]/is',// [subscript]...[/subscript]
  868. '/\[superscript\](.*?)\[\/superscript\]/is',// [superscript]...[/superscript]
  869. '/\+\+(\S.*?\S)\+\+/is', // ++...++
  870. '/\[(---+|___+)\]\s*/ise', // [---], [___] --- before inserted
  871. '/^-----*/me', // ----
  872. '/\[inserted\](.*?)\[\/inserted\]/is', // [inserted]...[/inserted]
  873. '/ --(\S.*?\S)--/is', // --...--
  874. '/\[deleted\](.*?)\[\/deleted\]/is', // [deleted]...[/deleted]
  875. '/\*\*(\S.*?\S)\*\*/is', // **...**
  876. '/\[b\](.*?)\[\/b\]/is', // [b]...[/b]
  877. '/ \/\/(\S.*?\w)\/\//is', // //...//
  878. '/\[i\](.*?)\[\/i\]/is', // [i]...[/i]
  879. '/__(\S.*?\S)__/is', // __...__
  880. '/\[u\](.*?)\[\/u\]/is', // [u]...[/u]
  881. '/\[color=([^\]]+?)\](.*?)\[\/color\]/is', // [color=<color>]...[/color]
  882. '/\[new\]/ie', // [new]
  883. '/\[popular\]/ie', // [popular]
  884. '/\[flag=([^\]]+?)\]/ie', // [flag=<flag>]
  885. '/\[flag\](.*?)\[\/flag\]/ise', // [flag]...[/flag]
  886. '/\[list\](.*?)\[\/list\]/ise', // [list]...[/list]
  887. '/\[list=([^\]]+?)\](.*?)\[\/list\]/ise', // [list=1]...[/list]
  888. '/\n\n+[ \t]*\[\*\][ \t]*/ie', // [*] (outside [list]...[/list])
  889. '/\n?[ \t]*\[\*\][ \t]*/ie',
  890. '/\[li\](.*?)\[\/li\]/is', // [li]...[/li] (outside [list]...[/list])
  891. '/\[chart=([^\]]+?)\](.*?)\[\/chart\]/ise', // [chart=<width>, <height>, <params>]...[/chart]
  892. '/\[embed=([^\]]+?)\]/ie', // [embed=<id>, <width>, <height>, <params>] or [embed=<id>, window]
  893. '/\[flash=([^\]]+?)\]/ie', // [flash=<id>, <width>, <height>, <params>] or [flash=<id>, window]
  894. '/\[sound=([^\]]+?)\]/ie', // [sound=<id>]
  895. '/\[go=([^\]]+?)\]/ie', // [go=<name>]
  896. '/\[\[([^\]]+?)\]\]/ie', // [[<name>]]
  897. '/\[article\.description=([^\]]+?)\]/ie', // [article.description=<id>]
  898. '/\[article=([^\]]+?)\]/ie', // [article=<id>] or [article=<id>, title]
  899. '/\[next=([^\]]+?)\]/ie', // [next=<id>]
  900. '/\[previous=([^\]]+?)\]/ie', // [previous=<id>]
  901. '/\[random\]/ie', // [random]
  902. '/\[random\.description=([^\]]+?)\]/ie', // [random.description=section:<id>]
  903. '/\[random=([^\]]+?)\]/ie', // [random=section:<id>] or [random=category:<id>]
  904. '/\[form=([^\]]+?)\]/ie', // [form=<id>] or [form=<id>, title]
  905. '/\[section=([^\]]+?)\]/ie', // [section=<id>] or [section=<id>, title]
  906. '/\[category\.description=([^\]]+?)\]\n*/ise', // [category.description=<id>]
  907. '/\[category=([^\]]+?)\]/ie', // [category=<id>] or [category=<id>, title]
  908. '/\[user=([^\]]+?)\]/ie', // [user=<id>] or [user=<id>, title]
  909. '/\[server=([^\]]+?)\]/ie', // [server=<id>]
  910. '/\[file=([^\]]+?)\]/ie', // [file=<id>] or [file=<id>, title]
  911. '/\[download=([^\]]+?)\]/ie', // [download=<id>] or [download=<id>, title]
  912. '/\[action=([^\]]+?)\]/ie', // [action=<id>]
  913. '/\[comment=([^\]]+?)\]/ie', // [comment=<id>] or [comment=<id>, title]
  914. '/\[decision=([^\]]+?)\]/ie', // [decision=<id>] or [decision=<id>, title]
  915. '/\[url=([^\]]+?)\](.*?)\[\/url\]/ise', // [url=url]label[/url] (deprecated by [link])
  916. '/\[url\](.*?)\[\/url\]/ise', // [url]url[/url] (deprecated by [link])
  917. '/\[link=([^\]]+?)\](.*?)\[\/link\]/ise', // [link=label]url[/link]
  918. '/\[link\](.*?)\[\/link\]/ise', // [link]url[/link]
  919. '/\[button=([^\]]+?)\](.*?)\[\/button\]/ise', // [button=label]url[/button]
  920. '/\[button=([^\|]+?)\|([^\]]+?)]/ise', // [button=label|url]
  921. '/\[click=([^\|]+?)\|([^\]]+?)]/ise', // [click=label|url]
  922. '/\[clicks=([^\]]+?)]/ise', // [clicks=url]
  923. '/\[script\](.*?)\[\/script\]/ise', // [script]url[/script]
  924. '/\[menu\](.*?)\[\/menu\]\n*/ise', // [menu]url[/menu]
  925. '/\[menu=([^\]]+?)\](.*?)\[\/menu\]\n{0,1}/ise', // [menu=label]url[/menu]
  926. '/\[submenu\](.*?)\[\/submenu\]\n{0,1}/ise', // [submenu]url[/submenu]
  927. '/\[submenu=([^\]]+?)\](.*?)\[\/submenu\]\n*/ise', // [submenu=label]url[/submenu]
  928. '/\[email=([^\]]+?)\](.*?)\[\/email\]/ise', // [email=label]url[/email]
  929. '/\[email\](.*?)\[\/email\]/ise', // [email]url[/email]
  930. '/\[([^ ][^\]\|]+?[^ ])\|([^ ][^\]]+?[^ ])\]/ise', // [label|url]
  931. '/\[question\](.*?)\[\/question\]\n*/ise', // [question]...[/question]
  932. '/\[question\]/ise', // [question]
  933. '/\[answer\]/ise', // [answer]
  934. '/\[newsfeed=([^\]]+?)\]/ise', // [newsfeed=url]
  935. '/\[newsfeed\.([^=\]]+?)=([^\]]+?)\]/ise', // [newsfeed.variant=url]
  936. '/\[twitter=([^\]]+?)\]/ise', // [twitter=id]
  937. '/\[tsearch=([^\]]+?)\]/ise', // [tsearch=id]
  938. '/\[retweet\]/ise', // [retweet]
  939. '/\[iframe\](.*?)\[\/iframe\]/ise', // [iframe]<url>[/iframe]
  940. '/\[iframe=([^\]]+?)\](.*?)\[\/iframe\]/ise', // [iframe=<width>, <height>]<url>[/iframe]
  941. '/\[scroller\](.*?)\[\/scroller\]/ise', // [scroller]...[/scroller]
  942. '/\[toq\]\n*/ise', // [toq] (table of questions)
  943. '/\[title\](.*?)\[\/title\]\n*/is', // [title]...[/title]
  944. '/\[subtitle\](.*?)\[\/subtitle\]\n*/is', // [subtitle]...[/subtitle]
  945. '/\[(header[1-5])\](.*?)\[\/\1\]\n*/ise', // [header1]...[/header1] ... [header5]...[/header5]
  946. '/^======(\S.*?\S)======/me', // ======...====== level 5 headline
  947. '/<(br \/|p)>======(\S.*?\S)======<(br \/|\/p)>/me', // ======...====== level 5 headline
  948. '/^=====(\S.*?\S)=====/me', // =====...===== level 4 headline
  949. '/<(br \/|p)>=====(\S.*?\S)=====<(br \/|\/p)>/me', // =====...===== level 4 headline
  950. '/^====(\S.*?\S)====/me', // ====...==== level 3 headline
  951. '/<(br \/|p)>====(\S.*?\S)====<(br \/|\/p)>/me', // ====...==== level 3 headline
  952. '/^===(\S.*?\S)===/me', // ===...=== level 2 headline
  953. '/<(br \/|p)>===(\S.*?\S)===<(br \/|\/p)>/me', // ===...=== level 2 headline
  954. '/^==(\S.*?\S)==/me', // ==...== level 1 headline
  955. '/<(br \/|p)>==(\S.*?\S)==<(br \/|\/p)>/me', // ==...== level 1 headline
  956. '/\[toc\]\n*/ise', // [toc] (table of content)
  957. '/\[published\.([^\]=]+?)=([^\]]+?)\]\n*/ise', // [published.decorated=section:4029]
  958. '/\[published\.([^\]]+?)\]\n*/ise', // [published.decorated]
  959. '/\[published=([^\]]+?)\]\n*/ise', // [published=section:4029]
  960. '/\[published\]\n*/ise', // [published]
  961. '/\[read\.([^\]=]+?)=([^\]]+?)\]\n*/ise', // [read.decorated=section:4029]
  962. '/\[read\.([^\]]+?)\]\n*/ise', // [read.decorated]
  963. '/\[read=([^\]]+?)\]\n*/ise', // [read=section:4029]
  964. '/\[read\]\n*/ise', // [read]
  965. '/\[updated\.([^\]=]+?)=([^\]]+?)\]\n*/ise', // [updated.simple=section:4029] (a list of recent updates)
  966. '/\[updated\.([^\]]+?)\]\n*/ise', // [updated.simple] (a list of recent updates)
  967. '/\[updated=([^\]]+?)\]\n*/ise', // [updated=section:4029] (a compact list of recent updates)
  968. '/\[updated\]\n*/ise', // [updated] (a compact list of recent updates)
  969. '/\[voted\.([^\]=]+?)=([^\]]+?)\]\n*/ise', // [voted.decorated=section:4029]
  970. '/\[voted\.([^\]]+?)\]\n*/ise', // [voted.decorated]
  971. '/\[voted=([^\]]+?)\]\n*/ise', // [voted=section:4029]
  972. '/\[voted\]\n*/ise', // [voted]
  973. '/\[freemind\]\n*/ise', // [freemind] (a mind map of site content)
  974. '/\[freemind=([^\]]+?)\]\n*/ise', // [freemind=section:4029] (a mind map of section content)
  975. '/\[sections\]\n*/ise', // [sections] (site map)
  976. '/\[sections\.([^\]=]+?)\]\n*/ise', // [sections.folded] (site map)
  977. '/\[sections=([^\]]+?)\]\n*/ise', // [sections=section:4029] (sub-sections)
  978. '/\[sections\.([^\]=]+?)=([^\]]+?)\]\n*/ise', // [sections.simple=self] (assigned)
  979. '/\[categories\]\n*/ise', // [categories] (category tree)
  980. '/\[categories\.([^\]=]+?)\]\n*/ise', // [categories.folded] (category tree)
  981. '/\[categories=([^\]]+?)\]\n*/ise', // [categories=section:4029] (sub-categories)
  982. '/\[categories\.([^\]=]+?)=([^\]]+?)\]\n*/ise', // [categories.simple=self] (assigned)
  983. '/\[calendar\]\n*/ise', // [calendar]
  984. '/\[calendar=([^\]]+?)\]\n*/ise', // [calendar=section:4029]
  985. '/\[users=([^\]]+?)\]/ie', // [users=present]
  986. '/\[news=([^\]]+?)\]/ise', // [news=flash]
  987. '/\[table=([^\]]+?)\]/ise', // [table=<id>]
  988. '/\[table\.([^=\]]+?)=([^\]]+?)\]/ise', // [table.json=<id>] [table.timeplot=<id>]
  989. '/\[locations=([^\]]+?)\]/ise', // [locations=<id>]
  990. '/\[location=([^\]]+?)\]/ise', // [location=<id>]
  991. '/\[wikipedia=([^\]]+?)\]/ise', // [wikipedia=keyword] or [wikipedia=keyword, title]
  992. '/\[digraph\](.*?)\[\/digraph\]/ise', // [digraph]url[/digraph]
  993. '/\[be\]/i', // [be] belgian flag
  994. '/\[ca\]/i', // [ca] canadian flag
  995. '/\[ch\]/i', // [ch] swiss flag
  996. '/\[de\]/i', // [de] german flag
  997. '/\[en\]/i', // [en] english flag
  998. '/\[es\]/i', // [es] spanish flag
  999. '/\[fr\]/i', // [fr] french flag
  1000. '/\[gb\]/i', // [gb] gb flag
  1001. '/\[gr\]/i', // [gr] greek flag
  1002. '/\[it\]/i', // [it] italian flag
  1003. '/\[pt\]/i', // [pt] portuguese flag
  1004. '/\[us\]/i', // [pt] us flag
  1005. '/\[clear\]\n*/i', // [clear]
  1006. '/\[nl\]\n*/si', // [nl] (after tables)
  1007. '/\[br\]/i' // [br] (deprecated by [nl])
  1008. );
  1009. }
  1010. // initialize only once
  1011. static $replace;
  1012. if(!isset($replace)) {
  1013. $replace = array(
  1014. '', // delete HTML comments
  1015. "Codes::render_escaped(Codes::fix_tags('$1'))", // [escape]...[/escape]
  1016. "Codes::render_pre(Codes::fix_tags('$1'), 'php')", // [php]...[/php]
  1017. "Codes::render_pre(Codes::fix_tags('$1'), 'snippet')", // [snippet]...[/snippet]
  1018. '', // [page]
  1019. "Codes::render_hidden(Codes::fix_tags('$1'), 'hidden')", // [hidden]...[/hidden]
  1020. "Codes::render_hidden(Codes::fix_tags('$1'), 'restricted')", // [restricted]...[/restricted]
  1021. "Codes::render_hidden(Codes::fix_tags('$1'), 'anonymous')", // [anonymous]...[/anonymous]
  1022. "Codes::get_parameter('\\1')", // [parameter=<name>]
  1023. "i18n::filter(Codes::fix_tags('$2'), '$1')", // [lang=xy]...[/lang]
  1024. "utf8::encode(str_replace('$1', '|', utf8::from_unicode(Codes::fix_tags('$2'))))", // [csv=;]...[/csv]
  1025. "str_replace(',', '|', Codes::fix_tags('$1'))", // [csv]...[/csv]
  1026. "Codes::render_static_table(Codes::fix_tags('$2'), '$1')", // [table=variant]...[/table]
  1027. "Codes::render_static_table(Codes::fix_tags('$1'), '')", // [table]...[/table]
  1028. "Codes::render_object('images', '$1')", // [images=<ids>]
  1029. "'<div class=\"external_image\"><img src=\"'.encode_link('$1').'\" alt=\"\" /></div>'", // [image]src[/image]
  1030. "'<div class=\"external_image\"><img src=\"'.encode_link('$2').'\" alt=\"'.encode_link('$1').'\" /></div>'", // [image=alt]src[/image]
  1031. "'<div class=\"external_image\"><img src=\"'.encode_link('$1').'\" alt=\"\" /></div>'", // [img]src[/img]
  1032. "'<div class=\"external_image\"><img src=\"'.encode_link('$2').'\" alt=\"'.encode_link('$1').'\" /></div>'", // [img=alt]src[/img]
  1033. "Codes::render_object('image', Codes::fix_tags('$1'))", // [image=<id>]
  1034. '<code>\\1</code>', // ##...##
  1035. '<code>\\1</code>', // [code]...[/code]
  1036. "Skin::build_block(Codes::fix_tags('$1'), 'indent')", // [indent]...[indent]
  1037. "Skin::build_block(Codes::fix_tags('$1'), 'quote')", // [quote]...[/quote]
  1038. "Skin::build_box('$1', Codes::fix_tags('$2'), 'folded')", // [folded=title]...[/folded]
  1039. "Skin::build_box(NULL, Codes::fix_tags('$1'), 'folded')", // [folded]...[/folded]
  1040. "Skin::build_box('$1', Codes::fix_tags('$2'), 'folded')", // [folder=title]...[/folder]
  1041. "Skin::build_box(NULL, Codes::fix_tags('$1'), 'folded')", // [folder]...[/folder]
  1042. "Skin::build_box('$1', Codes::fix_tags('$2'), 'unfolded')", // [unfolded=title]...[/unfolded]
  1043. "Skin::build_box(NULL, Codes::fix_tags('$1'), 'unfolded')", // [unfolded]...[/unfolded]
  1044. "Skin::build_box('$1', Codes::fix_tags('$2'), 'sidebar')", // [sidebar=title]...[/sidebar]
  1045. "Skin::build_box(NULL, Codes::fix_tags('$1'), 'sidebar')", // [sidebar]...[/sidebar]
  1046. "Skin::build_block(Codes::fix_tags('$1'), 'note')", // [note]...[/note]
  1047. "Skin::build_block(Codes::fix_tags('$1'), 'caution')", // [caution]...[/caution]
  1048. "Skin::build_block('$1', 'search')", // [search=<words>]
  1049. "Skin::build_block(NULL, 'search')", // [search]
  1050. "Codes::render_cloud('$1')", // [cloud=12]
  1051. "Codes::render_cloud(20)", // [cloud]
  1052. "Codes::render_collections()", // [collections]
  1053. '', // [login=<words>] --obsoleted
  1054. '', // [login] --obsoleted
  1055. "Skin::build_block(Codes::fix_tags('$1'), 'center')", // [center]...[/center]
  1056. "Skin::build_block(Codes::fix_tags('$1'), 'right')", // [right]...[/right]
  1057. "Skin::build_block(Codes::fix_tags('$1'), 'decorated')", // [decorated]...[/decorated]
  1058. "Skin::build_block(Codes::fix_tags('$2'), '$1')", // [style=variant]...[/style]
  1059. '<acronym title="\\1">\\2</acronym>', // [hint=help]...[/hint]
  1060. "Skin::build_block(Codes::fix_tags('$1'), 'tiny')", // [tiny]...[/tiny]
  1061. "Skin::build_block(Codes::fix_tags('$1'), 'small')", // [small]...[/small]
  1062. "Skin::build_block(Codes::fix_tags('$1'), 'big')", // [big]...[/big]
  1063. "Skin::build_block(Codes::fix_tags('$1'), 'huge')", // [huge]...[/huge]
  1064. '<sub>\\1</sub>', // [subscript]...[/subscript]
  1065. '<sup>\\1</sup>', // [superscript]...[/superscript]
  1066. '<ins>\\1</ins>', // ++...++
  1067. "HORIZONTAL_RULER", // [---], [___]
  1068. "HORIZONTAL_RULER", // ----
  1069. '<ins>\\1</ins>', // [inserted]...[/inserted]
  1070. ' <del>\\1</del>', // --...--
  1071. '<del>\\1</del>', // [deleted]...[/deleted]
  1072. '<b>\\1</b>', // **...**
  1073. '<b>\\1</b>', // [b]...[/b]
  1074. ' <i>\\1</i>', // //...//
  1075. '<i>\\1</i>', // [i]...[/i]
  1076. '<span style="text-decoration: underline">\\1</span>', // __...__
  1077. '<span style="text-decoration: underline">\\1</span>', // [u]...[/u]
  1078. '<span style="color: \\1">\\2</span>', // [color]...[/color]
  1079. "NEW_FLAG", // [new]
  1080. "POPULAR_FLAG", // [popular]
  1081. "Skin::build_flag('\\1')", // [flag=....]
  1082. "Skin::build_flag('\\1')", // [flag]...[/flag]
  1083. "Codes::render_list(Codes::fix_tags('$1'), NULL)", // [list]...[/list]
  1084. "Codes::render_list(Codes::fix_tags('$2'), '$1')", // [list=?]...[/list]
  1085. "BR.BR.BULLET_IMG.'&nbsp;'", // standalone [*]
  1086. "BR.BULLET_IMG.'&nbsp;'",
  1087. '<li>\\1</li>', // [li]...[/li]
  1088. "Codes::render_chart(Codes::fix_tags('$2'), '$1')", // [chart=<width>, <height>, <params>]...[/chart]
  1089. "Codes::render_embed(Codes::fix_tags('$1'))", // [embed=<id>, <width>, <height>, <params>]
  1090. "Codes::render_embed(Codes::fix_tags('$1'))", // [flash=<id>, <width>, <height>, <params>] -- obsoleted by 'embed'
  1091. "Codes::render_object('sound', Codes::fix_tags('$1'))", // [sound=<id>]
  1092. "Codes::render_object('go', Codes::fix_tags('$1'))", // [go=<name>]
  1093. "Codes::render_object('go', Codes::fix_tags('$1'))", // [[<name>]]
  1094. "Codes::render_object('article.description', Codes::fix_tags('$1'))",// [article.description=<id>]
  1095. "Codes::render_object('article', Codes::fix_tags('$1'))", // [article=<id>]
  1096. "Codes::render_object('next', Codes::fix_tags('$1'))", // [next=<id>]
  1097. "Codes::render_object('previous', Codes::fix_tags('$1'))", // [previous=<id>]
  1098. "Codes::render_random()", // [random]
  1099. "Codes::render_random('$1', 'description')", // [random.description=section:<id>]
  1100. "Codes::render_random('$1')", // [random=section:<id>]
  1101. "Codes::render_object('form', Codes::fix_tags('$1'))", // [form=<id>]
  1102. "Codes::render_object('section', Codes::fix_tags('$1'))", // [section=<id>]
  1103. "Codes::render_object('category.description', '$1')", // [category.description=<id>]
  1104. "Codes::render_object('category', Codes::fix_tags('$1'))", // [category=<id>]
  1105. "Codes::render_object('user', Codes::fix_tags('$1'))", // [user=<id>]
  1106. "Codes::render_object('server', Codes::fix_tags('$1'))", // [server=<id>]
  1107. "Codes::render_object('file', Codes::fix_tags('$1'))", // [file=<id>] or [file=<id>, title]
  1108. "Codes::render_object('download', Codes::fix_tags('$1'))", // [download=<id>] or [download=<id>, title]
  1109. "Codes::render_object('action', Codes::fix_tags('$1'))", // [action=<id>]
  1110. "Codes::render_object('comment',…

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