]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - plugins/OStatus/lib/discoveryhints.php
Don't accept non-objects before testing with "instanceof".
[quix0rs-gnu-social.git] / plugins / OStatus / lib / discoveryhints.php
index 4da2ec0f1e7cf375c95f1e9eff56bb2ded9efe99..4df7690038f6741347b13766c06175a213ae54c6 100644 (file)
  */
 
 class DiscoveryHints {
-
-    static function fromXRD($xrd)
+    static function fromXRD(XML_XRD $xrd)
     {
         $hints = array();
 
-        foreach ($xrd->links as $link) {
-            switch ($link['rel']) {
-            case Discovery::PROFILEPAGE:
-                $hints['profileurl'] = $link['href'];
-                break;
-            case Salmon::NS_REPLIES:
-                $hints['salmon'] = $link['href'];
-                break;
-            case Discovery::UPDATESFROM:
-                $hints['feedurl'] = $link['href'];
-                break;
-            case Discovery::HCARD:
-                $hints['hcardurl'] = $link['href'];
-                break;
-            default:
-                break;
+        if (Event::handle('StartDiscoveryHintsFromXRD', array($xrd, &$hints))) {
+            foreach ($xrd->links as $link) {
+                switch ($link->rel) {
+                case WebFingerResource_Profile::PROFILEPAGE:
+                    $hints['profileurl'] = $link->href;
+                    break;
+                case Salmon::REL_SALMON:
+                case Salmon::NS_MENTIONS:   // XXX: deprecated, remove in the future
+                case Salmon::NS_REPLIES:    // XXX: deprecated, remove in the future
+                    $hints['salmon'] = $link->href;
+                    break;
+                case Discovery::UPDATESFROM:
+                    if (empty($link->type) || $link->type == 'application/atom+xml') {
+                        $hints['feedurl'] = $link->href;
+                    }
+                    break;
+                case Discovery::HCARD:
+                case Discovery::MF2_HCARD:
+                    $hints['hcard'] = $link->href;
+                    break;
+                default:
+                    break;
+                }
             }
+            Event::handle('EndDiscoveryHintsFromXRD', array($xrd, &$hints));
         }
 
         return $hints;
@@ -63,147 +70,73 @@ class DiscoveryHints {
 
     static function hcardHints($body, $url)
     {
-        common_debug("starting tidy");
-
-        $body = self::_tidy($body, $url);
-
-        common_debug("done with tidy");
-
-        set_include_path(get_include_path() . PATH_SEPARATOR . INSTALLDIR . '/plugins/OStatus/extlib/hkit/');
-        require_once('hkit.class.php');
-
-        // hKit code is not clean for notices and warnings
-        $old = error_reporting();
-        error_reporting($old & ~E_NOTICE & ~E_WARNING);
-
-        $h     = new hKit;
-        $hcards = $h->getByString('hcard', $body);
+        $hcard = self::_hcard($body, $url);
 
-        error_reporting($old);
-
-        if (empty($hcards)) {
+        if (empty($hcard)) {
             return array();
         }
 
-        if (count($hcards) == 1) {
-            $hcard = $hcards[0];
-        } else {
-            foreach ($hcards as $try) {
-                if (array_key_exists('url', $try)) {
-                    if (is_string($try['url']) && $try['url'] == $url) {
-                        $hcard = $try;
-                        break;
-                    } else if (is_array($try['url'])) {
-                        foreach ($try['url'] as $tryurl) {
-                            if ($tryurl == $url) {
-                                $hcard = $try;
-                                break 2;
-                            }
-                        }
-                    }
-                }
-            }
-            // last chance; grab the first one
-            if (empty($hcard)) {
-                $hcard = $hcards[0];
-            }
-        }
-
         $hints = array();
 
-        if (array_key_exists('nickname', $hcard)) {
-            $hints['nickname'] = $hcard['nickname'];
+        // XXX: don't copy stuff into an array and then copy it again
+
+        if (array_key_exists('nickname', $hcard) && !empty($hcard['nickname'][0])) {
+            $hints['nickname'] = $hcard['nickname'][0];
         }
 
-        if (array_key_exists('fn', $hcard)) {
-            $hints['fullname'] = $hcard['fn'];
-        } else if (array_key_exists('n', $hcard)) {
-            $hints['fullname'] = implode(' ', $hcard['n']);
+        if (array_key_exists('name', $hcard) && !empty($hcard['name'][0])) {
+            $hints['fullname'] = $hcard['name'][0];
         }
 
-        if (array_key_exists('photo', $hcard)) {
-            $hints['avatar'] = $hcard['photo'];
+        if (array_key_exists('photo', $hcard) && count($hcard['photo'])) {
+            $hints['avatar'] = $hcard['photo'][0];
         }
 
-        if (array_key_exists('note', $hcard)) {
-            $hints['bio'] = $hcard['note'];
+        if (array_key_exists('note', $hcard) && !empty($hcard['note'][0])) {
+            $hints['bio'] = $hcard['note'][0];
         }
 
-        if (array_key_exists('adr', $hcard)) {
-            if (is_string($hcard['adr'])) {
-                $hints['location'] = $hcard['adr'];
-            } else if (is_array($hcard['adr'])) {
-                $hints['location'] = implode(' ', $hcard['adr']);
-            }
+        if (array_key_exists('adr', $hcard) && !empty($hcard['adr'][0])) {
+            $hints['location'] = $hcard['adr'][0]['value'];
         }
 
-        if (array_key_exists('url', $hcard)) {
-            if (is_string($hcard['url'])) {
-                $hints['homepage'] = $hcard['url'];
-            } else if (is_array($hcard['url'])) {
-                // HACK get the last one; that's how our hcards look
-                $hints['homepage'] = $hcard['url'][count($hcard['url'])-1];
-            }
+        if (array_key_exists('url', $hcard) && !empty($hcard['url'][0])) {
+            $hints['homepage'] = $hcard['url'][0];
         }
 
         return $hints;
     }
 
-    /**
-     * hKit needs well-formed XML for its parsing.
-     * We'll take the HTML body here and normalize it to XML.
-     *
-     * @param string $body HTML document source, possibly not-well-formed
-     * @param string $url source URL
-     * @return string well-formed XML document source
-     * @throws Exception if HTML parsing failed.
-     */
-    private static function _tidy($body, $url)
+    static function _hcard($body, $url)
     {
-        if (empty($body)) {
-            throw new Exception("Empty HTML could not be parsed.");
+        $mf2 = new Mf2\Parser($body, $url);
+        $mf2 = $mf2->parse();
+        
+        if (empty($mf2['items'])) {
+            return null;
         }
-        $dom = new DOMDocument();
 
-        // Some HTML errors will trigger warnings, but still work.
-        $old = error_reporting();
-        error_reporting($old & ~E_WARNING);
-        
-        $ok = $dom->loadHTML($body);
+        $hcards = array();
 
-        error_reporting($old);
-        
-        if ($ok) {
-            // hKit doesn't give us a chance to pass the source URL for
-            // resolving relative links, such as the avatar photo on a
-            // Google profile. We'll slip it into a <base> tag if there's
-            // not already one present.
-            $bases = $dom->getElementsByTagName('base');
-            if ($bases && $bases->length >= 1) {
-                $base = $bases->item(0);
-                if ($base->hasAttribute('href')) {
-                    $base->setAttribute('href', $url);
-                }
-            } else {
-                $base = $dom->createElement('base');
-                $base->setAttribute('href', $url);
-                $heads = $dom->getElementsByTagName('head');
-                if ($heads || $heads->length) {
-                    $head = $heads->item(0);
-                } else {
-                    $head = $dom->createElement('head');
-                    $root = $dom->documentRoot;
-                    if ($root->firstChild) {
-                        $root->insertBefore($head, $root->firstChild);
-                    } else {
-                        $root->appendChild($head);
-                    }
-                }
-                $head->appendChild($base);
+        foreach ($mf2['items'] as $item) {
+            if (!in_array('h-card', $item['type'])) {
+                continue;
+            }
+
+            // We found a match, return it immediately
+            if (isset($item['properties']['url']) && in_array($url, $item['properties']['url'])) {
+                return $item['properties'];
             }
-            return $dom->saveXML();
-        } else {
-            throw new Exception("Invalid HTML could not be parsed.");
+
+            // Let's keep all the hcards for later, to return one of them at least
+            $hcards[] = $item['properties'];
         }
+
+        // No match immediately for the url we expected, but there were h-cards found
+        if (count($hcards) > 0) {
+            return $hcards[0];
+        }
+
+        return null;
     }
 }