/** * 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); }