]>
Commit | Line | Data |
---|---|---|
59c06b17 CS |
1 | <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); |
2 | /** | |
3 | * CodeIgniter | |
4 | * | |
5 | * An open source application development framework for PHP 5.1.6 or newer | |
6 | * | |
7 | * @package CodeIgniter | |
8 | * @author ExpressionEngine Dev Team | |
9 | * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc. | |
10 | * @license http://codeigniter.com/user_guide/license.html | |
11 | * @link http://codeigniter.com | |
12 | * @since Version 1.0 | |
13 | * @filesource | |
14 | */ | |
15 | ||
16 | // ------------------------------------------------------------------------ | |
17 | ||
18 | /** | |
19 | * Trackback Class | |
20 | * | |
21 | * Trackback Sending/Receiving Class | |
22 | * | |
23 | * @package CodeIgniter | |
24 | * @subpackage Libraries | |
25 | * @category Trackbacks | |
26 | * @author ExpressionEngine Dev Team | |
27 | * @link http://codeigniter.com/user_guide/libraries/trackback.html | |
28 | */ | |
29 | class CI_Trackback { | |
30 | ||
31 | var $time_format = 'local'; | |
32 | var $charset = 'UTF-8'; | |
33 | var $data = array('url' => '', 'title' => '', 'excerpt' => '', 'blog_name' => '', 'charset' => ''); | |
34 | var $convert_ascii = TRUE; | |
35 | var $response = ''; | |
36 | var $error_msg = array(); | |
37 | ||
38 | /** | |
39 | * Constructor | |
40 | * | |
41 | * @access public | |
42 | */ | |
43 | public function __construct() | |
44 | { | |
45 | log_message('debug', "Trackback Class Initialized"); | |
46 | } | |
47 | ||
48 | // -------------------------------------------------------------------- | |
49 | ||
50 | /** | |
51 | * Send Trackback | |
52 | * | |
53 | * @access public | |
54 | * @param array | |
55 | * @return bool | |
56 | */ | |
57 | function send($tb_data) | |
58 | { | |
59 | if ( ! is_array($tb_data)) | |
60 | { | |
61 | $this->set_error('The send() method must be passed an array'); | |
62 | return FALSE; | |
63 | } | |
64 | ||
65 | // Pre-process the Trackback Data | |
66 | foreach (array('url', 'title', 'excerpt', 'blog_name', 'ping_url') as $item) | |
67 | { | |
68 | if ( ! isset($tb_data[$item])) | |
69 | { | |
70 | $this->set_error('Required item missing: '.$item); | |
71 | return FALSE; | |
72 | } | |
73 | ||
74 | switch ($item) | |
75 | { | |
76 | case 'ping_url' : $$item = $this->extract_urls($tb_data[$item]); | |
77 | break; | |
78 | case 'excerpt' : $$item = $this->limit_characters($this->convert_xml(strip_tags(stripslashes($tb_data[$item])))); | |
79 | break; | |
80 | case 'url' : $$item = str_replace('-', '-', $this->convert_xml(strip_tags(stripslashes($tb_data[$item])))); | |
81 | break; | |
82 | default : $$item = $this->convert_xml(strip_tags(stripslashes($tb_data[$item]))); | |
83 | break; | |
84 | } | |
85 | ||
86 | // Convert High ASCII Characters | |
87 | if ($this->convert_ascii == TRUE) | |
88 | { | |
89 | if ($item == 'excerpt') | |
90 | { | |
91 | $$item = $this->convert_ascii($$item); | |
92 | } | |
93 | elseif ($item == 'title') | |
94 | { | |
95 | $$item = $this->convert_ascii($$item); | |
96 | } | |
97 | elseif ($item == 'blog_name') | |
98 | { | |
99 | $$item = $this->convert_ascii($$item); | |
100 | } | |
101 | } | |
102 | } | |
103 | ||
104 | // Build the Trackback data string | |
105 | $charset = ( ! isset($tb_data['charset'])) ? $this->charset : $tb_data['charset']; | |
106 | ||
107 | $data = "url=".rawurlencode($url)."&title=".rawurlencode($title)."&blog_name=".rawurlencode($blog_name)."&excerpt=".rawurlencode($excerpt)."&charset=".rawurlencode($charset); | |
108 | ||
109 | // Send Trackback(s) | |
110 | $return = TRUE; | |
111 | if (count($ping_url) > 0) | |
112 | { | |
113 | foreach ($ping_url as $url) | |
114 | { | |
115 | if ($this->process($url, $data) == FALSE) | |
116 | { | |
117 | $return = FALSE; | |
118 | } | |
119 | } | |
120 | } | |
121 | ||
122 | return $return; | |
123 | } | |
124 | ||
125 | // -------------------------------------------------------------------- | |
126 | ||
127 | /** | |
128 | * Receive Trackback Data | |
129 | * | |
130 | * This function simply validates the incoming TB data. | |
131 | * It returns FALSE on failure and TRUE on success. | |
132 | * If the data is valid it is set to the $this->data array | |
133 | * so that it can be inserted into a database. | |
134 | * | |
135 | * @access public | |
136 | * @return bool | |
137 | */ | |
138 | function receive() | |
139 | { | |
140 | foreach (array('url', 'title', 'blog_name', 'excerpt') as $val) | |
141 | { | |
142 | if ( ! isset($_POST[$val]) OR $_POST[$val] == '') | |
143 | { | |
144 | $this->set_error('The following required POST variable is missing: '.$val); | |
145 | return FALSE; | |
146 | } | |
147 | ||
148 | $this->data['charset'] = ( ! isset($_POST['charset'])) ? 'auto' : strtoupper(trim($_POST['charset'])); | |
149 | ||
150 | if ($val != 'url' && function_exists('mb_convert_encoding')) | |
151 | { | |
152 | $_POST[$val] = mb_convert_encoding($_POST[$val], $this->charset, $this->data['charset']); | |
153 | } | |
154 | ||
155 | $_POST[$val] = ($val != 'url') ? $this->convert_xml(strip_tags($_POST[$val])) : strip_tags($_POST[$val]); | |
156 | ||
157 | if ($val == 'excerpt') | |
158 | { | |
159 | $_POST['excerpt'] = $this->limit_characters($_POST['excerpt']); | |
160 | } | |
161 | ||
162 | $this->data[$val] = $_POST[$val]; | |
163 | } | |
164 | ||
165 | return TRUE; | |
166 | } | |
167 | ||
168 | // -------------------------------------------------------------------- | |
169 | ||
170 | /** | |
171 | * Send Trackback Error Message | |
172 | * | |
173 | * Allows custom errors to be set. By default it | |
174 | * sends the "incomplete information" error, as that's | |
175 | * the most common one. | |
176 | * | |
177 | * @access public | |
178 | * @param string | |
179 | * @return void | |
180 | */ | |
181 | function send_error($message = 'Incomplete Information') | |
182 | { | |
183 | echo "<?xml version=\"1.0\" encoding=\"utf-8\"?".">\n<response>\n<error>1</error>\n<message>".$message."</message>\n</response>"; | |
184 | exit; | |
185 | } | |
186 | ||
187 | // -------------------------------------------------------------------- | |
188 | ||
189 | /** | |
190 | * Send Trackback Success Message | |
191 | * | |
192 | * This should be called when a trackback has been | |
193 | * successfully received and inserted. | |
194 | * | |
195 | * @access public | |
196 | * @return void | |
197 | */ | |
198 | function send_success() | |
199 | { | |
200 | echo "<?xml version=\"1.0\" encoding=\"utf-8\"?".">\n<response>\n<error>0</error>\n</response>"; | |
201 | exit; | |
202 | } | |
203 | ||
204 | // -------------------------------------------------------------------- | |
205 | ||
206 | /** | |
207 | * Fetch a particular item | |
208 | * | |
209 | * @access public | |
210 | * @param string | |
211 | * @return string | |
212 | */ | |
213 | function data($item) | |
214 | { | |
215 | return ( ! isset($this->data[$item])) ? '' : $this->data[$item]; | |
216 | } | |
217 | ||
218 | // -------------------------------------------------------------------- | |
219 | ||
220 | /** | |
221 | * Process Trackback | |
222 | * | |
223 | * Opens a socket connection and passes the data to | |
224 | * the server. Returns TRUE on success, FALSE on failure | |
225 | * | |
226 | * @access public | |
227 | * @param string | |
228 | * @param string | |
229 | * @return bool | |
230 | */ | |
231 | function process($url, $data) | |
232 | { | |
233 | $target = parse_url($url); | |
234 | ||
235 | // Open the socket | |
236 | if ( ! $fp = @fsockopen($target['host'], 80)) | |
237 | { | |
238 | $this->set_error('Invalid Connection: '.$url); | |
239 | return FALSE; | |
240 | } | |
241 | ||
242 | // Build the path | |
243 | $ppath = ( ! isset($target['path'])) ? $url : $target['path']; | |
244 | ||
245 | $path = (isset($target['query']) && $target['query'] != "") ? $ppath.'?'.$target['query'] : $ppath; | |
246 | ||
247 | // Add the Trackback ID to the data string | |
248 | if ($id = $this->get_id($url)) | |
249 | { | |
250 | $data = "tb_id=".$id."&".$data; | |
251 | } | |
252 | ||
253 | // Transfer the data | |
254 | fputs ($fp, "POST " . $path . " HTTP/1.0\r\n" ); | |
255 | fputs ($fp, "Host: " . $target['host'] . "\r\n" ); | |
256 | fputs ($fp, "Content-type: application/x-www-form-urlencoded\r\n" ); | |
257 | fputs ($fp, "Content-length: " . strlen($data) . "\r\n" ); | |
258 | fputs ($fp, "Connection: close\r\n\r\n" ); | |
259 | fputs ($fp, $data); | |
260 | ||
261 | // Was it successful? | |
262 | $this->response = ""; | |
263 | ||
264 | while ( ! feof($fp)) | |
265 | { | |
266 | $this->response .= fgets($fp, 128); | |
267 | } | |
268 | @fclose($fp); | |
269 | ||
270 | ||
271 | if (stristr($this->response, '<error>0</error>') === FALSE) | |
272 | { | |
273 | $message = 'An unknown error was encountered'; | |
274 | ||
275 | if (preg_match("/<message>(.*?)<\/message>/is", $this->response, $match)) | |
276 | { | |
277 | $message = trim($match['1']); | |
278 | } | |
279 | ||
280 | $this->set_error($message); | |
281 | return FALSE; | |
282 | } | |
283 | ||
284 | return TRUE; | |
285 | } | |
286 | ||
287 | // -------------------------------------------------------------------- | |
288 | ||
289 | /** | |
290 | * Extract Trackback URLs | |
291 | * | |
292 | * This function lets multiple trackbacks be sent. | |
293 | * It takes a string of URLs (separated by comma or | |
294 | * space) and puts each URL into an array | |
295 | * | |
296 | * @access public | |
297 | * @param string | |
298 | * @return string | |
299 | */ | |
300 | function extract_urls($urls) | |
301 | { | |
302 | // Remove the pesky white space and replace with a comma. | |
303 | $urls = preg_replace("/\s*(\S+)\s*/", "\\1,", $urls); | |
304 | ||
305 | // If they use commas get rid of the doubles. | |
306 | $urls = str_replace(",,", ",", $urls); | |
307 | ||
308 | // Remove any comma that might be at the end | |
309 | if (substr($urls, -1) == ",") | |
310 | { | |
311 | $urls = substr($urls, 0, -1); | |
312 | } | |
313 | ||
314 | // Break into an array via commas | |
315 | $urls = preg_split('/[,]/', $urls); | |
316 | ||
317 | // Removes duplicates | |
318 | $urls = array_unique($urls); | |
319 | ||
320 | array_walk($urls, array($this, 'validate_url')); | |
321 | ||
322 | return $urls; | |
323 | } | |
324 | ||
325 | // -------------------------------------------------------------------- | |
326 | ||
327 | /** | |
328 | * Validate URL | |
329 | * | |
330 | * Simply adds "http://" if missing | |
331 | * | |
332 | * @access public | |
333 | * @param string | |
334 | * @return string | |
335 | */ | |
336 | function validate_url($url) | |
337 | { | |
338 | $url = trim($url); | |
339 | ||
340 | if (substr($url, 0, 4) != "http") | |
341 | { | |
342 | $url = "http://".$url; | |
343 | } | |
344 | } | |
345 | ||
346 | // -------------------------------------------------------------------- | |
347 | ||
348 | /** | |
349 | * Find the Trackback URL's ID | |
350 | * | |
351 | * @access public | |
352 | * @param string | |
353 | * @return string | |
354 | */ | |
355 | function get_id($url) | |
356 | { | |
357 | $tb_id = ""; | |
358 | ||
359 | if (strpos($url, '?') !== FALSE) | |
360 | { | |
361 | $tb_array = explode('/', $url); | |
362 | $tb_end = $tb_array[count($tb_array)-1]; | |
363 | ||
364 | if ( ! is_numeric($tb_end)) | |
365 | { | |
366 | $tb_end = $tb_array[count($tb_array)-2]; | |
367 | } | |
368 | ||
369 | $tb_array = explode('=', $tb_end); | |
370 | $tb_id = $tb_array[count($tb_array)-1]; | |
371 | } | |
372 | else | |
373 | { | |
374 | $url = rtrim($url, '/'); | |
375 | ||
376 | $tb_array = explode('/', $url); | |
377 | $tb_id = $tb_array[count($tb_array)-1]; | |
378 | ||
379 | if ( ! is_numeric($tb_id)) | |
380 | { | |
381 | $tb_id = $tb_array[count($tb_array)-2]; | |
382 | } | |
383 | } | |
384 | ||
385 | if ( ! preg_match ("/^([0-9]+)$/", $tb_id)) | |
386 | { | |
387 | return FALSE; | |
388 | } | |
389 | else | |
390 | { | |
391 | return $tb_id; | |
392 | } | |
393 | } | |
394 | ||
395 | // -------------------------------------------------------------------- | |
396 | ||
397 | /** | |
398 | * Convert Reserved XML characters to Entities | |
399 | * | |
400 | * @access public | |
401 | * @param string | |
402 | * @return string | |
403 | */ | |
404 | function convert_xml($str) | |
405 | { | |
406 | $temp = '__TEMP_AMPERSANDS__'; | |
407 | ||
408 | $str = preg_replace("/&#(\d+);/", "$temp\\1;", $str); | |
409 | $str = preg_replace("/&(\w+);/", "$temp\\1;", $str); | |
410 | ||
411 | $str = str_replace(array("&","<",">","\"", "'", "-"), | |
412 | array("&", "<", ">", """, "'", "-"), | |
413 | $str); | |
414 | ||
415 | $str = preg_replace("/$temp(\d+);/","&#\\1;",$str); | |
416 | $str = preg_replace("/$temp(\w+);/","&\\1;", $str); | |
417 | ||
418 | return $str; | |
419 | } | |
420 | ||
421 | // -------------------------------------------------------------------- | |
422 | ||
423 | /** | |
424 | * Character limiter | |
425 | * | |
426 | * Limits the string based on the character count. Will preserve complete words. | |
427 | * | |
428 | * @access public | |
429 | * @param string | |
430 | * @param integer | |
431 | * @param string | |
432 | * @return string | |
433 | */ | |
434 | function limit_characters($str, $n = 500, $end_char = '…') | |
435 | { | |
436 | if (strlen($str) < $n) | |
437 | { | |
438 | return $str; | |
439 | } | |
440 | ||
441 | $str = preg_replace("/\s+/", ' ', str_replace(array("\r\n", "\r", "\n"), ' ', $str)); | |
442 | ||
443 | if (strlen($str) <= $n) | |
444 | { | |
445 | return $str; | |
446 | } | |
447 | ||
448 | $out = ""; | |
449 | foreach (explode(' ', trim($str)) as $val) | |
450 | { | |
451 | $out .= $val.' '; | |
452 | if (strlen($out) >= $n) | |
453 | { | |
454 | return trim($out).$end_char; | |
455 | } | |
456 | } | |
457 | } | |
458 | ||
459 | // -------------------------------------------------------------------- | |
460 | ||
461 | /** | |
462 | * High ASCII to Entities | |
463 | * | |
464 | * Converts Hight ascii text and MS Word special chars | |
465 | * to character entities | |
466 | * | |
467 | * @access public | |
468 | * @param string | |
469 | * @return string | |
470 | */ | |
471 | function convert_ascii($str) | |
472 | { | |
473 | $count = 1; | |
474 | $out = ''; | |
475 | $temp = array(); | |
476 | ||
477 | for ($i = 0, $s = strlen($str); $i < $s; $i++) | |
478 | { | |
479 | $ordinal = ord($str[$i]); | |
480 | ||
481 | if ($ordinal < 128) | |
482 | { | |
483 | $out .= $str[$i]; | |
484 | } | |
485 | else | |
486 | { | |
487 | if (count($temp) == 0) | |
488 | { | |
489 | $count = ($ordinal < 224) ? 2 : 3; | |
490 | } | |
491 | ||
492 | $temp[] = $ordinal; | |
493 | ||
494 | if (count($temp) == $count) | |
495 | { | |
496 | $number = ($count == 3) ? (($temp['0'] % 16) * 4096) + (($temp['1'] % 64) * 64) + ($temp['2'] % 64) : (($temp['0'] % 32) * 64) + ($temp['1'] % 64); | |
497 | ||
498 | $out .= '&#'.$number.';'; | |
499 | $count = 1; | |
500 | $temp = array(); | |
501 | } | |
502 | } | |
503 | } | |
504 | ||
505 | return $out; | |
506 | } | |
507 | ||
508 | // -------------------------------------------------------------------- | |
509 | ||
510 | /** | |
511 | * Set error message | |
512 | * | |
513 | * @access public | |
514 | * @param string | |
515 | * @return void | |
516 | */ | |
517 | function set_error($msg) | |
518 | { | |
519 | log_message('error', $msg); | |
520 | $this->error_msg[] = $msg; | |
521 | } | |
522 | ||
523 | // -------------------------------------------------------------------- | |
524 | ||
525 | /** | |
526 | * Show error messages | |
527 | * | |
528 | * @access public | |
529 | * @param string | |
530 | * @param string | |
531 | * @return string | |
532 | */ | |
533 | function display_errors($open = '<p>', $close = '</p>') | |
534 | { | |
535 | $str = ''; | |
536 | foreach ($this->error_msg as $val) | |
537 | { | |
538 | $str .= $open.$val.$close; | |
539 | } | |
540 | ||
541 | return $str; | |
542 | } | |
543 | ||
544 | } | |
545 | // END Trackback Class | |
546 | ||
547 | /* End of file Trackback.php */ | |
548 | /* Location: ./system/libraries/Trackback.php */ |