aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorredmatrix <git@macgirvin.com>2016-03-22 19:58:59 -0700
committerredmatrix <git@macgirvin.com>2016-03-22 19:58:59 -0700
commit6f2ba0c6193a229b3f371de2cae7b314927d4cbb (patch)
treed3f0580d276174b8de9279ac067023f0bcf9d366
parent51a840f46a71800c5ce8111dacc2c4e1bbbe0b1a (diff)
downloadvolse-hubzilla-6f2ba0c6193a229b3f371de2cae7b314927d4cbb.tar.gz
volse-hubzilla-6f2ba0c6193a229b3f371de2cae7b314927d4cbb.tar.bz2
volse-hubzilla-6f2ba0c6193a229b3f371de2cae7b314927d4cbb.zip
rewrite the webfinger discovery logic
-rw-r--r--include/crypto.php23
-rw-r--r--include/network.php454
-rw-r--r--mod/xrd.php17
-rw-r--r--version.inc2
-rwxr-xr-xview/tpl/xrd_person.tpl5
5 files changed, 253 insertions, 248 deletions
diff --git a/include/crypto.php b/include/crypto.php
index 3cddc7581..d82ee5114 100644
--- a/include/crypto.php
+++ b/include/crypto.php
@@ -308,11 +308,33 @@ function metorsa($m,$e) {
return $key;
}
+
+
function salmon_key($pubkey) {
pemtome($pubkey,$m,$e);
return 'RSA' . '.' . base64url_encode($m,true) . '.' . base64url_encode($e,true) ;
}
+
+function convert_salmon_key($key) {
+
+ if(strstr($key,','))
+ $rawkey = substr($key,strpos($key,',')+1);
+ else
+ $rawkey = substr($key,5);
+
+ $key_info = explode('.',$rawkey);
+
+ $m = base64url_decode($key_info[1]);
+ $e = base64url_decode($key_info[2]);
+
+ logger('key details: ' . print_r($key_info,true), LOGGER_DATA);
+ $salmon_key = metopem($m,$e);
+ return $salmon_key;
+
+}
+
+
function z_obscure($s) {
return json_encode(crypto_encapsulate($s,get_config('system','pubkey')));
}
@@ -322,3 +344,4 @@ function z_unobscure($s) {
return $s;
return crypto_unencapsulate(json_decode($s,true),get_config('system','prvkey'));
}
+
diff --git a/include/network.php b/include/network.php
index 3efc82447..dd0089bf8 100644
--- a/include/network.php
+++ b/include/network.php
@@ -1061,32 +1061,16 @@ function discover_by_url($url,$arr = null) {
}
-function convert_salmon_key($key) {
-
- if(strstr($key,','))
- $rawkey = substr($key,strpos($key,',')+1);
- else
- $rawkey = substr($key,5);
-
- $key_info = explode('.',$rawkey);
-
- $m = base64url_decode($key_info[1]);
- $e = base64url_decode($key_info[2]);
-
- logger('key details: ' . print_r($key_info,true), LOGGER_DEBUG);
- $salmon_key = metopem($m,$e);
- return $salmon_key;
-
-}
-
-
function discover_by_webbie($webbie) {
require_once('library/HTML5/Parser.php');
- $result = array();
- $network = null;
+ $result = array();
+
+ $network = null;
+
$diaspora = false;
- $gnusoc = false;
+ $gnusoc = false;
+ $dfrn = false;
$has_salmon = false;
$salmon_key = false;
@@ -1094,7 +1078,6 @@ function discover_by_webbie($webbie) {
$diaspora_base = '';
$diaspora_guid = '';
$diaspora_key = '';
- $dfrn = false;
$webbie = strtolower($webbie);
@@ -1102,6 +1085,10 @@ function discover_by_webbie($webbie) {
if($x && array_key_exists('links',$x) && $x['links']) {
foreach($x['links'] as $link) {
if(array_key_exists('rel',$link)) {
+
+ // If we discover zot - don't search further; grab the info and get out of
+ // here.
+
if($link['rel'] == 'http://purl.org/zot/protocol') {
logger('discover_by_webbie: zot found for ' . $webbie, LOGGER_DEBUG);
if(array_key_exists('zot',$x) && $x['zot']['success'])
@@ -1115,6 +1102,9 @@ function discover_by_webbie($webbie) {
}
}
}
+ if($link['rel'] == NAMESPACE_DFRN) {
+ $dfrn = $link['href'];
+ }
if($link['rel'] == 'magic-public-key') {
if(substr($link['href'],0,5) === 'data:') {
$salmon_key = convert_salmon_key($link['href']);
@@ -1131,88 +1121,40 @@ function discover_by_webbie($webbie) {
}
}
- logger('webfing: ' . print_r($x,true), LOGGER_DATA, LOG_INFO);
+ logger('webfinger: ' . print_r($x,true), LOGGER_DATA, LOG_INFO);
$arr = array('address' => $webbie, 'success' => false, 'webfinger' => $x);
call_hooks('discover_channel_webfinger', $arr);
if($arr['success'])
return true;
- if($salmon_key && $has_salmon && $atom_feed) {
-
- $gnusoc = true;
- $addr = $x['address'];
+ $aliases = array();
- $m = parse_url($x['location']);
+ // Now let's make some decisions on what we may need
+ // to obtain further info
- $k = z_fetch_url($atom_feed);
- if($k['success'])
- $feed_meta = feed_meta($k['body']);
+ $probe_atom = false;
+ $probe_old = false;
+ $probe_hcard = false;
- // stash any discovered pubsubhubbub hubs in case we need to follow them
- // this will save an expensive lookup later
+ $address = '';
+ $location = '';
+ $nickname = '';
+ $fullname = '';
+ $avatar = '';
+ $pubkey = '';
- if($feed_meta['hubs'])
- set_xconfig($addr,'system','push_hubs',$feed_meta['hubs']);
+ if(array_key_exists('address',$x))
+ $address = $x['address'];
+ if(array_key_exists('location',$x))
+ $location = $x['location'];
+ if(array_key_exists('nickname',$x))
+ $nickname = $x['nickname'];
- if($feed_meta && $feed_meta['author']) {
- $r = q("select * from xchan where xchan_hash = '%s' limit 1",
- dbesc($addr)
- );
- if($r) {
- $r = q("update xchan set xchan_name = '%s', xchan_network = '%s', xchan_name_date = '%s' where xchan_hash = '%s' limit 1",
- dbesc(($feed_meta['author']['author_name']) ? $feed_meta['author']['author_name'] : $x['nickname']),
- dbesc('gnusoc'),
- dbesc(datetime_convert()),
- dbesc($addr)
- );
- }
- else {
-
- $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_pubkey, xchan_addr, xchan_url, xchan_name, xchan_network, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
- dbesc($addr),
- dbesc($x['location']),
- dbesc($salmon_key),
- dbesc($addr),
- dbesc($x['location']),
- dbesc(($feed_meta['author']['author_name']) ? $feed_meta['author']['author_name'] : $x['nickname']),
- dbesc('gnusoc'),
- dbescdate(datetime_convert())
- );
- }
-
- $r = q("select * from hubloc where hubloc_hash = '%s' limit 1",
- dbesc($addr)
- );
-
- if(! $r) {
-
- $r = q("insert into hubloc ( hubloc_guid, hubloc_hash, hubloc_addr, hubloc_network, hubloc_url, hubloc_host, hubloc_callback, hubloc_updated, hubloc_primary ) values ('%s','%s','%s','%s','%s','%s','%s','%s', 1)",
- dbesc($x['location']),
- dbesc($addr),
- dbesc($addr),
- dbesc('gnusoc'),
- dbesc($m['scheme'] . '://' . $m['host']),
- dbesc($m['host']),
- dbesc($salmon),
- dbescdate(datetime_convert())
- );
- }
- $photos = import_xchan_photo($feed_meta['author']['author_photo'],$addr);
- $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
- dbescdate(datetime_convert()),
- dbesc($photos[0]),
- dbesc($photos[1]),
- dbesc($photos[2]),
- dbesc($photos[3]),
- dbesc($addr)
- );
- return true;
-
- }
- }
- else {
+ if(! $x)
+ $probe_old = true;
+ if($probe_old) {
$x = old_webfinger($webbie);
if($x) {
logger('old_webfinger: ' . print_r($x,true));
@@ -1245,174 +1187,194 @@ function discover_by_webbie($webbie) {
$pubkey = $diaspora_key;
$diaspora = true;
}
+ if($link['@attributes']['rel'] == 'magic-public-key') {
+ if(substr($link['@attributes']['href'],0,5) === 'data:') {
+ $salmon_key = convert_salmon_key($link['@attributes']['href']);
+ }
+ }
+ if($link['@attributes']['rel'] == 'salmon') {
+ $has_salmon = true;
+ $salmon = $link['@attributes']['href'];
+ }
+
+ if($link['@attributes']['rel'] == 'http://schemas.google.com/g/2010#updates-from') {
+ $atom_feed = $link['@attributes']['href'];
+ }
+ if($link['@attributes']['rel'] === 'alias') {
+ $aliases[] = $link['@attributes']['href'];
+ }
+ if($link['@attributes']['rel'] === 'subject') {
+ $subject = $link['@attributes']['href'];
+ }
}
}
+ }
- if($diaspora && $diaspora_base && $diaspora_guid) {
- $guid = $diaspora_guid;
- $diaspora_base = trim($diaspora_base,'/');
+ if($subject || $aliases) {
+ if(strpos($webbie,'@')) {
+ $rhs = substr($webbie,strpos($webbie,'@')+1);
+ }
+ else {
+ $m = parse_url($webbie);
+ if($m) {
+ $rhs = $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
+ }
+ }
- $notify = $diaspora_base . '/receive';
+ $v = array('subject' => $subject,'aliases' => $aliases);
+ $address = find_webfinger_address($v,$rhs);
+ $location = find_webfinger_location($v,$rhs);
+ if($address)
+ $nickname = substr($address,0,strpos($address,'@'));
- if(strpos($webbie,'@')) {
- $addr = str_replace('acct:', '', $webbie);
- $hostname = substr($webbie,strpos($webbie,'@')+1);
- }
- $network = 'diaspora';
- // until we get a dfrn layer, we'll use diaspora protocols for Friendica,
- // but give it a different network so we can go back and fix these when we get proper support.
- // It really should be just 'friendica' but we also want to distinguish
- // between Friendica sites that we can use D* protocols with and those we can't.
- // Some Friendica sites will have Diaspora disabled.
- if($dfrn)
- $network = 'friendica-over-diaspora';
- if($hcard) {
- $vcard = scrape_vcard($hcard);
- $vcard['nick'] = substr($webbie,0,strpos($webbie,'@'));
- if(! $vcard['fn'])
- $vcard['fn'] = $webbie;
- }
-
- $r = q("select * from xchan where xchan_hash = '%s' limit 1",
- dbesc($addr)
- );
+ }
- // fix relative urls
- if($vcard['photo'] && (strpos($vcard['photo'],'http') !== 0))
- $vcard['photo'] = $diaspora_base . '/' . $vcard['photo'];
-
- /**
- *
- * Diaspora communications are notoriously unreliable and receiving profile update messages (indeed any messages)
- * are pretty much random luck. We'll check the timestamp of the xchan_name_date at a higher level and refresh
- * this record once a month; because if you miss a profile update message and they update their profile photo or name
- * you're otherwise stuck with stale info until they change their profile again - which could be years from now.
- *
- */
-
- if($r) {
- $r = q("update xchan set xchan_name = '%s', xchan_network = '%s', xchan_name_date = '%s' where xchan_hash = '%s' limit 1",
- dbesc($vcard['fn']),
- dbesc($network),
- dbesc(datetime_convert()),
- dbesc($addr)
- );
+ if($salmon_key && $has_salmon && $atom_feed && (! $dfrn) && (! $diaspora)) {
+ $gnusoc = true;
+ $probe_atom = true;
+ }
+
+ if(! $pubkey)
+ $pubkey = $salmon_key;
+
+ if(($dfrn || $diaspora) && $hcard)
+ $probe_hcard = true;
+
+ if(! $fullname)
+ $fullname = $nickname;
+
+ if($probe_atom) {
+ $k = z_fetch_url($atom_feed);
+ if($k['success'])
+ $feed_meta = feed_meta($k['body']);
+ if($feed_meta) {
+
+ // stash any discovered pubsubhubbub hubs in case we need to follow them
+ // this will save an expensive lookup later
+
+ if($feed_meta['hubs'] && $address) {
+ set_xconfig($address,'system','push_hubs',$feed_meta['hubs']);
}
- else {
-
- $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_pubkey, xchan_addr, xchan_url, xchan_name, xchan_network, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
- dbesc($addr),
- dbesc($guid),
- dbesc($pubkey),
- dbesc($addr),
- dbesc($profile),
- dbesc($vcard['fn']),
- dbesc($network),
- dbescdate(datetime_convert())
- );
+ if($feed_meta['author']['author_name']) {
+ $fullname = $feed_meta['author']['author_name'];
}
+ if(! $avatar) {
+ if($feed_meta['author']['author_photo'])
+ $avatar = $feed_meta['author']['author_photo'];
+ }
+ }
+ }
+ else {
+ if($probe_hcard) {
+ $vcard = scrape_vcard($hcard);
+ if($vcard) {
+ logger('vcard: ' . print_r($vcard,true), LOGGER_DATA);
+ if($vcard['fn'])
+ $fullname = $vcard['fn'];
+ if($vcard['photo'] && (strpos($vcard['photo'],'http') !== 0))
+ $vcard['photo'] = $diaspora_base . '/' . $vcard['photo'];
+ if(! $avatar)
+ $avatar = $vcard['photo'];
- $r = q("select * from hubloc where hubloc_hash = '%s' limit 1",
- dbesc($webbie)
- );
-
- if(! $r) {
-
- $r = q("insert into hubloc ( hubloc_guid, hubloc_hash, hubloc_addr, hubloc_network, hubloc_url, hubloc_host, hubloc_callback, hubloc_updated, hubloc_primary ) values ('%s','%s','%s','%s','%s','%s','%s','%s', 1)",
- dbesc($guid),
- dbesc($addr),
- dbesc($addr),
- dbesc($network),
- dbesc(trim($diaspora_base,'/')),
- dbesc($hostname),
- dbesc($notify),
- dbescdate(datetime_convert())
- );
}
- $photos = import_xchan_photo($vcard['photo'],$addr);
- $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
- dbescdate(datetime_convert()),
- dbesc($photos[0]),
- dbesc($photos[1]),
- dbesc($photos[2]),
- dbesc($photos[3]),
- dbesc($addr)
- );
- return true;
+ }
+ }
+
+ if(($profile) && (! $location))
+ $location = $profile;
+
+ if($location) {
+ $m = parse_url($location);
+ $base = $m['scheme'] . '://' . $m['host'];
+ $host = $m['host'];
+ }
+
+ if($diaspora && $diaspora_base && $diaspora_guid) {
+ if($dfrn)
+ $network = 'friendica-over-diaspora';
+ else
+ $network = 'diaspora';
+
+ $base = trim($diaspora_base,'/');
+ $notify = $base . '/receive';
+
+ }
+ else {
+ if($gnusoc) {
+ $network = 'gnusoc';
+ $notify = $salmon;
}
}
- return false;
-/*
- $vcard['fn'] = notags($vcard['fn']);
- $vcard['nick'] = str_replace(' ','',notags($vcard['nick']));
-
- $result['name'] = $vcard['fn'];
- $result['nick'] = $vcard['nick'];
- $result['guid'] = $guid;
- $result['url'] = $profile;
- $result['hostname'] = $hostname;
- $result['addr'] = $addr;
- $result['batch'] = $batch;
- $result['notify'] = $notify;
- $result['poll'] = $poll;
- $result['request'] = $request;
- $result['confirm'] = $confirm;
- $result['poco'] = $poco;
- $result['photo'] = $vcard['photo'];
- $result['priority'] = $priority;
- $result['network'] = $network;
- $result['alias'] = $alias;
- $result['pubkey'] = $pubkey;
-
- logger('probe_url: ' . print_r($result,true), LOGGER_DEBUG);
-
- return $result;
-
-*/
-
-/* Sample Diaspora result.
-
-Array
-(
- [name] => Mike Macgirvin
- [nick] => macgirvin
- [guid] => a9174a618f8d269a
- [url] => https://joindiaspora.com/u/macgirvin
- [hostname] => joindiaspora.com
- [addr] => macgirvin@joindiaspora.com
- [batch] =>
- [notify] => https://joindiaspora.com/receive
- [poll] => https://joindiaspora.com/public/macgirvin.atom
- [request] =>
- [confirm] =>
- [poco] =>
- [photo] => https://joindiaspora.s3.amazonaws.com/uploads/images/thumb_large_fec4e6eef13ae5e56207.jpg
- [priority] =>
- [network] => diaspora
- [alias] =>
- [pubkey] => -----BEGIN PUBLIC KEY-----
-MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtihtyIuRDWkDpCA+I1UaQ
-jI4S7k625+A7EEJm+pL2ZVSJxeCKiFeEgHBQENjLMNNm8l8F6blxgQqE6ZJ9Spa7f
-tlaXYTRCrfxKzh02L3hR7sNA+JS/nXJaUAIo+IwpIEspmcIRbD9GB7Wv/rr+M28uH
-31EeYyDz8QL6InU/bJmnCdFvmEMBQxJOw1ih9tQp7UNJAbUMCje0WYFzBz7sfcaHL
-OyYcCOqOCBLdGucUoJzTQ9iDBVzB8j1r1JkIHoEb2moUoKUp+tkCylNfd/3IVELF9
-7w1Qjmit3m50OrJk2DQOXvCW9KQxaQNdpRPSwhvemIt98zXSeyZ1q/YjjOwG0DWDq
-AF8aLj3/oQaZndTPy/6tMiZogKaijoxj8xFLuPYDTw5VpKquriVC0z8oxyRbv4t9v
-8JZZ9BXqzmayvY3xZGGp8NulrfjW+me2bKh0/df1aHaBwpZdDTXQ6kqAiS2FfsuPN
-vg57fhfHbL1yJ4oDbNNNeI0kJTGchXqerr8C20khU/cQ2Xt31VyEZtnTB665Ceugv
-kp3t2qd8UpAVKl430S5Quqx2ymfUIdxdW08CEjnoRNEL3aOWOXfbf4gSVaXmPCR4i
-LSIeXnd14lQYK/uxW/8cTFjcmddsKxeXysoQxbSa9VdDK+KkpZdgYXYrTTofXs6v+
-4afAEhRaaY+MCAwEAAQ==
------END PUBLIC KEY-----
-
-)
-*/
+ logger('network: ' . $network);
+ logger('address: ' . $address);
+ logger('fullname: ' . $fullname);
+ logger('pubkey: ' . $pubkey);
+ logger('location: ' . $location);
+
+
+
+ // if we have everything we need, let's create the records
+
+ if($network && $address && $fullname && $pubkey && $location) {
+ $r = q("select * from xchan where xchan_hash = '%s' limit 1",
+ dbesc($address)
+ );
+ if($r) {
+ $r = q("update xchan set xchan_name = '%s', xchan_network = '%s', xchan_name_date = '%s' where xchan_hash = '%s' limit 1",
+ dbesc($fullname),
+ dbesc($network),
+ dbesc(datetime_convert()),
+ dbesc($address)
+ );
+ }
+ else {
+ $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_pubkey, xchan_addr, xchan_url, xchan_name, xchan_network, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
+ dbesc($address),
+ dbesc(($diaspora_guid) ? $diaspora_guid : $location),
+ dbesc($pubkey),
+ dbesc($address),
+ dbesc($location),
+ dbesc($fullname),
+ dbesc($network),
+ dbescdate(datetime_convert())
+ );
+ }
+
+ $r = q("select * from hubloc where hubloc_hash = '%s' limit 1",
+ dbesc($address)
+ );
+
+ if(! $r) {
+ $r = q("insert into hubloc ( hubloc_guid, hubloc_hash, hubloc_addr, hubloc_network, hubloc_url, hubloc_host, hubloc_callback, hubloc_updated, hubloc_primary ) values ('%s','%s','%s','%s','%s','%s','%s','%s', 1)",
+ dbesc(($diaspora_guid) ? $diaspora_guid : $location),
+ dbesc($address),
+ dbesc($address),
+ dbesc($network),
+ dbesc($base),
+ dbesc($host),
+ dbesc($notify),
+ dbescdate(datetime_convert())
+ );
+ }
+ $photos = import_xchan_photo($avatar,$address);
+ $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
+ dbescdate(datetime_convert()),
+ dbesc($photos[0]),
+ dbesc($photos[1]),
+ dbesc($photos[2]),
+ dbesc($photos[3]),
+ dbesc($address)
+ );
+ return true;
+ }
+ return false;
}
+
function webfinger_rfc7033($webbie,$zot = false) {
@@ -1573,7 +1535,7 @@ function fetch_lrdd_template($host) {
function fetch_xrd_links($url) {
-logger('fetch_xrd_links: ' . $url);
+ logger('fetch_xrd_links: ' . $url, LOGGER_DEBUG);
$redirects = 0;
$x = z_fetch_url($url,false,$redirects,array('timeout' => 20));
@@ -1619,6 +1581,10 @@ logger('fetch_xrd_links: ' . $url);
}
}
+ if(isset($arr['xrd']['subject'])) {
+ $links[]['@attributes'] = array('rel' => 'subject' , 'href' => $arr['xrd']['subject']);
+ }
+
logger('fetch_xrd_links: ' . print_r($links,true), LOGGER_DATA);
return $links;
diff --git a/mod/xrd.php b/mod/xrd.php
index da4ab51a4..ed8e1eabe 100644
--- a/mod/xrd.php
+++ b/mod/xrd.php
@@ -7,8 +7,12 @@ function xrd_init(&$a) {
$uri = urldecode(notags(trim($_GET['uri'])));
logger('xrd: ' . $uri,LOGGER_DEBUG);
- if(substr($uri,0,4) === 'http')
+ $resource = $uri;
+
+ if(substr($uri,0,4) === 'http') {
+ $uri = str_replace('~','',$uri);
$name = basename($uri);
+ }
else {
$local = str_replace('acct:', '', $uri);
if(substr($local,0,2) == '//')
@@ -35,9 +39,18 @@ function xrd_init(&$a) {
header("Content-type: application/xrd+xml");
+ $aliases = array('acct:' . $r[0]['channel_address'] . '@' . $a->get_hostname(), z_root() . '/channel/' . $r[0]['channel_address'], z_root() . '/~' . $r[0]['channel_address']);
+
+ for($x = 0; $x < count($aliases); $x ++) {
+ if($aliases[$x] === $resource)
+ unset($aliases[$x]);
+ }
+
+
$o = replace_macros(get_markup_template('xrd_person.tpl'), array(
'$nick' => $r[0]['channel_address'],
- '$accturi' => $uri,
+ '$accturi' => $resource,
+ '$aliases' => $aliases,
'$profile_url' => $a->get_baseurl() . '/channel/' . $r[0]['channel_address'],
'$hcard_url' => $a->get_baseurl() . '/hcard/' . $r[0]['channel_address'],
'$atom' => $a->get_baseurl() . '/feed/' . $r[0]['channel_address'],
diff --git a/version.inc b/version.inc
index ecfd6b86e..fe23fb3bf 100644
--- a/version.inc
+++ b/version.inc
@@ -1 +1 @@
-2016-03-21.1342H
+2016-03-22.1343H
diff --git a/view/tpl/xrd_person.tpl b/view/tpl/xrd_person.tpl
index 754eb3944..93fdcb1df 100755
--- a/view/tpl/xrd_person.tpl
+++ b/view/tpl/xrd_person.tpl
@@ -2,7 +2,10 @@
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
<Subject>{{$accturi}}</Subject>
-
+ {{if $aliases}}{{foreach $aliases as $a}}
+ <Alias>{{$a}}</Alias>
+ {{/foreach}}{{/if}}
+
<Link rel="http://schemas.google.com/g/2010#updates-from"
type="application/atom+xml"
href="{{$atom}}" />