Derek Jones | 8ede1a2 | 2011-10-05 13:34:52 -0500 | [diff] [blame] | 1 | ############### |
| 2 | Trackback Class |
| 3 | ############### |
| 4 | |
| 5 | The Trackback Class provides functions that enable you to send and |
| 6 | receive Trackback data. |
| 7 | |
| 8 | If you are not familiar with Trackbacks you'll find more information |
| 9 | `here <http://en.wikipedia.org/wiki/Trackback>`_. |
| 10 | |
Connor Tumbleson | 75b3fb2 | 2014-01-11 06:58:43 -0600 | [diff] [blame] | 11 | .. contents:: |
Andrey Andreev | cc04209 | 2014-01-03 17:08:27 +0200 | [diff] [blame] | 12 | :local: |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 13 | |
| 14 | .. raw:: html |
| 15 | |
Andrey Andreev | cc04209 | 2014-01-03 17:08:27 +0200 | [diff] [blame] | 16 | <div class="custom-index container"></div> |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 17 | |
| 18 | ************************* |
| 19 | Using the Trackback Class |
| 20 | ************************* |
| 21 | |
Derek Jones | 8ede1a2 | 2011-10-05 13:34:52 -0500 | [diff] [blame] | 22 | Initializing the Class |
| 23 | ====================== |
| 24 | |
| 25 | Like most other classes in CodeIgniter, the Trackback class is |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 26 | initialized in your controller using the ``$this->load->library()`` method:: |
Derek Jones | 8ede1a2 | 2011-10-05 13:34:52 -0500 | [diff] [blame] | 27 | |
| 28 | $this->load->library('trackback'); |
| 29 | |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 30 | Once loaded, the Trackback library object will be available using:: |
| 31 | |
| 32 | $this->trackback |
Derek Jones | 8ede1a2 | 2011-10-05 13:34:52 -0500 | [diff] [blame] | 33 | |
| 34 | Sending Trackbacks |
| 35 | ================== |
| 36 | |
| 37 | A Trackback can be sent from any of your controller functions using code |
| 38 | similar to this example:: |
| 39 | |
Derek Jones | e0da604 | 2011-10-05 15:37:39 -0500 | [diff] [blame] | 40 | $this->load->library('trackback'); |
| 41 | |
| 42 | $tb_data = array( |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 43 | 'ping_url' => 'http://example.com/trackback/456', |
| 44 | 'url' => 'http://www.my-example.com/blog/entry/123', |
| 45 | 'title' => 'The Title of My Entry', |
| 46 | 'excerpt' => 'The entry content.', |
| 47 | 'blog_name' => 'My Blog Name', |
| 48 | 'charset' => 'utf-8' |
| 49 | ); |
Derek Jones | e0da604 | 2011-10-05 15:37:39 -0500 | [diff] [blame] | 50 | |
| 51 | if ( ! $this->trackback->send($tb_data)) |
| 52 | { |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 53 | echo $this->trackback->display_errors(); |
Derek Jones | e0da604 | 2011-10-05 15:37:39 -0500 | [diff] [blame] | 54 | } |
| 55 | else |
| 56 | { |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 57 | echo 'Trackback was sent!'; |
Derek Jones | e0da604 | 2011-10-05 15:37:39 -0500 | [diff] [blame] | 58 | } |
Derek Jones | 8ede1a2 | 2011-10-05 13:34:52 -0500 | [diff] [blame] | 59 | |
| 60 | Description of array data: |
| 61 | |
| 62 | - **ping_url** - The URL of the site you are sending the Trackback to. |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 63 | You can send Trackbacks to multiple URLs by separating each URL with a comma. |
Derek Jones | 8ede1a2 | 2011-10-05 13:34:52 -0500 | [diff] [blame] | 64 | - **url** - The URL to YOUR site where the weblog entry can be seen. |
| 65 | - **title** - The title of your weblog entry. |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 66 | - **excerpt** - The content of your weblog entry. |
Derek Jones | 8ede1a2 | 2011-10-05 13:34:52 -0500 | [diff] [blame] | 67 | - **blog_name** - The name of your weblog. |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 68 | - **charset** - The character encoding your weblog is written in. If omitted, UTF-8 will be used. |
Derek Jones | 8ede1a2 | 2011-10-05 13:34:52 -0500 | [diff] [blame] | 69 | |
Andrey Andreev | 9a0e660 | 2015-01-19 14:54:08 +0200 | [diff] [blame] | 70 | .. note:: The Trackback class will automatically send only the first 500 characters of your |
Connor Tumbleson | 75b3fb2 | 2014-01-11 06:58:43 -0600 | [diff] [blame] | 71 | entry. It will also strip all HTML. |
| 72 | |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 73 | The Trackback sending method returns TRUE/FALSE (boolean) on success |
Derek Jones | 8ede1a2 | 2011-10-05 13:34:52 -0500 | [diff] [blame] | 74 | or failure. If it fails, you can retrieve the error message using:: |
| 75 | |
| 76 | $this->trackback->display_errors(); |
| 77 | |
| 78 | Receiving Trackbacks |
| 79 | ==================== |
| 80 | |
| 81 | Before you can receive Trackbacks you must create a weblog. If you don't |
| 82 | have a blog yet there's no point in continuing. |
| 83 | |
| 84 | Receiving Trackbacks is a little more complex than sending them, only |
| 85 | because you will need a database table in which to store them, and you |
| 86 | will need to validate the incoming trackback data. You are encouraged to |
| 87 | implement a thorough validation process to guard against spam and |
| 88 | duplicate data. You may also want to limit the number of Trackbacks you |
| 89 | allow from a particular IP within a given span of time to further |
| 90 | curtail spam. The process of receiving a Trackback is quite simple; the |
| 91 | validation is what takes most of the effort. |
| 92 | |
| 93 | Your Ping URL |
| 94 | ============= |
| 95 | |
| 96 | In order to accept Trackbacks you must display a Trackback URL next to |
| 97 | each one of your weblog entries. This will be the URL that people will |
| 98 | use to send you Trackbacks (we will refer to this as your "Ping URL"). |
| 99 | |
| 100 | Your Ping URL must point to a controller function where your Trackback |
| 101 | receiving code is located, and the URL must contain the ID number for |
| 102 | each particular entry, so that when the Trackback is received you'll be |
| 103 | able to associate it with a particular entry. |
| 104 | |
| 105 | For example, if your controller class is called Trackback, and the |
| 106 | receiving function is called receive, your Ping URLs will look something |
| 107 | like this:: |
| 108 | |
| 109 | http://example.com/index.php/trackback/receive/entry_id |
| 110 | |
| 111 | Where entry_id represents the individual ID number for each of your |
| 112 | entries. |
| 113 | |
| 114 | Creating a Trackback Table |
| 115 | ========================== |
| 116 | |
| 117 | Before you can receive Trackbacks you must create a table in which to |
Derek Jones | e0da604 | 2011-10-05 15:37:39 -0500 | [diff] [blame] | 118 | store them. Here is a basic prototype for such a table:: |
Derek Jones | 8ede1a2 | 2011-10-05 13:34:52 -0500 | [diff] [blame] | 119 | |
Derek Jones | e0da604 | 2011-10-05 15:37:39 -0500 | [diff] [blame] | 120 | CREATE TABLE trackbacks ( |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 121 | tb_id int(10) unsigned NOT NULL auto_increment, |
| 122 | entry_id int(10) unsigned NOT NULL default 0, |
| 123 | url varchar(200) NOT NULL, |
| 124 | title varchar(100) NOT NULL, |
| 125 | excerpt text NOT NULL, |
| 126 | blog_name varchar(100) NOT NULL, |
| 127 | tb_date int(10) NOT NULL, |
| 128 | ip_address varchar(45) NOT NULL, |
| 129 | PRIMARY KEY `tb_id` (`tb_id`), |
| 130 | KEY `entry_id` (`entry_id`) |
Derek Jones | e0da604 | 2011-10-05 15:37:39 -0500 | [diff] [blame] | 131 | ); |
| 132 | |
Derek Jones | 8ede1a2 | 2011-10-05 13:34:52 -0500 | [diff] [blame] | 133 | The Trackback specification only requires four pieces of information to |
| 134 | be sent in a Trackback (url, title, excerpt, blog_name), but to make |
| 135 | the data more useful we've added a few more fields in the above table |
| 136 | schema (date, IP address, etc.). |
| 137 | |
| 138 | Processing a Trackback |
| 139 | ====================== |
| 140 | |
| 141 | Here is an example showing how you will receive and process a Trackback. |
| 142 | The following code is intended for use within the controller function |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 143 | where you expect to receive Trackbacks.:: |
Derek Jones | 8ede1a2 | 2011-10-05 13:34:52 -0500 | [diff] [blame] | 144 | |
Derek Jones | e0da604 | 2011-10-05 15:37:39 -0500 | [diff] [blame] | 145 | $this->load->library('trackback'); |
| 146 | $this->load->database(); |
| 147 | |
| 148 | if ($this->uri->segment(3) == FALSE) |
| 149 | { |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 150 | $this->trackback->send_error('Unable to determine the entry ID'); |
Derek Jones | e0da604 | 2011-10-05 15:37:39 -0500 | [diff] [blame] | 151 | } |
| 152 | |
| 153 | if ( ! $this->trackback->receive()) |
| 154 | { |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 155 | $this->trackback->send_error('The Trackback did not contain valid data'); |
Derek Jones | e0da604 | 2011-10-05 15:37:39 -0500 | [diff] [blame] | 156 | } |
| 157 | |
| 158 | $data = array( |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 159 | 'tb_id' => '', |
| 160 | 'entry_id' => $this->uri->segment(3), |
| 161 | 'url' => $this->trackback->data('url'), |
| 162 | 'title' => $this->trackback->data('title'), |
| 163 | 'excerpt' => $this->trackback->data('excerpt'), |
| 164 | 'blog_name' => $this->trackback->data('blog_name'), |
| 165 | 'tb_date' => time(), |
| 166 | 'ip_address' => $this->input->ip_address() |
| 167 | ); |
Derek Jones | e0da604 | 2011-10-05 15:37:39 -0500 | [diff] [blame] | 168 | |
| 169 | $sql = $this->db->insert_string('trackbacks', $data); |
| 170 | $this->db->query($sql); |
| 171 | |
| 172 | $this->trackback->send_success(); |
Derek Jones | 8ede1a2 | 2011-10-05 13:34:52 -0500 | [diff] [blame] | 173 | |
| 174 | Notes: |
| 175 | ^^^^^^ |
| 176 | |
| 177 | The entry ID number is expected in the third segment of your URL. This |
| 178 | is based on the URI example we gave earlier:: |
| 179 | |
| 180 | http://example.com/index.php/trackback/receive/entry_id |
| 181 | |
| 182 | Notice the entry_id is in the third URI segment, which you can retrieve |
| 183 | using:: |
| 184 | |
| 185 | $this->uri->segment(3); |
| 186 | |
| 187 | In our Trackback receiving code above, if the third segment is missing, |
| 188 | we will issue an error. Without a valid entry ID, there's no reason to |
| 189 | continue. |
| 190 | |
| 191 | The $this->trackback->receive() function is simply a validation function |
| 192 | that looks at the incoming data and makes sure it contains the four |
| 193 | pieces of data that are required (url, title, excerpt, blog_name). It |
| 194 | returns TRUE on success and FALSE on failure. If it fails you will issue |
| 195 | an error message. |
| 196 | |
| 197 | The incoming Trackback data can be retrieved using this function:: |
| 198 | |
| 199 | $this->trackback->data('item') |
| 200 | |
| 201 | Where item represents one of these four pieces of info: url, title, |
| 202 | excerpt, or blog_name |
| 203 | |
| 204 | If the Trackback data is successfully received, you will issue a success |
| 205 | message using:: |
| 206 | |
| 207 | $this->trackback->send_success(); |
| 208 | |
| 209 | .. note:: The above code contains no data validation, which you are |
| 210 | encouraged to add. |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 211 | |
| 212 | *************** |
| 213 | Class Reference |
| 214 | *************** |
| 215 | |
Andrey Andreev | cd3d9db | 2015-02-02 13:41:01 +0200 | [diff] [blame] | 216 | .. php:class:: CI_Trackback |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 217 | |
| 218 | .. attribute:: $data = array('url' => '', 'title' => '', 'excerpt' => '', 'blog_name' => '', 'charset' => '') |
| 219 | |
| 220 | Trackback data array. |
| 221 | |
| 222 | .. attribute:: $convert_ascii = TRUE |
| 223 | |
| 224 | Whether to convert high ASCII and MS Word characters to HTML entities. |
| 225 | |
Andrey Andreev | cd3d9db | 2015-02-02 13:41:01 +0200 | [diff] [blame] | 226 | .. php:method:: send($tb_data) |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 227 | |
Andrey Andreev | 28c2c97 | 2014-02-08 04:27:48 +0200 | [diff] [blame] | 228 | :param array $tb_data: Trackback data |
| 229 | :returns: TRUE on success, FALSE on failure |
| 230 | :rtype: bool |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 231 | |
| 232 | Send trackback. |
| 233 | |
Andrey Andreev | cd3d9db | 2015-02-02 13:41:01 +0200 | [diff] [blame] | 234 | .. php:method:: receive() |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 235 | |
Andrey Andreev | 28c2c97 | 2014-02-08 04:27:48 +0200 | [diff] [blame] | 236 | :returns: TRUE on success, FALSE on failure |
| 237 | :rtype: bool |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 238 | |
| 239 | This method simply validates the incoming TB data, returning TRUE on success and FALSE on failure. |
| 240 | If the data is valid it is set to the ``$this->data`` array so that it can be inserted into a database. |
| 241 | |
Andrey Andreev | 3e75ff6 | 2015-12-10 13:28:19 +0200 | [diff] [blame] | 242 | .. php:method:: send_error([$message = 'Incomplete information']) |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 243 | |
Andrey Andreev | 28c2c97 | 2014-02-08 04:27:48 +0200 | [diff] [blame] | 244 | :param string $message: Error message |
| 245 | :rtype: void |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 246 | |
| 247 | Responses to a trackback request with an error message. |
| 248 | |
| 249 | .. note:: This method will terminate script execution. |
| 250 | |
Andrey Andreev | cd3d9db | 2015-02-02 13:41:01 +0200 | [diff] [blame] | 251 | .. php:method:: send_success() |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 252 | |
Andrey Andreev | 28c2c97 | 2014-02-08 04:27:48 +0200 | [diff] [blame] | 253 | :rtype: void |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 254 | |
| 255 | Responses to a trackback request with a success message. |
| 256 | |
| 257 | .. note:: This method will terminate script execution. |
| 258 | |
Andrey Andreev | cd3d9db | 2015-02-02 13:41:01 +0200 | [diff] [blame] | 259 | .. php:method:: data($item) |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 260 | |
Andrey Andreev | 28c2c97 | 2014-02-08 04:27:48 +0200 | [diff] [blame] | 261 | :param string $item: Data key |
| 262 | :returns: Data value or empty string if not found |
| 263 | :rtype: string |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 264 | |
Andrey Andreev | 71d8f72 | 2017-01-17 12:01:00 +0200 | [diff] [blame] | 265 | Returns a single item from the response data array. |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 266 | |
Andrey Andreev | cd3d9db | 2015-02-02 13:41:01 +0200 | [diff] [blame] | 267 | .. php:method:: process($url, $data) |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 268 | |
Andrey Andreev | 28c2c97 | 2014-02-08 04:27:48 +0200 | [diff] [blame] | 269 | :param string $url: Target url |
| 270 | :param string $data: Raw POST data |
| 271 | :returns: TRUE on success, FALSE on failure |
| 272 | :rtype: bool |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 273 | |
| 274 | Opens a socket connection and passes the data to the server, returning TRUE on success and FALSE on failure. |
| 275 | |
Andrey Andreev | cd3d9db | 2015-02-02 13:41:01 +0200 | [diff] [blame] | 276 | .. php:method:: extract_urls($urls) |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 277 | |
Andrey Andreev | 28c2c97 | 2014-02-08 04:27:48 +0200 | [diff] [blame] | 278 | :param string $urls: Comma-separated URL list |
| 279 | :returns: Array of URLs |
| 280 | :rtype: array |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 281 | |
| 282 | This method lets multiple trackbacks to be sent. It takes a string of URLs (separated by comma or space) and puts each URL into an array. |
| 283 | |
Andrey Andreev | cd3d9db | 2015-02-02 13:41:01 +0200 | [diff] [blame] | 284 | .. php:method:: validate_url(&$url) |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 285 | |
Andrey Andreev | 28c2c97 | 2014-02-08 04:27:48 +0200 | [diff] [blame] | 286 | :param string $url: Trackback URL |
| 287 | :rtype: void |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 288 | |
| 289 | Simply adds the *http://* prefix it it's not already present in the URL. |
| 290 | |
Andrey Andreev | cd3d9db | 2015-02-02 13:41:01 +0200 | [diff] [blame] | 291 | .. php:method:: get_id($url) |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 292 | |
Andrey Andreev | 28c2c97 | 2014-02-08 04:27:48 +0200 | [diff] [blame] | 293 | :param string $url: Trackback URL |
| 294 | :returns: URL ID or FALSE on failure |
| 295 | :rtype: string |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 296 | |
| 297 | Find and return a trackback URL's ID or FALSE on failure. |
| 298 | |
Andrey Andreev | cd3d9db | 2015-02-02 13:41:01 +0200 | [diff] [blame] | 299 | .. php:method:: convert_xml($str) |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 300 | |
Andrey Andreev | 28c2c97 | 2014-02-08 04:27:48 +0200 | [diff] [blame] | 301 | :param string $str: Input string |
| 302 | :returns: Converted string |
| 303 | :rtype: string |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 304 | |
| 305 | Converts reserved XML characters to entities. |
| 306 | |
Andrey Andreev | cd3d9db | 2015-02-02 13:41:01 +0200 | [diff] [blame] | 307 | .. php:method:: limit_characters($str[, $n = 500[, $end_char = '…']]) |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 308 | |
Andrey Andreev | 28c2c97 | 2014-02-08 04:27:48 +0200 | [diff] [blame] | 309 | :param string $str: Input string |
| 310 | :param int $n: Max characters number |
| 311 | :param string $end_char: Character to put at end of string |
| 312 | :returns: Shortened string |
| 313 | :rtype: string |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 314 | |
| 315 | Limits the string based on the character count. Will preserve complete words. |
| 316 | |
Andrey Andreev | cd3d9db | 2015-02-02 13:41:01 +0200 | [diff] [blame] | 317 | .. php:method:: convert_ascii($str) |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 318 | |
Andrey Andreev | 28c2c97 | 2014-02-08 04:27:48 +0200 | [diff] [blame] | 319 | :param string $str: Input string |
| 320 | :returns: Converted string |
| 321 | :rtype: string |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 322 | |
| 323 | Converts high ASCII text and MS Word special characterss to HTML entities. |
| 324 | |
Andrey Andreev | cd3d9db | 2015-02-02 13:41:01 +0200 | [diff] [blame] | 325 | .. php:method:: set_error($msg) |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 326 | |
Andrey Andreev | 28c2c97 | 2014-02-08 04:27:48 +0200 | [diff] [blame] | 327 | :param string $msg: Error message |
| 328 | :rtype: void |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 329 | |
| 330 | Set an log an error message. |
| 331 | |
Andrey Andreev | cd3d9db | 2015-02-02 13:41:01 +0200 | [diff] [blame] | 332 | .. php:method:: display_errors([$open = '<p>'[, $close = '</p>']]) |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 333 | |
Andrey Andreev | 28c2c97 | 2014-02-08 04:27:48 +0200 | [diff] [blame] | 334 | :param string $open: Open tag |
| 335 | :param string $close: Close tag |
| 336 | :returns: HTML formatted error messages |
| 337 | :rtype: string |
Andrey Andreev | 9ea31e8 | 2013-09-23 17:20:56 +0300 | [diff] [blame] | 338 | |
| 339 | Returns error messages formatted in HTML or an empty string if there are no errors. |