[ Index ] |
|
Code source de Dotclear 2.0-beta6 |
1 <?php 2 # ***** BEGIN LICENSE BLOCK ***** 3 # This file is part of DotClear. 4 # Copyright (c) 2005 Olivier Meunier. All rights 5 # reserved. 6 # 7 # DotClear is free software; you can redistribute it and/or modify 8 # it under the terms of the GNU General Public License as published by 9 # the Free Software Foundation; either version 2 of the License, or 10 # (at your option) any later version. 11 # 12 # DotClear is distributed in the hope that it will be useful, 13 # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 # GNU General Public License for more details. 16 # 17 # You should have received a copy of the GNU General Public License 18 # along with DotClear; if not, write to the Free Software 19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 # 21 # ***** END LICENSE BLOCK ***** 22 23 /** 24 @ingroup DC_CORE 25 @brief Trackbacks sender and server 26 27 Sends and receives trackbacks. Also handles trackbacks auto discovery. 28 */ 29 class dcTrackback 30 { 31 public $core; ///< <b>dcCore</b> dcCore instance 32 public $table; ///< <b>string</b> done pings table name 33 34 /** 35 Object constructor 36 37 @param core <b>dcCore</b> dcCore instance 38 */ 39 public function __construct(&$core) 40 { 41 $this->core =& $core; 42 $this->con =& $this->core->con; 43 $this->table = $this->core->prefix.'ping'; 44 } 45 46 /// @name Send trackbacks 47 //@{ 48 /** 49 Get all pings sent for a given post. 50 51 @param post_id <b>integer</b> Post ID 52 @return <b>record</b> 53 */ 54 public function getPostPings($post_id) 55 { 56 $strReq = 'SELECT ping_url, ping_dt '. 57 'FROM '.$this->table.' '. 58 'WHERE post_id = '.(integer) $post_id; 59 60 return $this->con->select($strReq); 61 } 62 63 /** 64 Sends a ping to given <var>$url</var>. 65 66 @param url <b>string</b> URL to ping 67 @param post_id <b>integer</b> Post ID 68 @param post_title <b>string</b> Post title 69 @param post_excerpt <b>string</b> Post excerpt 70 @param post_url <b>string</b> Post URL 71 */ 72 public function ping($url,$post_id,$post_title,$post_excerpt,$post_url) 73 { 74 if ($this->core->blog === null) { 75 return false; 76 } 77 78 $post_id = (integer) $post_id; 79 80 # Check for previously done trackback 81 $strReq = 'SELECT post_id, ping_url FROM '.$this->table.' '. 82 'WHERE post_id = '.$post_id.' '. 83 "AND ping_url = '".$this->con->escape($url)."' "; 84 85 $rs = $this->con->select($strReq); 86 87 if (!$rs->isEmpty()) { 88 throw new Exception(sprintf(__('%s has still been pinged'),$url)); 89 } 90 91 $data = array( 92 'title' => $post_title, 93 'excerpt' => $post_excerpt, 94 'url' => $post_url, 95 'blog_name' => trim(html::escapeHTML(html::clean($this->core->blog->name))) 96 //,'__debug' => false 97 ); 98 99 # Ping 100 try 101 { 102 $http = self::initHttp($url,$path); 103 $http->post($path,$data,'UTF-8'); 104 $res = $http->getContent(); 105 } 106 catch (Exception $e) 107 { 108 throw new Exception(__('Unable to ping URL')); 109 } 110 111 $pattern = 112 '|<response>.*<error>(.*)</error>(.*)'. 113 '(<message>(.*)</message>(.*))?'. 114 '</response>|msU'; 115 116 if (!preg_match($pattern,$res,$match)) 117 { 118 throw new Exception(sprintf(__('%s is not a ping URL'),$url)); 119 } 120 121 $ping_error = trim($match[1]); 122 $ping_msg = (!empty($match[4])) ? $match[4] : ''; 123 124 if ($ping_error != '0') { 125 throw new Exception(sprintf(__('%s, ping error:'),$url).' '.$ping_msg); 126 } else { 127 # Notify ping result in database 128 $cur = $this->con->openCursor($this->table); 129 $cur->post_id = $post_id; 130 $cur->ping_url = $url; 131 $cur->ping_dt = array('NOW()'); 132 133 $cur->insert(); 134 } 135 } 136 //@} 137 138 /// @name Receive trackbacks 139 //@{ 140 /** 141 Receives a trackback and insert it as a comment of given post. 142 143 @param post_id <b>integer</b> Post ID 144 */ 145 public function receive($post_id) 146 { 147 header('Content-Type: text/xml; charset=UTF-8'); 148 if (empty($_POST)) { 149 http::head(405,'Method Not Allowed'); 150 echo 151 '<?xml version="1.0" encoding="utf-8"?>'."\n". 152 "<response>\n". 153 " <error>1</error>\n". 154 " <message>POST request needed</message>\n". 155 "</response>"; 156 return; 157 } 158 159 $post_id = (integer) $post_id; 160 161 $title = !empty($_POST['title']) ? $_POST['title'] : ''; 162 $excerpt = !empty($_POST['excerpt']) ? $_POST['excerpt'] : ''; 163 $url = !empty($_POST['url']) ? $_POST['url'] : ''; 164 $blog_name = !empty($_POST['blog_name']) ? $_POST['blog_name'] : ''; 165 $charset = ''; 166 $comment = ''; 167 168 $err = false; 169 $msg = ''; 170 171 if ($this->core->blog === null) 172 { 173 $err = true; 174 $msg = 'No blog.'; 175 } 176 elseif ($url == '') 177 { 178 $err = true; 179 $msg = 'URL parameter is requiered.'; 180 } 181 elseif ($blog_name == '') { 182 $err = true; 183 $msg = 'Blog name is requiered.'; 184 } 185 186 if (!$err) 187 { 188 $post = $this->core->blog->getPosts(array('post_id'=>$post_id)); 189 190 if ($post->isEmpty()) 191 { 192 $err = true; 193 $msg = 'No such post.'; 194 } 195 elseif (!$post->trackbacksActive()) 196 { 197 $err = true; 198 $msg = 'Trackbacks are not allowed for this post or weblog.'; 199 } 200 } 201 202 if (!$err) 203 { 204 $charset = self::getCharsetFromRequest(); 205 206 if (!$charset) { 207 $charset = mb_detect_encoding($title.' '.$excerpt.' '.$blog_name, 208 'UTF-8,ISO-8859-1,ISO-8859-2,ISO-8859-3,'. 209 'ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,'. 210 'ISO-8859-9,ISO-8859-10,ISO-8859-13,ISO-8859-14,ISO-8859-15'); 211 } 212 213 if (strtolower($charset) != 'utf-8') { 214 $title = iconv($charset,'UTF-8',$title); 215 $excerpt = iconv($charset,'UTF-8',$excerpt); 216 $blog_name = iconv($charset,'UTF-8',$blog_name); 217 } 218 219 $title = trim(html::clean($title)); 220 $title = html::decodeEntities($title); 221 $title = html::escapeHTML($title); 222 $title = text::cutString($title,60); 223 224 $excerpt = trim(html::clean($excerpt)); 225 $excerpt = html::decodeEntities($excerpt); 226 $excerpt = preg_replace('/\s+/ms',' ',$excerpt); 227 $excerpt = text::cutString($excerpt,252); 228 $excerpt = html::escapeHTML($excerpt).'...'; 229 230 $blog_name = trim(html::clean($blog_name)); 231 $blog_name = html::decodeEntities($blog_name); 232 $blog_name = html::escapeHTML($blog_name); 233 $blog_name = text::cutString($blog_name,60); 234 235 $url = trim(html::clean($url)); 236 237 if (!$blog_name) { 238 $blog_name = 'Anonymous blog'; 239 } 240 241 $comment = 242 "<!-- TB -->\n". 243 '<p><strong>'.($title ? $title : $blog_name)."</strong></p>\n". 244 '<p>'.$excerpt.'</p>'; 245 246 $cur = $this->core->con->openCursor($this->core->prefix.'comment'); 247 $cur->comment_author = (string) $blog_name; 248 $cur->comment_site = (string) $url; 249 $cur->comment_content = (string) $comment; 250 $cur->post_id = $post_id; 251 $cur->comment_trackback = 1; 252 $cur->comment_status = $this->core->blog->settings->comments_pub ? 1 : -1; 253 $cur->comment_ip = http::realIP(); 254 255 try 256 { 257 # --BEHAVIOR-- publicBeforeTrackbackCreate 258 $this->core->callBehavior('publicBeforeTrackbackCreate',$cur); 259 260 $comment_id = $this->core->blog->addComment($cur); 261 262 # --BEHAVIOR-- publicAfterTrackbackCreate 263 $this->core->callBehavior('publicAfterTrackbackCreate',$cur,$comment_id); 264 } 265 catch (Exception $e) 266 { 267 $err = 1; 268 $msg = 'Something went wrong : '.$e->getMessage(); 269 } 270 } 271 272 273 $debug_trace = 274 " <debug>\n". 275 ' <title>'.$title."</title>\n". 276 ' <excerpt>'.$excerpt."</excerpt>\n". 277 ' <url>'.$url."</url>\n". 278 ' <blog_name>'.$blog_name."</blog_name>\n". 279 ' <charset>'.$charset."</charset>\n". 280 ' <comment>'.$comment."</comment>\n". 281 " </debug>\n"; 282 283 $resp = 284 '<?xml version="1.0" encoding="utf-8"?>'."\n". 285 "<response>\n". 286 ' <error>'.(integer) $err."</error>\n"; 287 288 if ($msg) { 289 $resp .= ' <message>'.$msg."</message>\n"; 290 } 291 292 if (!empty($_POST['__debug'])) { 293 $resp .= $debug_trace; 294 } 295 296 echo $resp."</response>"; 297 } 298 //@} 299 300 private static function initHttp($url,&$path) 301 { 302 $client = netHttp::initClient($url,$path,5); 303 $client->setUserAgent('Dotclear - http://www.dotclear.net/'); 304 $client->useGzip(false); 305 $client->setPersistReferers(false); 306 307 return $client; 308 } 309 310 private static function getCharsetFromRequest() 311 { 312 if (isset($_SERVER['CONTENT_TYPE'])) 313 { 314 if (preg_match('|charset=([a-zA-Z0-9-]+)|',$_SERVER['CONTENT_TYPE'],$m)) { 315 return $m[1]; 316 } 317 } 318 319 return null; 320 } 321 322 /// @name Trackbacks auto discovery 323 //@{ 324 /** 325 Returns an array containing all discovered trackbacks URLs in 326 <var>$text</var>. 327 328 @param text <b>string</b> Input text 329 @return <b>array</b> 330 */ 331 public function discover($text) 332 { 333 $res = array(); 334 335 foreach ($this->getTextLinks($text) as $link) 336 { 337 if (($url = $this->getPingURL($link)) !== null) { 338 $res[] = $url; 339 } 340 } 341 342 return $res; 343 } 344 //@} 345 346 private function getTextLinks($text) 347 { 348 $res = array(); 349 350 # href attribute on "a" tags 351 if (preg_match_all('/<a ([^>]+)>/ms', $text, $match, PREG_SET_ORDER)) 352 { 353 for ($i = 0; $i<count($match); $i++) 354 { 355 if (preg_match('/href="(http:\/\/[^"]+)"/ms', $match[$i][1], $matches)) { 356 $res[$matches[1]] = 1; 357 } 358 } 359 } 360 unset($match); 361 362 # cite attributes on "blockquote" and "q" tags 363 if (preg_match_all('/<(blockquote|q) ([^>]+)>/ms', $text, $match, PREG_SET_ORDER)) 364 { 365 for ($i = 0; $i<count($match); $i++) 366 { 367 if (preg_match('/cite="(http:\/\/[^"]+)"/ms', $match[$i][2], $matches)) { 368 $res[$matches[1]] = 1; 369 } 370 } 371 } 372 373 return array_keys($res); 374 } 375 376 private function getPingURL($url) 377 { 378 try 379 { 380 $http = self::initHttp($url,$path); 381 $http->get($path); 382 $page_content = $http->getContent(); 383 } 384 catch (Exception $e) 385 { 386 return false; 387 } 388 389 $pattern_rdf = 390 '/<rdf:RDF.*?>.*?'. 391 '<rdf:Description\s+(.*?)\/>'. 392 '.*?<\/rdf:RDF>'. 393 '/ms'; 394 395 preg_match_all($pattern_rdf,$page_content,$rdf_all,PREG_SET_ORDER); 396 397 for ($i=0; $i<count($rdf_all); $i++) 398 { 399 $rdf = $rdf_all[$i][1]; 400 401 if (preg_match('/dc:identifier="'.preg_quote($url,'/').'"/ms',$rdf)) { 402 if (preg_match('/trackback:ping="(.*?)"/ms',$rdf,$tb_link)) { 403 return $tb_link[1]; 404 } 405 } 406 } 407 408 return null; 409 } 410 } 411 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Fri Feb 23 22:16:06 2007 | par Balluche grâce à PHPXref 0.7 |