Dotclear

Changeset 1674:00146501e490


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.

Files:
7 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) 
  • inc/core/class.dc.xmlrpc.php

    r1179 r1674  
    214214               array('array','integer','string','string'), 
    215215               'Retrieve all of the comment statuses.'); 
     216                
     217          # Pingback support 
     218          $this->addCallback('pingback.ping',array($this,'pingback_ping'), 
     219               array('string', 'string', 'string'), 
     220               'Notify a link to a post.'); 
    216221     } 
    217222      
     
    270275     } 
    271276      
    272      private function setBlog() 
     277     private function setBlog($bypass = false) 
    273278     { 
    274279          if (!$this->blog_id) { 
     
    288293          } 
    289294           
    290           if (!$this->core->blog->settings->system->enable_xmlrpc || 
    291           !$this->core->auth->check('usage,contentadmin',$this->core->blog->id)) { 
     295          if (!$bypass && 
     296               (!$this->core->blog->settings->system->enable_xmlrpc || 
     297               !$this->core->auth->check('usage,contentadmin',$this->core->blog->id))) { 
    292298               $this->core->blog = null; 
    293299               throw new Exception('Not enough permissions on this blog.'); 
     
    16291635          ); 
    16301636     } 
     1637 
     1638     /* Pingback support 
     1639     --------------------------------------------------- */ 
     1640     public function pingback_ping($from_url, $to_url) 
     1641     { 
     1642          # Come on, buddy! Don't make me waste time with this kind of silliness... 
     1643          if (!(filter_var($from_url, FILTER_VALIDATE_URL) && preg_match('!^https?://!',$from_url))) { 
     1644               throw new Exception(__('No valid source URL provided? Try again!'), 0); 
     1645          } 
     1646           
     1647          $this->setBlog(true); 
     1648          $tb = new dcTrackback($this->core); 
     1649          return $tb->receive_pb($from_url, $to_url); 
     1650     } 
    16311651} 
    16321652?> 
  • inc/public/class.dc.template.php

    r1611 r1674  
    7070          $this->addValue('BlogID',array($this,'BlogID')); 
    7171          $this->addValue('BlogURL',array($this,'BlogURL')); 
     72          $this->addValue('BlogXMLRPCURL',array($this,'BlogXMLRPCURL')); 
    7273          $this->addValue('BlogPublicURL',array($this,'BlogPublicURL')); 
    7374          $this->addValue('BlogQmarkURL',array($this,'BlogQmarkURL')); 
     
    906907      
    907908     /*dtd 
     909     <!ELEMENT tpl:BlogXMLRPCURL - O -- Blog XML-RPC URL --> 
     910     */ 
     911     public function BlogXMLRPCURL($attr) 
     912     { 
     913          $f = $this->getFilters($attr); 
     914          return '<?php echo '.sprintf($f,'$core->blog->url.$core->url->getURLFor(\'xmlrpc\',$core->blog->id)').'; ?>'; 
     915     } 
     916      
     917     /*dtd 
    908918     <!ELEMENT tpl:BlogURL - O -- Blog URL --> 
    909919     */ 
  • inc/public/default-templates/post.html

    r932 r1674  
    2525  <link rel="top" href="{{tpl:BlogURL}}" title="{{tpl:lang Home}}" /> 
    2626  <link rel="contents" href="{{tpl:BlogArchiveURL}}" title="{{tpl:lang Archives}}" /> 
     27  <tpl:EntryIf pings_active="1"><link rel="pingback" href="{{tpl:BlogXMLRPCURL}}" /></tpl:EntryIf> 
    2728   
    2829  <tpl:EntryNext><link rel="next" href="{{tpl:EntryURL}}" 
  • inc/public/lib.urlhandlers.php

    r1610 r1674  
    480480                     
    481481                    # The entry 
     482                    if ($_ctx->posts->trackbacksActive()) { 
     483                         header('X-Pingback: '.$core->blog->url.$core->url->getURLFor("xmlrpc",$core->blog->id)); 
     484                    } 
    482485                    self::serveDocument('post.html'); 
    483486               } 
  • plugins/pages/_public.php

    r1179 r1674  
    181181                     
    182182                    # The entry 
     183                    if ($_ctx->posts->trackbacksActive()) { 
     184                         header('X-Pingback: '.$core->blog->url.$core->url->getURLFor("xmlrpc",$core->blog->id)); 
     185                    } 
    183186                    $core->tpl->setPath($core->tpl->getPath(), dirname(__FILE__).'/default-templates'); 
    184187                    self::serveDocument('page.html'); 
  • plugins/pages/default-templates/page.html

    r725 r1674  
    2525  <link rel="top" href="{{tpl:BlogURL}}" title="{{tpl:lang Home}}" /> 
    2626  <link rel="contents" href="{{tpl:BlogArchiveURL}}" title="{{tpl:lang Archives}}" /> 
     27  <tpl:EntryIf pings_active="1"><link rel="pingback" href="{{tpl:BlogXMLRPCURL}}" /></tpl:EntryIf> 
    2728   
    2829  <link rel="alternate" type="application/atom+xml" title="Atom 1.0" href="{{tpl:BlogFeedURL type="atom"}}" /> 
Note: See TracChangeset for help on using the changeset viewer.

Sites map