From 3b1792c8b5066a28c5d64b903c63419d3e238ff1 Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Wed, 14 Oct 2015 16:13:58 -0500 Subject: [PATCH] Add webmention support --- plugins/Linkback/LinkbackPlugin.php | 64 ++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/plugins/Linkback/LinkbackPlugin.php b/plugins/Linkback/LinkbackPlugin.php index 84215046fa..045fc2f4f7 100644 --- a/plugins/Linkback/LinkbackPlugin.php +++ b/plugins/Linkback/LinkbackPlugin.php @@ -103,21 +103,73 @@ class LinkbackPlugin extends Plugin return $orig; } - $pb = $this->getPingback($result); - if (!empty($pb)) { - $this->pingback($result->final_url, $pb); // XXX: Should handle relative-URI resolution in these detections + $wm = $this->getWebmention($result); + if(!empty($wm)) { + $this->webmention($result->final_url, $wm); } else { - $tb = $this->getTrackback($result); - if (!empty($tb)) { - $this->trackback($result->final_url, $tb); + $pb = $this->getPingback($result); + if (!empty($pb)) { + $this->pingback($result->final_url, $pb); + } else { + $tb = $this->getTrackback($result); + if (!empty($tb)) { + $this->trackback($result->final_url, $tb); + } } } return $orig; } + // Based on https://github.com/indieweb/mention-client-php + // which is licensed Apache 2.0 + function getWebmention($result) { + // XXX: the fetcher only gives back one of each header, so this may fail on multiple Link headers + if(preg_match('~<((?:https?://)?[^>]+)>; rel="webmention"~', $result->headers['Link'], $match)) { + return $match[1]; + } elseif(preg_match('~<((?:https?://)?[^>]+)>; rel="http://webmention.org/?"~', $result->headers['Link'], $match)) { + return $match[1]; + } + + if(preg_match('/<(?:link|a)[ ]+href="([^"]+)"[ ]+rel="[^" ]* ?webmention ?[^" ]*"[ ]*\/?>/i', $result->body, $match) + || preg_match('/<(?:link|a)[ ]+rel="[^" ]* ?webmention ?[^" ]*"[ ]+href="([^"]+)"[ ]*\/?>/i', $result->body, $match)) { + return $match[1]; + } elseif(preg_match('/<(?:link|a)[ ]+href="([^"]+)"[ ]+rel="http:\/\/webmention\.org\/?"[ ]*\/?>/i', $result->body, $match) + || preg_match('/<(?:link|a)[ ]+rel="http:\/\/webmention\.org\/?"[ ]+href="([^"]+)"[ ]*\/?>/i', $result->body, $match)) { + return $match[1]; + } + } + + function webmention($url, $endpoint) { + $source = $this->notice->getUrl(); + + $payload = array( + 'source' => $source, + 'target' => $url + ); + + $request = HTTPClient::start(); + try { + $response = $request->post($endpoint, + array( + 'Content-type: application/x-www-form-urlencoded', + 'Accept: application/json' + ), + $payload + ); + + if(!in_array($response->getStatus(), array(200,202))) { + common_log(LOG_WARNING, + "Webmention request failed for '$url' ($endpoint)"); + } + } catch (HTTP_Request2_Exception $e) { + common_log(LOG_WARNING, + "Webmention request failed for '$url' ($endpoint)"); + } + } + function getPingback($result) { if (array_key_exists('X-Pingback', $result->headers)) { return $result->headers['X-Pingback'];