|
|
|
@ -5,7 +5,7 @@
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
require_once("include/xml.php"); |
|
|
|
|
|
|
|
|
|
require_once('include/Probe.php'); |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief Curl wrapper |
|
|
|
@ -371,324 +371,6 @@ function http_status_exit($val, $description = array()) {
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Given an email style address, perform webfinger lookup and |
|
|
|
|
// return the resulting DFRN profile URL, or if no DFRN profile URL |
|
|
|
|
// is located, returns an OStatus subscription template (prefixed |
|
|
|
|
// with the string 'stat:' to identify it as on OStatus template). |
|
|
|
|
// If this isn't an email style address just return $webbie. |
|
|
|
|
// Return an empty string if email-style addresses but webfinger fails, |
|
|
|
|
// or if the resultant personal XRD doesn't contain a supported |
|
|
|
|
// subscription/friend-request attribute. |
|
|
|
|
|
|
|
|
|
// amended 7/9/2011 to return an hcard which could save potentially loading |
|
|
|
|
// a lengthy content page to scrape dfrn attributes |
|
|
|
|
|
|
|
|
|
function webfinger_dfrn($webbie,&$hcard) { |
|
|
|
|
if(! strstr($webbie,'@')) { |
|
|
|
|
return $webbie; |
|
|
|
|
} |
|
|
|
|
$profile_link = ''; |
|
|
|
|
|
|
|
|
|
$links = webfinger($webbie); |
|
|
|
|
logger('webfinger_dfrn: ' . $webbie . ':' . print_r($links,true), LOGGER_DATA); |
|
|
|
|
if(count($links)) { |
|
|
|
|
foreach($links as $link) { |
|
|
|
|
if($link['@attributes']['rel'] === NAMESPACE_DFRN) |
|
|
|
|
$profile_link = $link['@attributes']['href']; |
|
|
|
|
if($link['@attributes']['rel'] === NAMESPACE_OSTATUSSUB) |
|
|
|
|
$profile_link = 'stat:' . $link['@attributes']['template']; |
|
|
|
|
if($link['@attributes']['rel'] === 'http://microformats.org/profile/hcard') |
|
|
|
|
$hcard = $link['@attributes']['href']; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return $profile_link; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief Perform webfinger lookup on an email style address |
|
|
|
|
* |
|
|
|
|
* @param string $webbi An email style address |
|
|
|
|
* @param boolean $debug |
|
|
|
|
* |
|
|
|
|
* @return array of link attributes from the personal XRD file |
|
|
|
|
* empty array on error/failure |
|
|
|
|
*/ |
|
|
|
|
function webfinger($webbie, $debug = false) { |
|
|
|
|
$host = ''; |
|
|
|
|
if(strstr($webbie,'@')) { |
|
|
|
|
$host = substr($webbie,strpos($webbie,'@') + 1); |
|
|
|
|
} |
|
|
|
|
if(strlen($host)) { |
|
|
|
|
$tpl = fetch_lrdd_template($host); |
|
|
|
|
logger('webfinger: lrdd template: ' . $tpl); |
|
|
|
|
if(strlen($tpl)) { |
|
|
|
|
$pxrd = str_replace('{uri}', urlencode('acct:' . $webbie), $tpl); |
|
|
|
|
logger('webfinger: pxrd: ' . $pxrd); |
|
|
|
|
$links = fetch_xrd_links($pxrd); |
|
|
|
|
if(! count($links)) { |
|
|
|
|
// try with double slashes |
|
|
|
|
$pxrd = str_replace('{uri}', urlencode('acct://' . $webbie), $tpl); |
|
|
|
|
logger('webfinger: pxrd: ' . $pxrd); |
|
|
|
|
$links = fetch_xrd_links($pxrd); |
|
|
|
|
} |
|
|
|
|
return $links; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return array(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function lrdd($uri, $debug = false) { |
|
|
|
|
|
|
|
|
|
$a = get_app(); |
|
|
|
|
|
|
|
|
|
// default priority is host priority, host-meta first |
|
|
|
|
|
|
|
|
|
$priority = 'host'; |
|
|
|
|
|
|
|
|
|
// All we have is an email address. Resource-priority is irrelevant |
|
|
|
|
// because our URI isn't directly resolvable. |
|
|
|
|
|
|
|
|
|
if(strstr($uri,'@')) { |
|
|
|
|
return(webfinger($uri)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// get the host meta file |
|
|
|
|
|
|
|
|
|
$host = @parse_url($uri); |
|
|
|
|
|
|
|
|
|
if($host) { |
|
|
|
|
$url = ((x($host,'scheme')) ? $host['scheme'] : 'http') . '://'; |
|
|
|
|
$url .= $host['host'] . '/.well-known/host-meta' ; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
return array(); |
|
|
|
|
|
|
|
|
|
logger('lrdd: constructed url: ' . $url); |
|
|
|
|
|
|
|
|
|
$xml = fetch_url($url); |
|
|
|
|
|
|
|
|
|
$headers = $a->get_curl_headers(); |
|
|
|
|
|
|
|
|
|
if (! $xml) |
|
|
|
|
return array(); |
|
|
|
|
|
|
|
|
|
logger('lrdd: host_meta: ' . $xml, LOGGER_DATA); |
|
|
|
|
|
|
|
|
|
if(! stristr($xml,'<xrd')) |
|
|
|
|
return array(); |
|
|
|
|
|
|
|
|
|
$h = parse_xml_string($xml); |
|
|
|
|
if(! $h) |
|
|
|
|
return array(); |
|
|
|
|
|
|
|
|
|
$arr = xml::element_to_array($h); |
|
|
|
|
|
|
|
|
|
if(isset($arr['xrd']['property'])) { |
|
|
|
|
$property = $arr['crd']['property']; |
|
|
|
|
if(! isset($property[0])) |
|
|
|
|
$properties = array($property); |
|
|
|
|
else |
|
|
|
|
$properties = $property; |
|
|
|
|
foreach($properties as $prop) |
|
|
|
|
if((string) $prop['@attributes'] === 'http://lrdd.net/priority/resource') |
|
|
|
|
$priority = 'resource'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// save the links in case we need them |
|
|
|
|
|
|
|
|
|
$links = array(); |
|
|
|
|
|
|
|
|
|
if(isset($arr['xrd']['link'])) { |
|
|
|
|
$link = $arr['xrd']['link']; |
|
|
|
|
if(! isset($link[0])) |
|
|
|
|
$links = array($link); |
|
|
|
|
else |
|
|
|
|
$links = $link; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// do we have a template or href? |
|
|
|
|
|
|
|
|
|
if(count($links)) { |
|
|
|
|
foreach($links as $link) { |
|
|
|
|
if($link['@attributes']['rel'] && attribute_contains($link['@attributes']['rel'],'lrdd')) { |
|
|
|
|
if(x($link['@attributes'],'template')) |
|
|
|
|
$tpl = $link['@attributes']['template']; |
|
|
|
|
elseif(x($link['@attributes'],'href')) |
|
|
|
|
$href = $link['@attributes']['href']; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if((! isset($tpl)) || (! strpos($tpl,'{uri}'))) |
|
|
|
|
$tpl = ''; |
|
|
|
|
|
|
|
|
|
if($priority === 'host') { |
|
|
|
|
if(strlen($tpl)) |
|
|
|
|
$pxrd = str_replace('{uri}', urlencode($uri), $tpl); |
|
|
|
|
elseif(isset($href)) |
|
|
|
|
$pxrd = $href; |
|
|
|
|
if(isset($pxrd)) { |
|
|
|
|
logger('lrdd: (host priority) pxrd: ' . $pxrd); |
|
|
|
|
$links = fetch_xrd_links($pxrd); |
|
|
|
|
return $links; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
$lines = explode("\n",$headers); |
|
|
|
|
if(count($lines)) { |
|
|
|
|
foreach($lines as $line) { |
|
|
|
|
if((stristr($line,'link:')) && preg_match('/<([^>].*)>.*rel\=[\'\"]lrdd[\'\"]/',$line,$matches)) { |
|
|
|
|
return(fetch_xrd_links($matches[1])); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// priority 'resource' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$html = fetch_url($uri); |
|
|
|
|
$headers = $a->get_curl_headers(); |
|
|
|
|
logger('lrdd: headers=' . $headers, LOGGER_DEBUG); |
|
|
|
|
|
|
|
|
|
// don't try and parse raw xml as html |
|
|
|
|
if(! strstr($html,'<?xml')) { |
|
|
|
|
require_once('library/HTML5/Parser.php'); |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
$dom = HTML5_Parser::parse($html); |
|
|
|
|
} catch (DOMException $e) { |
|
|
|
|
logger('lrdd: parse error: ' . $e); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(isset($dom) && $dom) { |
|
|
|
|
$items = $dom->getElementsByTagName('link'); |
|
|
|
|
foreach($items as $item) { |
|
|
|
|
$x = $item->getAttribute('rel'); |
|
|
|
|
if($x == "lrdd") { |
|
|
|
|
$pagelink = $item->getAttribute('href'); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(isset($pagelink)) |
|
|
|
|
return(fetch_xrd_links($pagelink)); |
|
|
|
|
|
|
|
|
|
// next look in HTTP headers |
|
|
|
|
|
|
|
|
|
$lines = explode("\n",$headers); |
|
|
|
|
if(count($lines)) { |
|
|
|
|
foreach($lines as $line) { |
|
|
|
|
/// @TODO Alter the following regex to support multiple relations (space separated) |
|
|
|
|
if((stristr($line,'link:')) && preg_match('/<([^>].*)>.*rel\=[\'\"]lrdd[\'\"]/',$line,$matches)) { |
|
|
|
|
$pagelink = $matches[1]; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// don't try and run feeds through the html5 parser |
|
|
|
|
if(stristr($line,'content-type:') && ((stristr($line,'application/atom+xml')) || (stristr($line,'application/rss+xml')))) |
|
|
|
|
return array(); |
|
|
|
|
if(stristr($html,'<rss') || stristr($html,'<feed')) |
|
|
|
|
return array(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(isset($pagelink)) |
|
|
|
|
return(fetch_xrd_links($pagelink)); |
|
|
|
|
|
|
|
|
|
// If we haven't found any links, return the host xrd links (which we have already fetched) |
|
|
|
|
|
|
|
|
|
if(isset($links)) |
|
|
|
|
return $links; |
|
|
|
|
|
|
|
|
|
return array(); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Given a host name, locate the LRDD template from that |
|
|
|
|
// host. Returns the LRDD template or an empty string on |
|
|
|
|
// error/failure. |
|
|
|
|
|
|
|
|
|
function fetch_lrdd_template($host) { |
|
|
|
|
$tpl = ''; |
|
|
|
|
|
|
|
|
|
$url1 = 'https://' . $host . '/.well-known/host-meta' ; |
|
|
|
|
$url2 = 'http://' . $host . '/.well-known/host-meta' ; |
|
|
|
|
$links = fetch_xrd_links($url1); |
|
|
|
|
logger('fetch_lrdd_template from: ' . $url1); |
|
|
|
|
logger('template (https): ' . print_r($links,true)); |
|
|
|
|
if(! count($links)) { |
|
|
|
|
logger('fetch_lrdd_template from: ' . $url2); |
|
|
|
|
$links = fetch_xrd_links($url2); |
|
|
|
|
logger('template (http): ' . print_r($links,true)); |
|
|
|
|
} |
|
|
|
|
if(count($links)) { |
|
|
|
|
foreach($links as $link) |
|
|
|
|
if($link['@attributes']['rel'] && $link['@attributes']['rel'] === 'lrdd' && (!$link['@attributes']['type'] || $link['@attributes']['type'] === 'application/xrd+xml')) |
|
|
|
|
$tpl = $link['@attributes']['template']; |
|
|
|
|
} |
|
|
|
|
if(! strpos($tpl,'{uri}')) |
|
|
|
|
$tpl = ''; |
|
|
|
|
return $tpl; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief Given a URL, retrieve the page as an XRD document. |
|
|
|
|
* |
|
|
|
|
* @param string $url An url |
|
|
|
|
* @return array of links |
|
|
|
|
* return empty array on error/failure |
|
|
|
|
*/ |
|
|
|
|
function fetch_xrd_links($url) { |
|
|
|
|
|
|
|
|
|
$xrd_timeout = intval(get_config('system','xrd_timeout')); |
|
|
|
|
$redirects = 0; |
|
|
|
|
$xml = fetch_url($url,false,$redirects,(($xrd_timeout) ? $xrd_timeout : 20), "application/xrd+xml"); |
|
|
|
|
|
|
|
|
|
logger('fetch_xrd_links: ' . $xml, LOGGER_DATA); |
|
|
|
|
|
|
|
|
|
if ((! $xml) || (! stristr($xml,'<xrd'))) |
|
|
|
|
return array(); |
|
|
|
|
|
|
|
|
|
// fix diaspora's bad xml |
|
|
|
|
$xml = str_replace(array('href="','"/>'),array('href="','"/>'),$xml); |
|
|
|
|
|
|
|
|
|
$h = parse_xml_string($xml); |
|
|
|
|
if(! $h) |
|
|
|
|
return array(); |
|
|
|
|
|
|
|
|
|
$arr = xml::element_to_array($h); |
|
|
|
|
|
|
|
|
|
$links = array(); |
|
|
|
|
|
|
|
|
|
if(isset($arr['xrd']['link'])) { |
|
|
|
|
$link = $arr['xrd']['link']; |
|
|
|
|
if(! isset($link[0])) |
|
|
|
|
$links = array($link); |
|
|
|
|
else |
|
|
|
|
$links = $link; |
|
|
|
|
} |
|
|
|
|
if(isset($arr['xrd']['alias'])) { |
|
|
|
|
$alias = $arr['xrd']['alias']; |
|
|
|
|
if(! isset($alias[0])) |
|
|
|
|
$aliases = array($alias); |
|
|
|
|
else |
|
|
|
|
$aliases = $alias; |
|
|
|
|
if(is_array($aliases) && count($aliases)) { |
|
|
|
|
foreach($aliases as $alias) { |
|
|
|
|
$links[]['@attributes'] = array('rel' => 'alias' , 'href' => $alias); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
logger('fetch_xrd_links: ' . print_r($links,true), LOGGER_DATA); |
|
|
|
|
|
|
|
|
|
return $links; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @brief Check URL to se if ts's real |
|
|
|
|
* |
|
|
|
|