diff options
Diffstat (limited to 'include/network.php')
-rw-r--r-- | include/network.php | 736 |
1 files changed, 483 insertions, 253 deletions
diff --git a/include/network.php b/include/network.php index 859a60650..ec255581d 100644 --- a/include/network.php +++ b/include/network.php @@ -27,11 +27,12 @@ function get_capath() { * * \b http_auth => username:password * * \b novalidate => do not validate SSL certs, default is to validate using our CA list * * \b nobody => only return the header + * * \b filep => stream resource to write body to. header and body are not returned when using this option. * * @return array an assoziative array with: * * \e int \b return_code => HTTP return code or 0 if timeout or failure * * \e boolean \b success => boolean true (if HTTP 2xx result) or false - * * \e string \b header => HTTP headers + * * \e string \b header => HTTP headers * * \e string \b body => fetched content */ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { @@ -40,7 +41,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { $ch = @curl_init($url); if(($redirects > 8) || (! $ch)) - return false; + return $ret; @curl_setopt($ch, CURLOPT_HEADER, true); @curl_setopt($ch, CURLINFO_HEADER_OUT, true); @@ -53,6 +54,11 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { if($ciphers) @curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, $ciphers); + if(x($opts,'filep')) { + @curl_setopt($ch, CURLOPT_FILE, $opts['filep']); + @curl_setopt($ch, CURLOPT_HEADER, $false); + } + if(x($opts,'headers')) @curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']); @@ -158,6 +164,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { * 'timeout' => int seconds, default system config value or 60 seconds * 'http_auth' => username:password * 'novalidate' => do not validate SSL certs, default is to validate using our CA list + * 'filep' => stream resource to write body to. header and body are not returned when using this option. * @return array an assoziative array with: * * \e int \b return_code => HTTP return code or 0 if timeout or failure * * \e boolean \b success => boolean true (if HTTP 2xx result) or false @@ -171,7 +178,7 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) { $ch = curl_init($url); if(($redirects > 8) || (! $ch)) - return ret; + return $ret; @curl_setopt($ch, CURLOPT_HEADER, true); @curl_setopt($ch, CURLINFO_HEADER_OUT, true); @@ -185,9 +192,16 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) { if($ciphers) @curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, $ciphers); - if(x($opts,'headers')) - @curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']); + if(x($opts,'filep')) { + @curl_setopt($ch, CURLOPT_FILE, $opts['filep']); + @curl_setopt($ch, CURLOPT_HEADER, $false); + } + if(x($opts,'headers')) { + @curl_setopt($ch, CURLOPT_HTTPHEADER, $opts['headers']); +logger('headers: ' . print_r($opts['headers'],true) . 'redir: ' . $redirects); + } + if(x($opts,'nobody')) @curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']); @@ -236,6 +250,21 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) { $base = substr($base,strlen($chunk)); } + // would somebody take lighttpd and just shoot it? + + if($http_code == 417) { + curl_close($ch); + if($opts) { + if($opts['headers']) + $opts['headers'][] = 'Expect:'; + else + $opts['headers'] = array('Expect:'); + } + else + $opts = array('headers' => array('Expect:')); + return z_post_url($url,$params,++$redirects,$opts); + } + if($http_code == 301 || $http_code == 302 || $http_code == 303 || $http_code == 307 || $http_code == 308) { $matches = array(); preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches); @@ -294,8 +323,8 @@ function z_post_url_json($url, $params, $redirects = 0, $opts = array()) { } -function json_return_and_die($x) { - header("content-type: application/json"); +function json_return_and_die($x, $content_type = 'application/json') { + header("Content-type: $content_type"); echo json_encode($x); killme(); } @@ -585,7 +614,7 @@ function scale_external_images($s, $include_link = true, $scale_replace = false) continue; } - $hostname = str_replace('www.','',substr($a->get_baseurl(),strpos($a->get_baseurl(),'://')+3)); + $hostname = str_replace('www.','',substr(z_root(),strpos(z_root(),'://')+3)); if(stristr($mtch[3],$hostname)) continue; @@ -1043,263 +1072,436 @@ function discover_by_url($url,$arr = null) { } + function discover_by_webbie($webbie) { require_once('library/HTML5/Parser.php'); + $result = array(); + + $network = null; + + $diaspora = false; + $gnusoc = false; + $dfrn = false; + + $has_salmon = false; + $salmon_key = false; + $atom_feed = false; + $diaspora_base = ''; + $diaspora_guid = ''; + $diaspora_key = ''; + $webbie = strtolower($webbie); $x = webfinger_rfc7033($webbie,true); if($x && array_key_exists('links',$x) && $x['links']) { foreach($x['links'] as $link) { - if(array_key_exists('rel',$link) && $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']) - $i = import_xchan($x['zot']); - else { - $z = z_fetch_url($link['href']); - if($z['success']) { - $j = json_decode($z['body'],true); - $i = import_xchan($j); - return true; + 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'] === PROTOCOL_ZOT) { + logger('discover_by_webbie: zot found for ' . $webbie, LOGGER_DEBUG); + if(array_key_exists('zot',$x) && $x['zot']['success']) + $i = import_xchan($x['zot']); + else { + $z = z_fetch_url($link['href']); + if($z['success']) { + $j = json_decode($z['body'],true); + $i = import_xchan($j); + return true; + } + } + } + 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']); } } + if($link['rel'] == 'salmon') { + $has_salmon = true; + $salmon = $link['href']; + } + if($link['rel'] == 'http://schemas.google.com/g/2010#updates-from') { + $atom_feed = $link['href']; + } } } } - $arr = array('address' => $webbie, 'success' => false); - call_hooks('discover_by_webbie', $arr); + 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; - $result = array(); - $network = null; - $diaspora = false; + $aliases = array(); + + // Now let's make some decisions on what we may need + // to obtain further info + + $probe_atom = false; + $probe_old = false; + $probe_hcard = false; + + $address = ''; + $location = ''; + $nickname = ''; + $fullname = ''; + $avatar = ''; + $pubkey = ''; + + if(is_array($x)) { + 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(! $x) + $probe_old = true; + + if($probe_old) { + $y = old_webfinger($webbie); + if($y) { + logger('old_webfinger: ' . print_r($x,true)); + foreach($y as $link) { + if($link['@attributes']['rel'] === NAMESPACE_DFRN) + $dfrn = unamp($link['@attributes']['href']); + if($link['@attributes']['rel'] === 'salmon') + $notify = unamp($link['@attributes']['href']); + if($link['@attributes']['rel'] === NAMESPACE_FEED) + $poll = unamp($link['@attributes']['href']); + if($link['@attributes']['rel'] === 'http://microformats.org/profile/hcard') + $hcard = unamp($link['@attributes']['href']); + if($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page') + $profile = unamp($link['@attributes']['href']); + if($link['@attributes']['rel'] === 'http://portablecontacts.net/spec/1.0') + $poco = unamp($link['@attributes']['href']); + if($link['@attributes']['rel'] === 'http://joindiaspora.com/seed_location') { + $diaspora_base = unamp($link['@attributes']['href']); + $diaspora = true; + } + if($link['@attributes']['rel'] === 'http://joindiaspora.com/guid') { + $diaspora_guid = unamp($link['@attributes']['href']); + $diaspora = true; + } + if($link['@attributes']['rel'] === 'diaspora-public-key') { + $diaspora_key = base64_decode(unamp($link['@attributes']['href'])); + if(strstr($diaspora_key,'RSA ')) + $pubkey = rsatopem($diaspora_key); + else + $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']; + } - $diaspora_base = ''; - $diaspora_guid = ''; - $diaspora_key = ''; - $dfrn = false; - - $x = old_webfinger($webbie); - if($x) { - logger('old_webfinger: ' . print_r($x,true)); - foreach($x as $link) { - if($link['@attributes']['rel'] === NAMESPACE_DFRN) - $dfrn = unamp($link['@attributes']['href']); - if($link['@attributes']['rel'] === 'salmon') - $notify = unamp($link['@attributes']['href']); - if($link['@attributes']['rel'] === NAMESPACE_FEED) - $poll = unamp($link['@attributes']['href']); - if($link['@attributes']['rel'] === 'http://microformats.org/profile/hcard') - $hcard = unamp($link['@attributes']['href']); - if($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page') - $profile = unamp($link['@attributes']['href']); - if($link['@attributes']['rel'] === 'http://portablecontacts.net/spec/1.0') - $poco = unamp($link['@attributes']['href']); - if($link['@attributes']['rel'] === 'http://joindiaspora.com/seed_location') { - $diaspora_base = unamp($link['@attributes']['href']); - $diaspora = true; - } - if($link['@attributes']['rel'] === 'http://joindiaspora.com/guid') { - $diaspora_guid = unamp($link['@attributes']['href']); - $diaspora = true; + 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($link['@attributes']['rel'] === 'diaspora-public-key') { - $diaspora_key = base64_decode(unamp($link['@attributes']['href'])); - if(strstr($diaspora_key,'RSA ')) - $pubkey = rsatopem($diaspora_key); - else - $pubkey = $diaspora_key; - $diaspora = true; + } + } + + 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'] : ''); } } - if($diaspora && $diaspora_base && $diaspora_guid) { - $guid = $diaspora_guid; - $diaspora_base = trim($diaspora_base,'/'); + $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,'@')); - $notify = $diaspora_base . '/receive'; + } - 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) - ); + 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) { - /** - * - * 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) - ); + // 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); + } + if($feed_meta['author']['author_name']) { + $fullname = $feed_meta['author']['author_name']; } - else { - - $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_pubkey, xchan_addr, xchan_url, xchan_name, xchan_network, xchan_instance_url, xchan_name_date ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ", - dbesc($addr), - dbesc($guid), - dbesc($pubkey), - dbesc($addr), - dbesc($profile), - dbesc($vcard['fn']), - dbesc($network), - dbesc(z_root()), - dbescdate(datetime_convert()) - ); + if(! $avatar) { + if($feed_meta['author']['author_photo']) + $avatar = $feed_meta['author']['author_photo']; } - $r = q("select * from hubloc where hubloc_hash = '%s' limit 1", - dbesc($webbie) - ); + // for GNU-social over-ride any url aliases we may have picked up in webfinger + // The author.uri element in the feed is likely to be more accurate + + if($gnusoc && $feed_meta['author']['author_uri']) + $location = $feed_meta['author']['author_uri']; + } + } + 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']; - 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('UTC','UTC',$arr['photo_updated'])), - 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) { +function webfinger_rfc7033($webbie,$zot = false) { - if(! strpos($webbie,'@')) - return false; - $lhs = substr($webbie,0,strpos($webbie,'@')); - $rhs = substr($webbie,strpos($webbie,'@')+1); - $resource = 'acct:' . $webbie; + if(strpos($webbie,'@')) { + $lhs = substr($webbie,0,strpos($webbie,'@')); + $rhs = substr($webbie,strpos($webbie,'@')+1); + $resource = 'acct:' . $webbie; + } + else { + $m = parse_url($webbie); + if($m) { + if($m['scheme'] !== 'https') + return false; + $rhs = $m['host'] . (($m['port']) ? ':' . $m['port'] : ''); + $resource = urlencode($webbie); + } + else + return false; + } + logger('fetching url from resource: ' . $rhs . ':' . $webbie); $s = z_fetch_url('https://' . $rhs . '/.well-known/webfinger?f=&resource=' . $resource . (($zot) ? '&zot=1' : '')); - if($s['success']) + if($s['success']) { $j = json_decode($s['body'],true); + + // We could have a number of URL aliases and webbies + // make an executive decision about the most likely "best" of each + // by comparing against some examples from known networks we're likely to encounter. + // Otherwise we have to store every alias that we may ever encounter and + // validate every URL we ever find against every possible alias + + // @fixme pump.io is going to be a real bugger since it doesn't return subject or aliases + // or provide lookup by url + + $j['address'] = find_webfinger_address($j,$rhs); + $j['location'] = find_webfinger_location($j,$rhs); + if($j['address']) + $j['nickname'] = substr($j['address'],0,strpos($j['address'],'@')); + } else return false; + return($j); } +function find_webfinger_address($j,$rhs) { + if(is_array($j) && ($j)) { + if(strpos($j['subject'],'acct:') !== false && strpos($j['subject'],'@' . $rhs)) + return str_replace('acct:','',$j['subject']); + if($j['aliases']) { + foreach($j['aliases'] as $alias) { + if(strpos($alias,'acct:') !== false && strpos($alias,'@' . $rhs)) { + return str_replace('acct:','',$alias); + } + } + } + } + return ''; +} + + +function find_webfinger_location($j,$rhs) { + if(is_array($j) && ($j)) { + if(strpos($j['subject'],'http') === 0) { + $x = match_webfinger_location($j['subject'],$rhs); + if($x) + return $x; + } + if($j['aliases']) { + foreach($j['aliases'] as $alias) { + if(strpos($alias,'http') === 0) { + $x = match_webfinger_location($alias,$rhs); + if($x) + return($x); + } + } + } + } + return ''; +} + +function match_webfinger_location($s,$h) { + + // 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)) + return $s; + // Friendica + if(preg_match('|' . $h . '/profile/|',$s)) + return $s; + + $arr = array('test' => $s, 'host' => $h, 'success' => false); + call_hooks('match_webfinger_location',$arr); + if($arr['success']) + return $s; + return ''; +} + + + + + + function old_webfinger($webbie) { @@ -1354,7 +1556,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)); @@ -1400,6 +1602,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; @@ -1451,8 +1657,25 @@ function scrape_vcard($url) { if(attribute_contains($item->getAttribute('class'), 'vcard')) { $level2 = $item->getElementsByTagName('*'); foreach($level2 as $x) { + if(attribute_contains($x->getAttribute('id'),'pod_location')) + $ret['pod_location'] = $x->textContent; if(attribute_contains($x->getAttribute('class'),'fn')) $ret['fn'] = $x->textContent; + if(attribute_contains($x->getAttribute('class'),'uid')) + $ret['uid'] = $x->textContent; + if(attribute_contains($x->getAttribute('class'),'nickname')) + $ret['nick'] = $x->textContent; + if(attribute_contains($x->getAttribute('class'),'searchable')) + $ret['searchable'] = $x->textContent; + if(attribute_contains($x->getAttribute('class'),'key')) + $ret['public_key'] = $x->textContent; + if(attribute_contains($x->getAttribute('class'),'given_name')) + $ret['given_name'] = $x->textContent; + if(attribute_contains($x->getAttribute('class'),'family_name')) + $ret['family_name'] = $x->textContent; + if(attribute_contains($x->getAttribute('class'),'url')) + $ret['url'] = $x->textContent; + if((attribute_contains($x->getAttribute('class'),'photo')) || (attribute_contains($x->getAttribute('class'),'avatar'))) { $size = intval($x->getAttribute('width')); @@ -1461,10 +1684,6 @@ function scrape_vcard($url) { $largest_photo = $size; } } - if((attribute_contains($x->getAttribute('class'),'nickname')) - || (attribute_contains($x->getAttribute('class'),'uid'))) { - $ret['nick'] = $x->textContent; - } } } } @@ -1615,18 +1834,19 @@ function format_and_send_email($sender,$xchan,$item) { // load the template for private message notifications $tpl = get_markup_template('email_notify_html.tpl'); $email_html_body = replace_macros($tpl,array( - '$banner' => $banner, - '$product' => $product, - '$preamble' => '', - '$sitename' => $sitename, - '$siteurl' => $siteurl, + '$banner' => $banner, + '$notify_icon' => Zotlabs\Project\System::get_notify_icon(), + '$product' => $product, + '$preamble' => '', + '$sitename' => $sitename, + '$siteurl' => $siteurl, '$source_name' => $sender['xchan_name'], '$source_link' => $sender['xchan_url'], '$source_photo' => $sender['xchan_photo_m'], - '$username' => $xchan['xchan_name'], + '$username' => $xchan['xchan_name'], '$hsitelink' => $datarray['hsitelink'], '$hitemlink' => $datarray['hitemlink'], - '$thanks' => $thanks, + '$thanks' => $thanks, '$site_admin' => $site_admin, '$title' => $title, '$htmlversion' => $htmlversion, @@ -1635,26 +1855,26 @@ function format_and_send_email($sender,$xchan,$item) { // load the template for private message notifications $tpl = get_markup_template('email_notify_text.tpl'); $email_text_body = replace_macros($tpl, array( - '$banner' => $banner, - '$product' => $product, - '$preamble' => '', - '$sitename' => $sitename, - '$siteurl' => $siteurl, + '$banner' => $banner, + '$product' => $product, + '$preamble' => '', + '$sitename' => $sitename, + '$siteurl' => $siteurl, '$source_name' => $sender['xchan_name'], '$source_link' => $sender['xchan_url'], '$source_photo' => $sender['xchan_photo_m'], - '$username' => $xchan['xchan_name'], - '$hsitelink' => $datarray['hsitelink'], - '$hitemlink' => $datarray['hitemlink'], - '$thanks' => $thanks, + '$username' => $xchan['xchan_name'], + '$hsitelink' => $datarray['hsitelink'], + '$hitemlink' => $datarray['hitemlink'], + '$thanks' => $thanks, '$site_admin' => $site_admin, - '$title' => $title, + '$title' => $title, '$textversion' => $textversion )); $sender_name = t('Administrator'); - $hostname = get_app()->get_hostname(); + $hostname = App::get_hostname(); if(strpos($hostname,':')) $hostname = substr($hostname,0,strpos($hostname,':')); $sender_email = 'noreply' . '@' . $hostname; @@ -1662,13 +1882,13 @@ function format_and_send_email($sender,$xchan,$item) { // use the EmailNotification library to send the message enotify::send(array( - 'fromName' => $product, - 'fromEmail' => $sender_email, - 'replyTo' => $sender_email, - 'toEmail' => str_replace('mailto:','',$xchan['xchan_addr']), - 'messageSubject' => (($title) ? $title : t('No Subject')), - 'htmlVersion' => $email_html_body, - 'textVersion' => $email_text_body, + 'fromName' => $product, + 'fromEmail' => $sender_email, + 'replyTo' => $sender_email, + 'toEmail' => str_replace('mailto:','',$xchan['xchan_addr']), + 'messageSubject' => (($title) ? $title : t('No Subject')), + 'htmlVersion' => $email_html_body, + 'textVersion' => $email_text_body, 'additionalMailHeader' => '', )); @@ -1717,7 +1937,7 @@ function get_site_info() { global $a; $register_policy = Array('REGISTER_CLOSED', 'REGISTER_APPROVE', 'REGISTER_OPEN'); - $directory_mode = Array('DIRECTORY_MODE_NORMAL', 'DIRECTORY_MODE_SECONDARY','DIRECTORY_MODE_PRIMARY', 256 => 'DIRECTORY_MODE_STANDALONE'); + $directory_mode = Array('DIRECTORY_MODE_NORMAL', 'DIRECTORY_MODE_PRIMARY', 'DIRECTORY_MODE_SECONDARY', 256 => 'DIRECTORY_MODE_STANDALONE'); $sql_extra = ''; @@ -1728,11 +1948,11 @@ function get_site_info() { $admin = array(); foreach($r as $rr) { if($rr['channel_pageflags'] & PAGE_HUBADMIN) - $admin[] = array( 'name' => $rr['channel_name'], 'address' => $rr['channel_address'] . '@' . get_app()->get_hostname(), 'channel' => z_root() . '/channel/' . $rr['channel_address']); + $admin[] = array( 'name' => $rr['channel_name'], 'address' => $rr['channel_address'] . '@' . App::get_hostname(), 'channel' => z_root() . '/channel/' . $rr['channel_address']); } if(! $admin) { foreach($r as $rr) { - $admin[] = array( 'name' => $rr['channel_name'], 'address' => $rr['channel_address'] . '@' . get_app()->get_hostname(), 'channel' => z_root() . '/channel/' . $rr['channel_address']); + $admin[] = array( 'name' => $rr['channel_name'], 'address' => $rr['channel_address'] . '@' . App::get_hostname(), 'channel' => z_root() . '/channel/' . $rr['channel_address']); } } } @@ -1747,7 +1967,7 @@ function get_site_info() { $service_class = false; $visible_plugins = array(); - if(is_array($a->plugins) && count($a->plugins)) { + if(is_array(App::$plugins) && count(App::$plugins)) { $r = q("select * from addon where hidden = 0"); if(count($r)) foreach($r as $rr) @@ -1763,16 +1983,13 @@ function get_site_info() { $site_info = get_config('system','info'); $site_name = get_config('system','sitename'); if(! get_config('system','hidden_version_siteinfo')) { - $version = RED_VERSION; - $tag = get_std_version(); + $version = Zotlabs\Project\System::get_project_version(); + $tag = Zotlabs\Project\System::get_std_version(); if(@is_dir('.git') && function_exists('shell_exec')) { $commit = trim( @shell_exec('git log -1 --format="%h"')); -// if(! get_config('system','hidden_tag_siteinfo')) -// $tag = trim( @shell_exec('git describe --tags --abbrev=0')); -// else -// $tag = ''; } + if(! isset($commit) || strlen($commit) > 16) $commit = ''; } @@ -1788,10 +2005,22 @@ function get_site_info() { $hide_in_statistics = intval(get_config('system','hide_in_statistics')); $site_expire = intval(get_config('system', 'default_expire_days')); + load_config('feature_lock'); + $locked_features = array(); + if(is_array(App::$config['feature_lock']) && count(App::$config['feature_lock'])) { + foreach(App::$config['feature_lock'] as $k => $v) { + if($k === 'config_loaded') + continue; + $locked_features[$k] = intval($v); + } + } + + $data = Array( 'version' => $version, 'version_tag' => $tag, + 'server_role' => Zotlabs\Project\System::get_server_role(), 'commit' => $commit, 'url' => z_root(), 'plugins' => $visible_plugins, @@ -1799,12 +2028,13 @@ function get_site_info() { 'invitation_only' => intval(get_config('system','invitation_only')), 'directory_mode' => $directory_mode[get_config('system','directory_mode')], 'language' => get_config('system','language'), - 'rss_connections' => get_config('system','feed_contacts'), + 'rss_connections' => intval(get_config('system','feed_contacts')), 'expiration' => $site_expire, 'default_service_restrictions' => $service_class, + 'locked_features' => $locked_features, 'admin' => $admin, 'site_name' => (($site_name) ? $site_name : ''), - 'platform' => PLATFORM_NAME, + 'platform' => Zotlabs\Project\System::get_platform_name(), 'dbdriver' => $db->getdriver(), 'lastpoll' => get_config('system','lastpoll'), 'info' => (($site_info) ? $site_info : ''), |