diff options
Diffstat (limited to 'include/network.php')
-rw-r--r-- | include/network.php | 804 |
1 files changed, 144 insertions, 660 deletions
diff --git a/include/network.php b/include/network.php index c03ca70f5..d3ccc498d 100644 --- a/include/network.php +++ b/include/network.php @@ -343,7 +343,7 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) { if (isset($url_parsed)) { curl_close($ch); if($http_code == 303) { - return z_fetch_url($newurl,false,$redirects++,$opts); + return z_fetch_url($newurl,false,++$redirects,$opts); } else { return z_post_url($newurl,$params,++$redirects,$opts); } @@ -397,31 +397,6 @@ function json_return_and_die($x, $content_type = 'application/json') { killme(); } - -/** - * @brief Generic XML return. - * - * Outputs a basic dfrn XML status structure to STDOUT, with a <status> variable - * of $st and an optional text <message> of $message and terminates the current - * process. - * - * @param string $st - * @param string $message - */ -function xml_status($st, $message = '') { - - $xml_message = ((strlen($message)) ? "\t<message>" . xmlify($message) . "</message>\r\n" : ''); - - if($st) - logger('Returning non_zero: ' . $st . " message=" . $message); - - header( "Content-type: text/xml" ); - echo '<?xml version="1.0" encoding="UTF-8"?>'."\r\n"; - echo "<result>\r\n\t<status>$st</status>\r\n$xml_message</result>\r\n"; - killme(); -} - - /** * @brief Send HTTP status header. * @@ -1007,39 +982,6 @@ function email_header_encode($in_str, $charset = 'UTF-8') { return $out_str; } -function email_send($addr, $subject, $headers, $item) { - //$headers .= 'MIME-Version: 1.0' . "\n"; - //$headers .= 'Content-Type: text/html; charset=UTF-8' . "\n"; - //$headers .= 'Content-Type: text/plain; charset=UTF-8' . "\n"; - //$headers .= 'Content-Transfer-Encoding: 8bit' . "\n\n"; - - $part = uniqid("", true); - - $html = prepare_body($item); - - $headers .= "Mime-Version: 1.0\n"; - $headers .= 'Content-Type: multipart/alternative; boundary="=_'.$part.'"'."\n\n"; - - $body = "\n--=_".$part."\n"; - $body .= "Content-Transfer-Encoding: 8bit\n"; - $body .= "Content-Type: text/plain; charset=utf-8; format=flowed\n\n"; - - $body .= html2plain($html)."\n"; - - $body .= "--=_".$part."\n"; - $body .= "Content-Transfer-Encoding: 8bit\n"; - $body .= "Content-Type: text/html; charset=utf-8\n\n"; - - $body .= '<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">'.$html."</body></html>\n"; - - $body .= "--=_".$part."--"; - - //$message = '<html><body>' . $html . '</body></html>'; - //$message = html2plain($html); - logger('notifier: email delivery to ' . $addr); - mail($addr, $subject, $body, $headers); -} - /** * @brief Creates an xchan entry for URL. * @@ -1056,10 +998,10 @@ function discover_by_url($url, $arr = null) { return false; $network = (($arr['network']) ? $arr['network'] : 'unknown'); - $name = (($arr['name']) ? $arr['name'] : 'unknown'); - $photo = (($arr['photo']) ? $arr['photo'] : ''); - $addr = (($arr['addr']) ? $arr['addr'] : ''); - $guid = $url; + $name = (($arr['name']) ? $arr['name'] : 'unknown'); + $photo = (($arr['photo']) ? $arr['photo'] : ''); + $addr = (($arr['addr']) ? $arr['addr'] : ''); + $guid = $url; } $profile = $url; @@ -1095,8 +1037,8 @@ function discover_by_url($url, $arr = null) { if($feed->error()) logger('scrape_feed: Error parsing XML: ' . $feed->error()); - $name = unxmlify(trim($feed->get_title())); - $photo = $feed->get_image_url(); + $name = unxmlify(trim($feed->get_title())); + $photo = $feed->get_image_url(); $author = $feed->get_author(); if($author) { @@ -1195,23 +1137,11 @@ function discover_by_url($url, $arr = null) { } function discover_by_webbie($webbie) { - require_once('library/HTML5/Parser.php'); - $result = array(); + $result = []; $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); @@ -1237,21 +1167,6 @@ 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']); - } - } - 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']; - } } } } @@ -1263,275 +1178,9 @@ function discover_by_webbie($webbie) { if($arr['success']) return true; - $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((! $dfrn) && (! $has_salmon)) - $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']; - } - - 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($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'] : ''); - } - } - - $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($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); - } - 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']; - } - - // 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(($vcard['public_key']) && (! $pubkey)) { - $diaspora_key = $vcard['public_key']; - if(strstr($diaspora_key,'RSA ')) - $pubkey = rsatopem($diaspora_key); - else - $pubkey = $diaspora_key; - } - if(! $avatar) - $avatar = $vcard['photo']; - if($diaspora) { - if(($vcard['uid']) && (! $diaspora_guid)) - $diaspora_guid = $vcard['uid']; - if(($vcard['url']) && (! $diaspora_base)) - $diaspora_base = $vcard['url']; - } - } - } - } - - 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; - } - } - - 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'", - dbesc($fullname), - dbesc($network), - dbesc(datetime_convert()), - dbesc($address) - ); - } - else { - $r = xchan_store_lowlevel( - [ - 'xchan_hash' => $address, - 'xchan_guid' => (($diaspora_guid) ? $diaspora_guid : $location), - 'xchan_pubkey' => $pubkey, - 'xchan_addr' => $address, - 'xchan_url' => $location, - 'xchan_name' => $fullname, - 'xchan_name_date' => datetime_convert(), - 'xchan_network' => $network - ] - ); - } - - $r = q("select * from hubloc where hubloc_hash = '%s' limit 1", - dbesc($address) - ); - - if(! $r) { - $r = hubloc_store_lowlevel( - [ - 'hubloc_guid' => (($diaspora_guid) ? $diaspora_guid : $location), - 'hubloc_hash' => $address, - 'hubloc_addr' => $address, - 'hubloc_network' => $network, - 'hubloc_url' => $base, - 'hubloc_host' => $host, - 'hubloc_callback' => $notify, - 'hubloc_updated' => datetime_convert(), - 'hubloc_primary' => 1 - ] - ); - } - $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) { @@ -1557,105 +1206,22 @@ function webfinger_rfc7033($webbie,$zot = false) { // and results in a 406 (Not Acceptable) response, and will also incorrectly produce an XML // document if you use 'application/jrd+json, */*'. We could set this to application/jrd+json, // but some test webfinger servers may not explicitly set the content type and they would be - // blocked. The best compromise until Mastodon is fixed is to remove the Accept header which is - // accomplished by setting it to nothing. + // blocked. The best compromise until Mastodon is fixed is to remove the Accept header which is + // accomplished by setting it to nothing. $counter = 0; - $s = z_fetch_url('https://' . $rhs . '/.well-known/webfinger?f=&resource=' . $resource . (($zot) ? '&zot=1' : ''), + $s = z_fetch_url('https://' . $rhs . '/.well-known/webfinger?f=&resource=' . $resource . (($zot) ? '&zot=1' : ''), false, $counter, [ 'headers' => [ 'Accept:' ] ]); 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'],'@')); + return($j); } - 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 ''; -} - -/** - * @brief Match the webfinger location for the different networks. - * - * @param string $s The string to search in - * @param string $h The host - * @return string - */ -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 false; - return ''; } - - - - function old_webfinger($webbie) { $host = ''; @@ -1723,9 +1289,6 @@ function fetch_xrd_links($url) { 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(); @@ -1765,89 +1328,13 @@ function fetch_xrd_links($url) { } -function scrape_vcard($url) { - - $ret = array(); - - logger('url=' . $url); - - $x = z_fetch_url($url); - if(! $x['success']) - return $ret; - - $s = $x['body']; - - if(! $s) - return $ret; - - $headers = $x['header']; - $lines = explode("\n",$headers); - if(count($lines)) { - foreach($lines as $line) { - // 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 ret; - } - } - - try { - $dom = HTML5_Parser::parse($s); - } catch (DOMException $e) { - logger('Parse error: ' . $e); - } - - if(! $dom) - return $ret; - - // Pull out hCard profile elements - - $largest_photo = 0; - - $items = $dom->getElementsByTagName('*'); - foreach($items as $item) { - 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')); - if(($size > $largest_photo) || (! $largest_photo)) { - $ret['photo'] = $x->getAttribute('src'); - $largest_photo = $size; - } - } - } - } - } - - return $ret; -} - /** * @brief * * @param string $url The URL to scrape * @return array */ + function scrape_feed($url) { require_once('library/HTML5/Parser.php'); @@ -1941,112 +1428,6 @@ function scrape_feed($url) { -function service_plink($contact, $guid) { - - $plink = ''; - - $m = parse_url($contact['xchan_url']); - if($m) { - $url = $m['scheme'] . '://' . $m['host'] . (($m['port']) ? ':' . $m['port'] : ''); - } - else - $url = 'https://' . substr($contact['xchan_addr'],strpos($contact['xchan_addr'],'@')+1); - - $handle = substr($contact['xchan_addr'], 0, strpos($contact['xchan_addr'],'@')); - - if($contact['xchan_network'] === 'diaspora') - $plink = $url . '/posts/' . $guid; - if($contact['xchan_network'] === 'friendica-over-diaspora') - $plink = $url . '/display/' . $handle . '/' . $guid; - if($contact['xchan_network'] === 'zot') - $plink = $url . '/channel/' . $handle . '?f=&mid=' . $guid; - - return $plink; -} - - -function format_and_send_email($sender,$xchan,$item) { - - $title = $item['title']; - $body = $item['body']; - - $textversion = strip_tags(html_entity_decode(bbcode(str_replace(array("\\r", "\\n"), array( "", "\n"), $body)),ENT_QUOTES,'UTF-8')); - - $htmlversion = bbcode(str_replace(array("\\r","\\n"), array("","<br />\n"),$body)); - - $banner = t('$Projectname Notification'); - $product = t('$projectname'); // PLATFORM_NAME; - $siteurl = z_root(); - $thanks = t('Thank You,'); - $sitename = get_config('system', 'sitename'); - $site_admin = sprintf( t('%s Administrator'), $sitename); - - // load the template for private message notifications - $tpl = get_markup_template('email_notify_html.tpl'); - $email_html_body = replace_macros($tpl, array( - '$banner' => $banner, - '$notify_icon' => Zotlabs\Lib\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'], - '$hsitelink' => $datarray['hsitelink'], /// @FIXME $datarray is undefined - '$hitemlink' => $datarray['hitemlink'], /// @FIXME $datarray is undefined - '$thanks' => $thanks, - '$site_admin' => $site_admin, - '$title' => $title, - '$htmlversion' => $htmlversion, - )); - - // 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, - '$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, - '$site_admin' => $site_admin, - '$title' => $title, - '$textversion' => $textversion - )); - - $sender_name = t('Administrator'); - - $hostname = App::get_hostname(); - if(strpos($hostname, ':')) - $hostname = substr($hostname,0,strpos($hostname,':')); - - $sender_email = get_config('system', 'reply_address'); - if(! $sender_email) - $sender_email = 'noreply' . '@' . $hostname; - - // use the EmailNotification library to send the message - - Zotlabs\Lib\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, - 'additionalMailHeader' => '', - )); -} - - function do_delivery($deliveries) { if(! (is_array($deliveries) && count($deliveries))) @@ -2160,33 +1541,33 @@ function get_site_info() { } - $data = Array( - 'version' => $version, - 'version_tag' => $tag, - 'server_role' => Zotlabs\Lib\System::get_server_role(), - 'commit' => $commit, - 'url' => z_root(), - 'plugins' => $visible_plugins, - 'register_policy' => $register_policy[get_config('system','register_policy')], - 'invitation_only' => intval(get_config('system','invitation_only')), - 'directory_mode' => $directory_mode[get_config('system','directory_mode')], - 'language' => get_config('system','language'), - 'rss_connections' => intval(get_config('system','feed_contacts')), - 'expiration' => $site_expire, + $data = [ + 'url' => z_root(), + 'platform' => Zotlabs\Lib\System::get_platform_name(), + 'site_name' => (($site_name) ? $site_name : ''), + 'version' => $version, + 'version_tag' => $tag, + 'server_role' => Zotlabs\Lib\System::get_server_role(), + 'commit' => $commit, + 'plugins' => $visible_plugins, + 'register_policy' => $register_policy[get_config('system','register_policy')], + 'invitation_only' => intval(get_config('system','invitation_only')), + 'directory_mode' => $directory_mode[get_config('system','directory_mode')], + 'language' => get_config('system','language'), + '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' => Zotlabs\Lib\System::get_platform_name(), - 'dbdriver' => DBA::$dba->getdriver(), - 'lastpoll' => get_config('system','lastpoll'), - 'info' => (($site_info) ? $site_info : ''), - 'channels_total' => $channels_total_stat, - 'channels_active_halfyear' => $channels_active_halfyear_stat, - 'channels_active_monthly' => $channels_active_monthly_stat, - 'local_posts' => $local_posts_stat, - 'hide_in_statistics' => $hide_in_statistics - ); + 'locked_features' => $locked_features, + 'admin' => $admin, + 'dbdriver' => DBA::$dba->getdriver(), + 'lastpoll' => get_config('system','lastpoll'), + 'info' => (($site_info) ? $site_info : ''), + 'channels_total' => $channels_total_stat, + 'channels_active_halfyear' => $channels_active_halfyear_stat, + 'channels_active_monthly' => $channels_active_monthly_stat, + 'local_posts' => $local_posts_stat, + 'hide_in_statistics' => $hide_in_statistics + ]; return $data; } @@ -2412,3 +1793,106 @@ function probe_api_path($host) { return ''; } + + +function scrape_vcard($url) { + + require_once('library/HTML5/Parser.php'); + + $ret = array(); + + logger('url=' . $url); + + $x = z_fetch_url($url); + if(! $x['success']) + return $ret; + + $s = $x['body']; + + if(! $s) + return $ret; + + $headers = $x['header']; + $lines = explode("\n",$headers); + if(count($lines)) { + foreach($lines as $line) { + // 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 ret; + } + } + + try { + $dom = HTML5_Parser::parse($s); + } catch (DOMException $e) { + logger('Parse error: ' . $e); + } + + if(! $dom) + return $ret; + + // Pull out hCard profile elements + + $largest_photo = 0; + + $items = $dom->getElementsByTagName('*'); + foreach($items as $item) { + 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')); + if(($size > $largest_photo) || (! $largest_photo)) { + $ret['photo'] = $x->getAttribute('src'); + $largest_photo = $size; + } + } + } + } + } + + return $ret; +} + +function service_plink($contact, $guid) { + + $plink = ''; + + $m = parse_url($contact['xchan_url']); + if($m) { + $url = $m['scheme'] . '://' . $m['host'] . (($m['port']) ? ':' . $m['port'] : ''); + } + else { + $url = 'https://' . substr($contact['xchan_addr'],strpos($contact['xchan_addr'],'@')+1); + } + + $handle = substr($contact['xchan_addr'], 0, strpos($contact['xchan_addr'],'@')); + + $plink = $url . '/channel/' . $handle . '?f=&mid=' . $guid; + + $x = [ 'xchan' => $contact, 'guid' => $guid, '$url' => $url, 'plink' => $plink ]; + call_hooks('service_plink', $x); + + return $x['plink']; +} + |