From c97142ad3edea1652f39e7fb58c8c3443f8a0f67 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 8 Mar 2009 11:50:55 -0700 Subject: [PATCH] first version of plugin for pingback and trackback (no trackback yet) --- plugins/LinkbackPlugin.php | 140 +++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 plugins/LinkbackPlugin.php diff --git a/plugins/LinkbackPlugin.php b/plugins/LinkbackPlugin.php new file mode 100644 index 0000000000..77adfa87d1 --- /dev/null +++ b/plugins/LinkbackPlugin.php @@ -0,0 +1,140 @@ +. + * + * @category Plugin + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +require_once('Auth/Yadis/Yadis.php'); + +define('LINKBACKPLUGIN_VERSION', '0.1'); + +/** + * Plugin to do linkbacks for notices containing URLs + * + * After new notices are saved, we check their text for URLs. If there + * are URLs, we test each URL to see if it supports any + * + * @category Plugin + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + * + * @see Event + */ + +class LinkbackPlugin extends Plugin +{ + var $notice = null; + + function __construct() + { + parent::__construct(); + } + + function onEndNoticeSave($notice) + { + if ($notice->is_local == 1) { + // Try to avoid actually mucking with the + // notice content + $c = $notice->content; + $this->notice = $notice; + // Ignoring results + common_replace_urls_callback($c, + array($this, 'linkbackUrl')); + } + return true; + } + + function linkbackUrl($url) + { + $orig = $url; + $url = htmlspecialchars_decode($orig); + $scheme = parse_url($url, PHP_URL_SCHEME); + if (!in_array($scheme, array('http', 'https'))) { + return $orig; + } + + // XXX: Do a HEAD first to save some time/bandwidth + + $fetcher = Auth_Yadis_Yadis::getHTTPFetcher(); + + $result = $fetcher->get($url, + array('User-Agent: ' . $this->userAgent(), + 'Accept: application/html+xml,text/html')); + + if (!in_array($result->status, array('200', '206'))) { + return $orig; + } + + if (array_key_exists('X-Pingback', $result->headers)) { + $endpoint = $result->headers['X-Pingback']; + } else if (preg_match('//', + $result->body, + $match)) { + $endpoint = $match[1]; + } else { + // XXX: do Trackback lookup + return $orig; + } + + $this->pingback($url, $endpoint); + return $orig; + } + + function pingback($url, $endpoint) + { + $args = array($this->notice->uri, $url); + + $request = xmlrpc_encode_request('pingback.ping', $args); + $context = stream_context_create(array('http' => array('method' => "POST", + 'header' => + "Content-Type: text/xml\r\n". + "User-Agent: " . $this->userAgent(), + 'content' => $request))); + $file = file_get_contents($endpoint, false, $context); + $response = xmlrpc_decode($file); + if (xmlrpc_is_fault($response)) { + common_log(LOG_WARNING, + "Pingback error for '$url' ($endpoint): ". + "$response[faultString] ($response[faultCode])"); + } else { + common_log(LOG_INFO, + "Pingback success for '$url' ($endpoint): ". + "'$response'"); + } + } + + function userAgent() + { + return 'LinkbackPlugin/'.LINKBACKPLUGIN_VERSION . + ' Laconica/' . LACONICA_VERSION; + } +}