Exemplo n.º 1
0
Arquivo: links.php Projeto: rair/yacs
 /**
  * ping back links referenced in some text
  *
  * This is the client implementation of
  * [link=trackback]http://www.movabletype.org/docs/mttrackback.html[/link]
  * and [link=pingback]http://www.hixie.ch/specs/pingback/pingback[/link] specifications.
  *
  * This function is triggered by publishing scripts, either [script]articles/publish.php[/script],
  * [script]services/blog.php[/script], [script]agents/messages.php[/script] or [script]agents/uploads.php[/script].
  *
  * @see articles/publish.php
  * @see services/blog.php
  * @see agents/messages.php
  * @see agents/uploads.php
  *
  * It is used to efficiently link pages across a set of web sites according to the following mechanism:
  * - The list of external links is built for this page
  * - Only the 7 first links are kept from the list; others are stripped
  * - If links do not exist, create additional records in the table used for links
  * - Each link (actually, only the 7 most recent) is checked, to see if it's trackback- or pingback-enabled or not
  * - Each trackback-/pingback-enabled link is activated, providing the full URL of the anchor page
  *
  * We are claiming to support most of the trackback client interface here, as described in the [link=trackback]http://www.movabletype.org/docs/mttrackback.html[/link] specification.
  * A foreign page is considered as being trackback-enabled if it has a special RDF section
  * linking its reference (i.e., URL) to a Trackback Ping URL.
  *
  * Note that YACS also implements the server part of the trackback specification in [script]links/trackback.php[/script],
  * which supports POST REST calls.
  *
  * @see links/trackback.php
  *
  * We are claiming to fully support the pingback client interface here, as described in the [link=pingback]http://www.hixie.ch/specs/pingback/pingback[/link] specification.
  * A foreign page is considered to be pingback-enabled if it has a meta link to a Pingback Ping URL.
  *
  * Note that YACS also implements the server part of the pingback specification in [script]services/ping.php[/script],
  * which supports XML-RPC calls.
  *
  * @see services/ping.php
  *
  * This function transforms every YACS codes into HTML before extracting links,
  * and before submitting the excerpt to remote site.
  *
  * @param string the referencing text that has to be scanned
  * @param string the local anchor of the referencing text (e.g., 'article:124')
  * @return array list($links, $advertised, $skipped)
  *
  * @link http://www.movabletype.org/docs/mttrackback.html TrackBack Technical Specification
  * @link http://www.hixie.ch/specs/pingback/pingback Pingback specification
  */
 public static function ping($text, $anchor)
 {
     global $context;
     // render all codes
     if (is_callable(array('Codes', 'beautify'))) {
         $text = Codes::beautify($text);
     }
     // suppress all links not coming from anchors (eg, <img src=...)
     $text = strip_tags($text, '<a>');
     // extract all links from the text, including those that have been encoded by YACS
     preg_match_all('/((http:\\/\\/|http%3A%2F%2F)[^ <"]+)/i', $text, $links);
     // nothing to do
     if (!@count($links[1])) {
         return;
     }
     // process each link only once
     $unique_links = array();
     foreach ($links[1] as $url) {
         // decode raw url encoding, if any
         $url = rawurldecode($url);
         // strip the clicking indirection, if any
         $url = rawurldecode(preg_replace('/^' . preg_quote($context['url_to_home'] . $context['url_to_root'] . 'links/click.php?url=', '/') . '/i', '', $url));
         $unique_links[$url] = 1;
     }
     // analyze found links
     $links_processed = array();
     $links_advertised = array();
     $links_skipped = array();
     foreach ($unique_links as $url => $dummy) {
         // analyze no more than 7 links
         if (@count($links_processed) >= 7) {
             break;
         }
         // skip links that point to ourself, and not to an article
         if (preg_match('/^' . preg_quote($context['url_to_home'], '/') . '\\b/i', $url) && !preg_match('/\\/article(-|s\\/view.php)/i', $url)) {
             $links_skipped[] = $url;
             continue;
         }
         // skip invalid links
         if (($content = http::proceed($url)) === FALSE) {
             $links_skipped[] = $url;
             continue;
         }
         // we will use the content to locate pingback and trackback interfaces
         $pages[$url] = $content;
         // ensure enough execution time
         Safe::set_time_limit(30);
         // stats
         $links_processed[] = $url;
     }
     // locate the anchor object for this text, we need its url
     $anchor = Anchors::get($anchor);
     if (!is_object($anchor)) {
         return;
     }
     // build an excerpt from anchor
     $excerpt = $anchor->get_teaser('basic');
     // find blog name for anchor
     if ($parent = $anchor->get_value('anchor')) {
         $blog = Anchors::get($parent);
         if (is_object($blog)) {
             $blog_name = $blog->get_title();
         }
     }
     // build an absolute URL for the source
     $source = $context['url_to_home'] . $context['url_to_root'] . $anchor->get_url();
     // process each link
     if (@count($pages)) {
         foreach ($pages as $target => $content) {
             // try trackback, if implemented
             if (Links::ping_as_trackback($content, $source, $target, $anchor->get_title(), $excerpt, $blog_name)) {
                 $links_advertised[] = $target;
             } elseif (Links::ping_as_pingback($content, $source, $target)) {
                 $links_advertised[] = $target;
             }
         }
     }
     return array($links_processed, $links_advertised, $links_skipped);
 }