*/
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'];
+ switch ($link->rel) {
+ case WebFingerResource_Profile::PROFILEPAGE:
+ $hints['profileurl'] = $link->href;
break;
- case Salmon::NS_REPLIES:
- $hints['salmon'] = $link['href'];
+ 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:
- $hints['feedurl'] = $link['href'];
+ if (empty($link->type) || $link->type == 'application/atom+xml') {
+ $hints['feedurl'] = $link->href;
+ }
break;
case Discovery::HCARD:
- $hints['hcardurl'] = $link['href'];
+ case Discovery::MF2_HCARD:
+ $hints['hcard'] = $link->href;
break;
default:
break;
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);
-
- error_reporting($old);
+ $hcard = self::_hcard($body, $url);
- 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) {
- // If the original had xmlns or xml:lang attributes on the
- // <html>, we seen to end up with duplicates, which causes
- // parse errors. Remove em!
- //
- // For some reason we have to iterate and remove them twice,
- // *plus* they don't show up on hasAttribute() or removeAttribute().
- // This might be some weird bug in PHP or libxml2, uncertain if
- // it affects other folks consistently.
- $root = $dom->documentElement;
- foreach ($root->attributes as $i => $x) {
- if ($i == 'xmlns' || $i == 'xml:lang') {
- $root->removeAttributeNode($x);
- }
- }
- foreach ($root->attributes as $i => $x) {
- if ($i == 'xmlns' || $i == 'xml:lang') {
- $root->removeAttributeNode($x);
- }
+ foreach ($mf2['items'] as $item) {
+ if (!in_array('h-card', $item['type'])) {
+ continue;
}
- // 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');
- if ($root->firstChild) {
- $root->insertBefore($head, $root->firstChild);
- } else {
- $root->appendChild($head);
- }
- }
- $head->appendChild($base);
+ // 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;
}
}