Dotclear


Ignore:
Timestamp:
09/01/13 03:16:29 (12 years ago)
Author:
Florent Cotton <florent.cotton@…>
Branch:
pingbacks
Children:
1675:23613441b822, 1676:ae97601883d2
Message:

Support des pingbacks : après le support de la détection et de l'envoi de pingbacks, au tour du support en réception.
Dans le détail (ou presque) :

  • Ajout d'un endpoint "pingback.ping" XML-RPC, mais le tout le gros du traitement est dans le fichier class.dc.trackback.php
  • Ajout d'une méthode "receive_pb" dans la classe dcTrackback pour la prise en charge quasi-complète de la réception et enregistrement d'un pingback.
  • Ajout d'une balise template {{tpl:BlogXMLRPCURL}} pour retourner l'URL du serveur XML-RPC du blog courant
  • Ajout d'un bloc au niveau des en-têtes dans les templates par défaut post.html et page.html pour la mise en oeuvre si besoin d'un <link rel="pingback" ../>
  • Ajout de l'envoi d'un en-tête HTTP supplémentaire "X-Pingback" dans les gestionnaires d'URLs pour les types "post" et "pages"

Reste plus qu'à tester en conditions réelles et à polir au besoin.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • inc/core/class.dc.trackback.php

    r1673 r1674  
    309309     } 
    310310     //@} 
     311 
     312     /// @name Receive pingbacks 
     313     //@{ 
     314     /** 
     315     Receives a pingback and insert it as a comment of given post. 
     316      
     317     @param    from_url       <b>string</b>       Source URL 
     318     @param    to_url              <b>string</b>       Target URL 
     319     */ 
     320     public function receive_pb($from_url, $to_url) 
     321     { 
     322          $reg = '!^'.preg_quote($this->core->blog->url).'(.*)!'; 
     323          $type = $args = $next = ''; 
     324           
     325          # Are you dumb? 
     326          if (!preg_match($reg, $to_url, $m)) { 
     327               throw new Exception(__('Any chance you ping one of my contents? No? Really?'), 0); 
     328          } 
     329           
     330          # Does the targeted URL look like a registered post type?  
     331          $url_part = $m[1]; 
     332          $p_type = ''; 
     333          $post_types = $this->core->getPostTypes(); 
     334          foreach ($post_types as $k => $v) { 
     335               $reg = '!^'.preg_quote(str_replace('%s', '', $v['public_url'])).'(.*)!'; 
     336               if (preg_match($reg, $url_part, $n)) { 
     337                    $p_type = $k; 
     338                    $post_url = $n[1]; 
     339                    break; 
     340               } 
     341          } 
     342           
     343          if (empty($p_type)) { 
     344               throw new Exception(__('Sorry but you can not ping this type of content.'), 33); 
     345          } 
     346 
     347          # Time to see if we've got a winner... 
     348          $params = array( 
     349               'post_type' => $p_type, 
     350               'post_url' => $post_url, 
     351          ); 
     352          $posts = $this->core->blog->getPosts($params); 
     353           
     354          # Missed!  
     355          if ($posts->isEmpty()) { 
     356               throw new Exception(__('Oops. Kinda "not found" stuff. Please check the target URL twice.'), 33); 
     357          } 
     358           
     359          # Nice try. But, sorry, no. 
     360          if (!$posts->trackbacksActive()) { 
     361               throw new Exception(__('Sorry, dude. This entry does not accept pingback at the moment.'), 33); 
     362          } 
     363 
     364          # OK. We've found our champion. Time to check the remote part. 
     365          try { 
     366               $http = self::initHttp($from_url, $from_path); 
     367                
     368               # First round : just to be sure the ping comes from an acceptable resource type. 
     369               $http->setHeadersOnly(true); 
     370               $http->get($from_path); 
     371               $c_type = explode(';', $http->getHeader('content-type')); 
     372 
     373               # Bad luck. Bye, bye... 
     374               if (!in_array($c_type[0],array('text/html', 'application/xhtml+xml'))) { 
     375                    throw new Exception(__('Your source URL does not look like a supported content type. Sorry. Bye, bye!'), 0); 
     376               } 
     377                
     378               # Second round : let's go fetch and parse the remote content 
     379               $http->setHeadersOnly(false); 
     380               $http->get($from_path); 
     381               $remote_content = $http->getContent(); 
     382 
     383               $charset = mb_detect_encoding($remote_content, 
     384                    'UTF-8,ISO-8859-1,ISO-8859-2,ISO-8859-3,'. 
     385                    'ISO-8859-4,ISO-8859-5,ISO-8859-6,ISO-8859-7,ISO-8859-8,'. 
     386                    'ISO-8859-9,ISO-8859-10,ISO-8859-13,ISO-8859-14,ISO-8859-15'); 
     387 
     388               if (strtolower($charset) != 'utf-8') { 
     389                    $remote_content = iconv($charset,'UTF-8',$remote_content); 
     390               } 
     391                
     392               # We want a title... 
     393               if (!preg_match('!<title>([^<].*?)</title>!mis', $remote_content, $m)) { 
     394                    throw new Exception(__('Where\'s your title?'), 0); 
     395               } 
     396               $title = trim(html::clean($m[1])); 
     397               $title = html::decodeEntities($title); 
     398               $title = html::escapeHTML($title); 
     399               $title = text::cutString($title,60); 
     400                
     401               preg_match('!<body[^>]*?>(.*)?</body>!msi', $remote_content, $m); 
     402               $source = $m[1]; 
     403               $source = preg_replace('![\r\n\s]+!ms',' ',$source); 
     404               $source = preg_replace( "/<\/*(h\d|p|th|td|li|dt|dd|pre|caption|input|textarea|button)[^>]*>/", "\n\n", $source ); 
     405               $source = strip_tags($source, '<a>'); 
     406               $source = explode("\n\n",$source); 
     407                
     408               $excerpt = ''; 
     409               foreach ($source as $line) { 
     410                    if (strpos($line, $to_url) !== false) { 
     411                         if (preg_match("!<a[^>]+?".$to_url."[^>]*>([^>]+?)</a>!", $line, $m)) { 
     412                              $excerpt = strip_tags($line); 
     413                              break; 
     414                         } 
     415                    } 
     416               } 
     417               if ($excerpt) { 
     418                    $excerpt = '(&#8230;) '.text::cutString(html::escapeHTML($excerpt),255).' (&#8230;)'; 
     419               } 
     420               else { 
     421                    $excerpt = '(??)'; 
     422               } 
     423 
     424               $comment = 
     425               "<!-- TB -->\n". 
     426               '<p><strong>'.$title."</strong></p>\n". 
     427               '<p>'.$excerpt.'</p>'; 
     428                
     429               $cur = $this->core->con->openCursor($this->core->prefix.'comment'); 
     430               $cur->comment_author = 'Anonymous blog'; 
     431               $cur->comment_site = (string) $from_url; 
     432               $cur->comment_content = (string) $comment; 
     433               $cur->post_id = $posts->post_id; 
     434               $cur->comment_trackback = 1; 
     435               $cur->comment_status = $this->core->blog->settings->system->trackbacks_pub ? 1 : -1; 
     436               $cur->comment_ip = http::realIP(); 
     437                
     438               # --BEHAVIOR-- publicBeforeTrackbackCreate 
     439               $this->core->callBehavior('publicBeforeTrackbackCreate',$cur); 
     440               if ($cur->post_id) { 
     441                    $comment_id = $this->core->blog->addComment($cur); 
     442                     
     443                    # --BEHAVIOR-- publicAfterTrackbackCreate 
     444                    $this->core->callBehavior('publicAfterTrackbackCreate',$cur,$comment_id); 
     445               } 
     446          } 
     447          catch (Exception $e) { 
     448               throw new Exception(__('Sorry, an internal problem has occured.'), 0); 
     449          } 
     450           
     451          return __('Thanks, mate. It was a pleasure.'); 
     452     } 
     453     //@} 
    311454      
    312455     private static function initHttp($url,&$path) 
Note: See TracChangeset for help on using the changeset viewer.

Sites map