1: <?php
2: /**
3: * The Horde_Text_Filter_Bbcode:: class finds bbcode-style markup (see below)
4: * in a block of text and turns it into HTML.
5: *
6: * Parameters:
7: * <pre>
8: * entities - (boolean) Before replacing bbcode with HTML tags, replace HTML
9: * entities?
10: * DEFAULT: false
11: * </pre>
12: *
13: * Supported bbcode:
14: * <pre>
15: * [b]Bold Text[/b]
16: * [i]Italics Text[/i]
17: * [u]Underlined Text[/u]
18: * [quote]Quoted Text[/quote]
19: * [center]Centered Text[/center]
20: *
21: * List of items
22: * [list]
23: * [*] Item one
24: * [*] Item two
25: * [/list]
26: *
27: * Numbered list
28: * [numlist]
29: * [*] Item one
30: * [*] Item two
31: * [/numlist]
32: *
33: * [url]http://www.horde.org[/url] -> Link to the address using the
34: * address itself for the text. You can specify the protocol: http or
35: * https and the port.
36: * [url]www.horde.org[/url] -> Link to the address using the address
37: * itself for the text. You can specify the port. The protocol is by
38: * default http.
39: * [url=http://www.horde.org]Link to Horde[/url] -> Link to the address
40: * using "Link to Horde" for the text. You can specify the protocol:
41: * http or https and the port.
42: * [url=www.horde.org]Link to Horde[/url] -> Link to the address using
43: * "Link to Horde" for the text. You can specify the port. The
44: * protocol is by default http
45: * [email]cpedrinaci@yahoo.es[/email] -> sets a mailto link.
46: * [email=cpedrinaci@yahoo.es]Mail to Carlos[/email] -> Sets a mailto link
47: * and the text is "Mail to Carlos".
48: * </pre>
49: *
50: * Copyright 2003-2012 Horde LLC (http://www.horde.org/)
51: *
52: * Email validation based on Chuck Hagenbuch's
53: * Mail_RFC822::isValidInetAddress().
54: *
55: * See the enclosed file COPYING for license information (LGPL). If you
56: * did not receive this file, see http://www.horde.org/licenses/lgpl21.
57: *
58: * @author Carlos Pedrinaci <cpedrinaci@yahoo.es>
59: * @category Horde
60: * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
61: * @package Text_Filter
62: */
63: class Horde_Text_Filter_Bbcode extends Horde_Text_Filter_Base
64: {
65: /**
66: * Filter parameters.
67: *
68: * @var array
69: */
70: protected $_params = array(
71: 'entities' => false
72: );
73:
74: /**
75: * Executes any code necessary before applying the filter patterns.
76: *
77: * @param string $text The text before the filtering.
78: *
79: * @return string The modified text.
80: */
81: public function preProcess($text)
82: {
83: if ($this->_params['entities']) {
84: $text = @htmlspecialchars($text);
85: }
86:
87: return $text;
88: }
89:
90: /**
91: * Returns a hash with replace patterns.
92: *
93: * @return array Patterns hash.
94: */
95: public function getPatterns()
96: {
97: $replace = array(
98: '[i]' => '<em>', '[/i]' => '</em>',
99: '[u]' => '<u>', '[/u]' => '</u>',
100: '[b]' => '<strong>', '[/b]' => '</strong>',
101: '[s]' => '<strike>', '[/s]' => '</strike>',
102: '[sub]' => '<sub>', '[/sub]' => '</sub>',
103: '[sup]' => '<sup>', '[/sup]' => '</sup>',
104: '[center]' => '<center>', '[/center]' => '</center>',
105: '[quote]' => '<blockquote>', '[/quote]' => '</blockquote>',
106: '[list]' => '<ul>', '[/list]' => '</ul>',
107: '[numlist]' => '<ol>', '[/numlist]' => '</ol>',
108: '[*]' => '<li>'
109: );
110:
111: /* When checking URLs we validate part of them, but it is up
112: * to the user to write them correctly (in particular the
113: * query string). Concerning mails we use the regular
114: * expression in Mail_RFC822's isValidInetAddress() function,
115: * slightly modified. */
116: $regexp = array(
117: "#\[url\]((http|https)://([a-zA-Z\d][\w-]*)(\.[a-zA-Z\d][\w-]*)+(:(\d+))?(/([^<>]+))*)\[/url\]#U" => $this->_link("$1", "$1") . "$1</a>",
118:
119: "#\[url\=((http|https)://([a-zA-Z\d][\w-]*)(\.[a-zA-Z\d][\w-]*)+(:(\d+))?(/([^<>]+))*)\]([^<>]+)\[/url\]#U" => $this->_link("$1", "$1") . "$9</a>",
120:
121: "#\[url\](([a-zA-Z\d][\w-]*)(\.[a-zA-Z\d][\w-]*)+(:(\d+))?(/([^<>]+))*)\[/url\]#U" => $this->_link("http://$1", "http://$1") . "$1</a>",
122:
123: "#\[url\=(([a-zA-Z\d][\w-]*)(\.[a-zA-Z\d][\w-]*)+(:(\d+))?(/([^<>]+))*)\]([^<>]+)\[/url\]#U" => $this->_link("http://$1", "http://$1") . "$8</a>",
124:
125: "#\[email\](([*+!.&\#$|\'\\%\/0-9a-zA-Z^_`{}=?~:-]+)@(([0-9a-zA-Z-]+\.)+[0-9a-zA-Z]{2,4}))\[/email\]#U" => $this->_link("mailto:$1", "mailto:$1") . "$1</a>",
126:
127: "#\[email\=(([*+!.&\#$|\'\\%\/0-9a-zA-Z^_`{}=?~:-]+)@(([0-9a-zA-Z-]+\.)+[0-9a-zA-Z]{2,4}))\]([^<>]+)\[/email\]#U" => $this->_link("mailto:$1", "mailto:$1") . "$5</a>",
128:
129: "#\[img\](.*)\[/img\]#U" => "<img src=\"$1\" alt=\"$1\" />",
130:
131: "#\[img\=(.*)\](.*)\[/img\]#U" => "<img src=\"$1\" alt=\"$2\" title=\"$2\" />",
132:
133: "#\[color\=(.*)\](.*)\[/color\]#U" => "<span style=\"color: $1;\">$2</span>"
134: );
135:
136: return array(
137: 'regexp' => $regexp,
138: 'replace' => $replace
139: );
140: }
141:
142: /**
143: * Return link for use in getPatterns() regexp.
144: *
145: * @var string $url The URL.
146: * @var string $title The link title.
147: *
148: * @return string The opening <a> tag.
149: */
150: protected function _link($url, $title)
151: {
152: return '<a href="' . $url . '" title="' . $title . '">';
153: }
154:
155: }
156: