]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
WebFingerResource introduced, instead of strict Profile object
authorMikael Nordfeldth <mmn@hethane.se>
Sun, 20 Oct 2013 13:32:56 +0000 (15:32 +0200)
committerMikael Nordfeldth <mmn@hethane.se>
Sun, 20 Oct 2013 13:48:14 +0000 (15:48 +0200)
This is the beginning of getting notice URI info via WebFinger

*XrdActionLinks is renamed *WebFingerProfileLinks, check EVENTS.txt
in WebFinger plugin for new events.

12 files changed:
classes/Notice.php
plugins/OStatus/OStatusPlugin.php
plugins/OStatus/lib/discoveryhints.php
plugins/OpenID/OpenIDPlugin.php
plugins/WebFinger/EVENTS.txt
plugins/WebFinger/WebFingerPlugin.php
plugins/WebFinger/actions/webfinger.php
plugins/WebFinger/lib/webfinger.php [deleted file]
plugins/WebFinger/lib/webfingerresource.php [new file with mode: 0644]
plugins/WebFinger/lib/webfingerresource/notice.php [new file with mode: 0644]
plugins/WebFinger/lib/webfingerresource/profile.php [new file with mode: 0644]
plugins/WebFinger/lib/xrdaction.php

index 4812dff91a29b5caf70fb9e2262154fcaef43889..2de4a889fa408ad79dfef2b0871cc7afdb527640 100644 (file)
@@ -216,6 +216,12 @@ class Notice extends Managed_DataObject
         return $this->uri;
     }
 
+    public function getUrl()
+    {
+        // The risk is we start having empty urls and non-http uris...
+        return $this->url ?: $this->uri;
+    }
+
     /**
      * Extract #hashtags from this notice's content and save them to the database.
      */
index 22d51de80ae706c6051021ff8e2bd224ee63c25b..84f2a5e9cafc4457015d0ee35ad7d471b8f8ff36 100644 (file)
@@ -1314,7 +1314,7 @@ class OStatusPlugin extends Plugin
         return true;
     }
 
-    function onEndXrdActionLinks(XML_XRD $xrd, Profile $target)
+    function onEndWebFingerProfileLinks(XML_XRD $xrd, Profile $target)
     {
         $xrd->links[] = new XML_XRD_Element_Link(Discovery::UPDATESFROM,
                             common_local_url('ApiTimelineUser',
index a868e73922f1a6d5800f52096db6b00e5c6bef41..ae2d5ad618e99a18d2b036cc5265f336f9413f22 100644 (file)
@@ -26,7 +26,7 @@ class DiscoveryHints {
 
         foreach ($xrd->links as $link) {
             switch ($link->rel) {
-            case WebFinger::PROFILEPAGE:
+            case WebFingerResource::PROFILEPAGE:
                 $hints['profileurl'] = $link->href;
                 break;
             case Salmon::NS_MENTIONS:
index e48b616f4d180d5e2c1475cc437abb27652c9ae2..293eb3155a1e60fc0ab41b65f825af57ffe64bc1 100644 (file)
@@ -773,7 +773,7 @@ class OpenIDPlugin extends Plugin
      * @return boolean hook value (always true)
      */
 
-    function onEndXrdActionLinks(XML_XRD $xrd, Profile $target)
+    function onEndWebFingerProfileLinks(XML_XRD $xrd, Profile $target)
     {
         $xrd->links[] = new XML_XRD_Element_Link(
                             'http://specs.openid.net/auth/2.0/provider',
index 81641e990625ef05527d7fa2c86c06ebc292fdcb..05e2b2a0f74f2d8614328ea8b5237680ae3bfbc7 100644 (file)
@@ -4,26 +4,28 @@ StartHostMetaLinks: Start /.well-known/host-meta links
 EndHostMetaLinks: End /.well-known/host-meta links
 - &links:   array containing the links elements to be written
 
-StartWebFingerReconstruction:
+StartGetWebFingerResource: Get a WebFingerResource extended object by resource string
+- $resource String that contains the requested URI
+- &$target  WebFingerResource extended object goes here
+- $args     Array which may contains arguments such as 'rel' filtering values
+
+EndGetWebFingerResource: Last attempts getting a WebFingerResource object
+- $resource String that contains the requested URI
+- &$target  WebFingerResource extended object goes here
+- $args     Array which may contains arguments such as 'rel' filtering values
+
+StartWebFingerReconstruction: Generate an acct: uri from a Profile object
 - $profile: Profile object for which we want a WebFinger ID
 - &$acct:   String reference where reconstructed ID is stored
 
-EndWebFingerReconstruction:
+EndWebFingerReconstruction: Last attempts to generate an acct: uri from a Profile object
 - $profile: Profile object for which we want a WebFinger ID
 - &$acct:   String reference where reconstructed ID is stored
 
-StartXrdActionAliases: About to set aliases for the XRD for a user
-- $xrd:     XML_XRD object being shown
-- $target:  Profile being shown
-
-EndXrdActionAliases: Done with aliases for the XRD for a user
-- $xrd:     XML_XRD object being shown
-- $target:  Profile being shown
-
-StartXrdActionLinks: About to set links for the XRD for a profile
+StartWebFingerProfileLinks: About to set links for the resource descriptor of a profile
 - $xrd:     XML_XRD object being shown
 - $target:  Profile being shown
 
-EndXrdActionLinks: Done with links for the XRD for a profile
+EndWebFingerProfileLinks: Done with links for the resource descriptor of a profile
 - $xrd:     XML_XRD object being shown
 - $target:  Profile being shown
index 8efce27d359b8eec6873596e3bcf6da308d43ade..24200a6f36dbd9d486f0e3b2ecfa90f5bf0e66c2 100644 (file)
@@ -58,6 +58,48 @@ class WebFingerPlugin extends Plugin
         return true;
     }
 
+    public function onEndGetWebFingerResource($resource, WebFingerResource &$target=null, array $args=array())
+    {
+        $profile = null;
+        if (Discovery::isAcct($resource)) {
+            $parts = explode('@', substr(urldecode($resource), 5)); // 5 is strlen of 'acct:'
+            if (count($parts) == 2) {
+                list($nick, $domain) = $parts;
+                if ($domain === common_config('site', 'server')) {
+                    $nick = common_canonical_nickname($nick);
+                    $user = User::getKV('nickname', $nick);
+                    if (!($user instanceof User)) {
+                        throw new NoSuchUserException(array('nickname'=>$nick));
+                    }
+                    $profile = $user->getProfile();
+                } else {
+                    throw new Exception(_('Remote profiles not supported via WebFinger yet.'));
+                }
+            }
+        } else {
+            $user = User::getKV('uri', $resource);
+            if ($user instanceof User) {
+                $profile = $user->getProfile();
+            } else {
+                // try and get it by profile url
+                $profile = Profile::getKV('profileurl', $resource);
+            }
+        }
+
+        if ($profile instanceof Profile) {
+            $target = new WebFingerResource_Profile($profile);
+            return false;   // We got our target, stop handler execution
+        }
+
+        $notice = Notice::getKV('uri', $resource);
+        if ($notice instanceof Notice) {
+            $target = new WebFingerResource_Notice($notice);
+            return false;
+        }
+
+        return true;
+    }
+
     public function onStartHostMetaLinks(array &$links)
     {
         foreach (Discovery::supportedMimeTypes() as $type) {
index ff717de4009e42d73677f1c7e81bc7e455cece1a..92ab1241473d6c4709a4fb535ed04f2c5d4cdb17 100644 (file)
@@ -26,6 +26,9 @@ if (!defined('GNUSOCIAL')) { exit(1); }
  */
 class WebfingerAction extends XrdAction
 {
+    protected $resource = null; // string with the resource URI
+    protected $target   = null; // object of the WebFingerResource class
+
     protected function prepare(array $args=array())
     {
         parent::prepare($args);
@@ -33,34 +36,8 @@ class WebfingerAction extends XrdAction
         // throws exception if resource is empty
         $this->resource = Discovery::normalize($this->trimmed('resource'));
 
-        if (Discovery::isAcct($this->resource)) {
-            $parts = explode('@', substr(urldecode($this->resource), 5));
-            if (count($parts) == 2) {
-                list($nick, $domain) = $parts;
-                if ($domain === common_config('site', 'server')) {
-                    $nick = common_canonical_nickname($nick);
-                    $user = User::getKV('nickname', $nick);
-                    if (!($user instanceof User)) {
-                        throw new NoSuchUserException(array('nickname'=>$nick));
-                    }
-                    $this->target = $user->getProfile();
-                } else {
-                    throw new Exception(_('Remote profiles not supported via WebFinger yet.'));
-                }
-            }
-        } else {
-            $user = User::getKV('uri', $this->resource);
-            if ($user instanceof User) {
-                $this->target = $user->getProfile();
-            } else {
-                // try and get it by profile url
-                $this->target = Profile::getKV('profileurl', $this->resource);
-            }
-        }
-
-        if (!($this->target instanceof Profile)) {
-            // TRANS: Client error displayed when user not found for an action.
-            $this->clientError(_('No such user: ') . var_export($this->resource,true), 404);
+        if (Event::handle('StartGetWebFingerResource', array($this->resource, &$this->target, $this->args))) {
+            Event::handle('EndGetWebFingerResource', array($this->resource, &$this->target, $this->args));
         }
 
         return true;
@@ -68,55 +45,18 @@ class WebfingerAction extends XrdAction
 
     protected function setXRD()
     {
-        if (empty($this->target)) {
+        if (!($this->target instanceof WebFingerResource)) {
             throw new Exception(_('Target not set for resource descriptor'));
         }
 
-        // $this->target set in a _child_ class prepare()
-        $nick = $this->target->nickname;
-
         $this->xrd->subject = $this->resource;
 
-        if (Event::handle('StartXrdActionAliases', array($this->xrd, $this->target))) {
-            $uris = WebFinger::getIdentities($this->target);
-            foreach ($uris as $uri) {
-                if ($uri != $this->xrd->subject && !in_array($uri, $this->xrd->aliases)) {
-                    $this->xrd->aliases[] = $uri;
-                }
+        foreach ($this->target->getAliases() as $alias) {
+            if ($alias != $this->xrd->subject && !in_array($alias, $this->xrd->aliases)) {
+                $this->xrd->aliases[] = $alias;
             }
-            Event::handle('EndXrdActionAliases', array($this->xrd, $this->target));
         }
 
-        if (Event::handle('StartXrdActionLinks', array($this->xrd, $this->target))) {
-
-            $this->xrd->links[] = new XML_XRD_Element_Link(WebFinger::PROFILEPAGE,
-                                        $this->target->getUrl(), 'text/html');
-
-            // XFN
-            $this->xrd->links[] = new XML_XRD_Element_Link('http://gmpg.org/xfn/11',
-                                        $this->target->getUrl(), 'text/html');
-            // FOAF
-            $this->xrd->links[] = new XML_XRD_Element_Link('describedby',
-                                        common_local_url('foaf', array('nickname' => $nick)),
-                                        'application/rdf+xml');
-
-            $link = new XML_XRD_Element_Link('http://apinamespace.org/atom',
-                                        common_local_url('ApiAtomService', array('id' => $nick)),
-                                        'application/atomsvc+xml');
-// XML_XRD must implement changing properties first           $link['http://apinamespace.org/atom/username'] = $nick;
-            $this->xrd->links[] = clone $link;
-
-            if (common_config('site', 'fancy')) {
-                $apiRoot = common_path('api/', true);
-            } else {
-                $apiRoot = common_path('index.php/api/', true);
-            }
-
-            $link = new XML_XRD_Element_Link('http://apinamespace.org/twitter', $apiRoot);
-// XML_XRD must implement changing properties first            $link['http://apinamespace.org/twitter/username'] = $nick;
-            $this->xrd->links[] = clone $link;
-
-            Event::handle('EndXrdActionLinks', array($this->xrd, $this->target));
-        }
+        $this->target->updateXRD($this->xrd);
     }
 }
diff --git a/plugins/WebFinger/lib/webfinger.php b/plugins/WebFinger/lib/webfinger.php
deleted file mode 100644 (file)
index 2acb430..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-/**
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2010, StatusNet, Inc.
- *
- * WebFinger functions
- *
- * PHP version 5
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @package   GNUsocial
- * @author    Mikael Nordfeldth
- * @copyright 2013 Free Software Foundation, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-class WebFinger
-{
-    const PROFILEPAGE = 'http://webfinger.net/rel/profile-page';
-
-    /*
-     * Reconstructs a WebFinger ID from data we know about the profile.
-     *
-     * @param  Profile  $profile    The profile we want a WebFinger ID for
-     * 
-     * @return string   $acct       acct:user@example.com URI
-     */
-    public static function reconstruct(Profile $profile)
-    {
-        $acct = null;
-
-        if (Event::handle('StartWebFingerReconstruction', array($profile, &$acct))) {
-            // TODO: getUri may not always give us the correct host on remote users?
-            $host = parse_url($profile->getUri(), PHP_URL_HOST);
-            if (empty($profile->nickname) || empty($host)) {
-                throw new WebFingerReconstructionException($profile);
-            }
-            $acct = sprintf('acct:%s@%s', $profile->nickname, $host);
-
-            Event::handle('EndWebFingerReconstruction', array($profile, &$acct));
-        }
-
-        return $acct;
-    }
-
-    /*
-     * Gets all URI aliases for a Profile
-     *
-     * @param  Profile  $profile    The profile we want aliases for
-     * 
-     * @return array    $aliases    All the Profile's alternative URLs
-     */
-    public static function getAliases(Profile $profile)
-    {
-        $aliases = array();
-        $aliases[] = $profile->getUri();
-        try {
-            $aliases[] = $profile->getUrl();
-        } catch (InvalidUrlException $e) {
-            common_debug('Profile id='.$profile->id.' has invalid profileurl: ' .
-                            var_export($profile->profileurl, true));
-        }
-        return $aliases;
-    }
-
-    /*
-     * Gets all identities for a Profile, includes WebFinger acct: if
-     * available, as well as alias URLs.
-     *
-     * @param  Profile  $profile    The profile we want aliases for
-     * 
-     * @return array    $uris       WebFinger acct: URI and alias URLs
-     */
-    public static function getIdentities(Profile $profile)
-    {
-        $uris = array();
-        try {
-            $uris[] = self::reconstruct($profile);
-        } catch (WebFingerReconstructionException $e) {
-            common_debug('WebFinger reconstruction for Profile failed, ' .
-                            ' (id='.$profile->id.')');
-        }
-        $uris = array_merge($uris, self::getAliases($profile));
-
-        return $uris;
-    }
-}
diff --git a/plugins/WebFinger/lib/webfingerresource.php b/plugins/WebFinger/lib/webfingerresource.php
new file mode 100644 (file)
index 0000000..c9fe172
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+/**
+ * WebFinger resource parent class
+ *
+ * @package   GNUsocial
+ * @author    Mikael Nordfeldth
+ * @copyright 2013 Free Software Foundation, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+abstract class WebFingerResource
+{
+    const PROFILEPAGE = 'http://webfinger.net/rel/profile-page';
+
+    protected $identities = array();
+
+    protected $object = null;
+    protected $type   = null;
+
+    public function __construct(Managed_DataObject $object)
+    {
+        $this->object = $object;
+    }
+
+    public function getObject()
+    {
+        if ($this->object === null) {
+            throw new ServerException('Object is not set');
+        }
+        return $this->object;
+    }
+
+    public function getAliases()
+    {
+        $aliases = array();
+
+        // Add the URI as an identity, this is _not_ necessarily an HTTP url
+        $aliases[] = $this->object->getUri();
+
+        try {
+            $aliases[] = $this->object->getUrl();
+        } catch (InvalidUrlException $e) {
+            // getUrl failed because no valid URL could be returned, just ignore it
+        }
+
+        return $aliases;
+    }
+
+    public function updateXRD(XML_XRD $xrd) {
+        $xrd->links[] = new XML_XRD_Element_Link(WebFingerResource::PROFILEPAGE,
+                                        $this->object->getUrl(), 'text/html');
+    }
+}
diff --git a/plugins/WebFinger/lib/webfingerresource/notice.php b/plugins/WebFinger/lib/webfingerresource/notice.php
new file mode 100644 (file)
index 0000000..9510a69
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+/**
+ * WebFinger resource for Notice objects
+ *
+ * @package   GNUsocial
+ * @author    Mikael Nordfeldth
+ * @copyright 2013 Free Software Foundation, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class WebFingerResource_Notice extends WebFingerResource
+{
+    public function __construct(Notice $object)
+    {
+        // The type argument above verifies that it's our class
+        parent::__construct($object);
+    }
+
+    public function updateXRD(XML_XRD $xrd)
+    {
+        parent::updateXRD($xrd);
+
+        // TODO: Add atom and json representation links here
+        // TODO: Add Salmon/callback links and stuff here
+    }
+}
diff --git a/plugins/WebFinger/lib/webfingerresource/profile.php b/plugins/WebFinger/lib/webfingerresource/profile.php
new file mode 100644 (file)
index 0000000..03dd84e
--- /dev/null
@@ -0,0 +1,87 @@
+<?php
+/**
+ * WebFinger resource for Profile objects
+ *
+ * @package   GNUsocial
+ * @author    Mikael Nordfeldth
+ * @copyright 2013 Free Software Foundation, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class WebFingerResource_Profile extends WebFingerResource
+{
+    public function __construct(Profile $object)
+    {
+        // The type argument above verifies that it's our class
+        parent::__construct($object);
+    }
+
+    public function getAliases()
+    {
+        $aliases = array();
+
+        try {
+            // Try to create an acct: URI if we're dealing with a profile
+            $aliases[] = $this->reconstructAcct();
+        } catch (WebFingerReconstructionException $e) {
+            common_debug("WebFinger reconstruction for Profile failed (id={$this->object->id})");
+        }
+
+        return array_merge($aliases, parent::getAliases());
+    }
+
+    protected function reconstructAcct()
+    {
+        $acct = null;
+
+        if (Event::handle('StartWebFingerReconstruction', array($this->object, &$acct))) {
+            // TODO: getUri may not always give us the correct host on remote users?
+            $host = parse_url($this->object->getUri(), PHP_URL_HOST);
+            if (empty($this->object->nickname) || empty($host)) {
+                throw new WebFingerReconstructionException($this->object);
+            }
+            $acct = sprintf('acct:%s@%s', $this->object->nickname, $host);
+
+            Event::handle('EndWebFingerReconstruction', array($this->object, &$acct));
+        }
+
+        return $acct;
+    }
+
+    public function updateXRD(XML_XRD $xrd)
+    {
+        if (Event::handle('StartWebFingerProfileLinks', array($xrd, $this->object))) {
+
+            parent::updateXRD($xrd);
+
+            // XFN
+            $xrd->links[] = new XML_XRD_Element_Link('http://gmpg.org/xfn/11',
+                                        $this->object->getUrl(), 'text/html');
+            // FOAF
+            $xrd->links[] = new XML_XRD_Element_Link('describedby',
+                                        common_local_url('foaf',
+                                                        array('nickname' => $this->object->nickname)),
+                                                                'application/rdf+xml');
+
+            $link = new XML_XRD_Element_Link('http://apinamespace.org/atom',
+                                        common_local_url('ApiAtomService',
+                                                        array('id' => $this->object->nickname)),
+                                                                'application/atomsvc+xml');
+// XML_XRD must implement changing properties first           $link['http://apinamespace.org/atom/username'] = $this->object->nickname;
+            $xrd->links[] = clone $link;
+
+            if (common_config('site', 'fancy')) {
+                $apiRoot = common_path('api/', true);
+            } else {
+                $apiRoot = common_path('index.php/api/', true);
+            }
+
+            $link = new XML_XRD_Element_Link('http://apinamespace.org/twitter', $apiRoot);
+// XML_XRD must implement changing properties first            $link['http://apinamespace.org/twitter/username'] = $this->object->nickname;
+            $xrd->links[] = clone $link;
+
+            Event::handle('EndWebFingerProfileLinks', array($xrd, $this->object));
+        }
+    }
+}
index 5089ad44e0280e7ac1c1933d81634cb3571abda7..a57ccdb382a14ae55dde8c1e88fd28af63b1fa9d 100644 (file)
@@ -31,8 +31,6 @@ abstract class XrdAction extends Action
     // our back-compatibility with StatusNet <=1.1.1
     protected $defaultformat = null;
 
-    protected $resource = null;
-    protected $target   = null;
     protected $xrd      = null;
 
     public function isReadOnly($args)