diff options
author | Mario Vavti <mario@mariovavti.com> | 2016-03-26 18:46:07 +0100 |
---|---|---|
committer | Mario Vavti <mario@mariovavti.com> | 2016-03-26 18:46:07 +0100 |
commit | f714e97d63e61dfda77f4d4ab4eb2b5b5fb06737 (patch) | |
tree | f1c439e3ca9d01f82a29629222e1afc603d194b8 /include | |
parent | a50706317435d09cacb95cad0a6ccaf8ae5b5f6c (diff) | |
parent | 3caf51b0754741dac2450a492de5aaebfa1b2fe9 (diff) | |
download | volse-hubzilla-f714e97d63e61dfda77f4d4ab4eb2b5b5fb06737.tar.gz volse-hubzilla-f714e97d63e61dfda77f4d4ab4eb2b5b5fb06737.tar.bz2 volse-hubzilla-f714e97d63e61dfda77f4d4ab4eb2b5b5fb06737.zip |
Merge branch 'master' of https://github.com/redmatrix/hubzilla
Diffstat (limited to 'include')
-rw-r--r-- | include/crypto.php | 23 | ||||
-rwxr-xr-x | include/items.php | 22 | ||||
-rw-r--r-- | include/network.php | 459 |
3 files changed, 252 insertions, 252 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/items.php b/include/items.php index c3a0b82d2..2884d8e52 100755 --- a/include/items.php +++ b/include/items.php @@ -3848,8 +3848,8 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { $datarray = get_atom_elements($feed,$item,$author); if($contact['xchan_network'] === 'rss') { - $res['public_policy'] = 'specific'; - $res['comment_policy'] = 'none'; + $datarray['public_policy'] = 'specific'; + $datarray['comment_policy'] = 'none'; } if((! x($author,'author_name')) || ($author['author_is_feed'])) @@ -3911,8 +3911,8 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { $datarray = get_atom_elements($feed,$item,$author); if($contact['xchan_network'] === 'rss') { - $res['public_policy'] = 'specific'; - $res['comment_policy'] = 'none'; + $datarray['public_policy'] = 'specific'; + $datarray['comment_policy'] = 'none'; } @@ -3932,6 +3932,16 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { $datarray['author_xchan'] = ''; + if(activity_match($datarray['verb'],ACTIVITY_FOLLOW) && $datarray['obj_type'] === ACTIVITY_OBJ_PERSON) { + $cb = array('item' => $datarray,'channel' => $importer, 'xchan' => null, 'author' => $author, 'caught' => false); + call_hooks('follow_from_feed',$cb); + if($cb['caught']) { + if($cb['return_code']) + http_status_exit($cb['return_code']); + continue; + } + } + if($author['author_link'] != $contact['xchan_url']) { $x = import_author_unknown(array('name' => $author['author_name'],'url' => $author['author_link'],'photo' => array('src' => $author['author_photo']))); if($x) @@ -4214,7 +4224,7 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) { if(($item['parent'] != $item['id']) || ($item['parent_mid'] !== $item['mid']) || (($item['thr_parent'] !== '') && ($item['thr_parent'] !== $item['mid']))) { $parent_item = (($item['thr_parent']) ? $item['thr_parent'] : $item['parent_mid']); - $o .= '<thr:in-reply-to ref="' . xmlify($parent_item) . '" type="text/html" href="' . xmlify($item['plink']) . '" />' . "\r\n"; + $o .= '<thr:in-reply-to ref="' . z_root() . '/display/' . xmlify($parent_item) . '" type="text/html" href="' . xmlify($item['plink']) . '" />' . "\r\n"; } if(activity_match($item['obj_type'],ACTIVITY_OBJ_EVENT) && activity_match($item['verb'],ACTIVITY_POST)) { @@ -4232,7 +4242,7 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) { $o .= '<content type="' . $type . '" >' . xmlify(prepare_text($body,$item['mimetype'])) . '</content>' . "\r\n"; } - $o .= '<id>' . xmlify($item['mid']) . '</id>' . "\r\n"; + $o .= '<id>' . z_root() . '/display/' . xmlify($item['mid']) . '</id>' . "\r\n"; $o .= '<published>' . xmlify(datetime_convert('UTC','UTC',$item['created'] . '+00:00',ATOM_TIME)) . '</published>' . "\r\n"; $o .= '<updated>' . xmlify(datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME)) . '</updated>' . "\r\n"; diff --git a/include/network.php b/include/network.php index 3efc82447..e7d341321 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,195 @@ 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']); + set_xconfig($address,'system','feed_url',$atom_feed); } - 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) { @@ -1497,8 +1460,8 @@ function find_webfinger_location($j,$rhs) { function match_webfinger_location($s,$h) { - // GNU-social and the older StatusNet - if(preg_match('|' . $h . '/user/([0-9]*?)$|',$s)) + // GNU-social and the older StatusNet - the $host/user/123 form doesn't work + if(preg_match('|' . $h . '/index.php/user/([0-9]*?)$|',$s)) return $s; // Redmatrix / hubzilla if(preg_match('|' . $h . '/channel/|',$s)) @@ -1573,7 +1536,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 +1582,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; |