aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/attach.php12
-rw-r--r--include/bbcode.php2
-rw-r--r--include/checksites.php61
-rw-r--r--include/conversation.php4
-rw-r--r--include/deliver.php4
-rw-r--r--include/hubloc.php32
-rwxr-xr-xinclude/items.php4
-rw-r--r--include/nav.php4
-rw-r--r--include/network.php20
-rw-r--r--include/notifier.php57
-rw-r--r--include/poller.php3
-rw-r--r--include/zot.php349
12 files changed, 475 insertions, 77 deletions
diff --git a/include/attach.php b/include/attach.php
index 513486bfc..39fdb5c3a 100644
--- a/include/attach.php
+++ b/include/attach.php
@@ -1132,7 +1132,7 @@ function attach_mkdirp($channel, $observer_hash, $arr = null) {
*/
function attach_change_permissions($channel_id, $resource, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $recurse = false) {
- $r = q("select hash, flags, is_dir from attach where hash = '%s' and uid = %d limit 1",
+ $r = q("select hash, flags, is_dir, is_photo from attach where hash = '%s' and uid = %d limit 1",
dbesc($resource),
intval($channel_id)
);
@@ -1162,6 +1162,16 @@ function attach_change_permissions($channel_id, $resource, $allow_cid, $allow_gi
dbesc($resource),
intval($channel_id)
);
+ if($r[0]['is_photo']) {
+ $x = q("update photo set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where resource_id = '%s' and uid = %d",
+ dbesc($allow_cid),
+ dbesc($allow_gid),
+ dbesc($deny_cid),
+ dbesc($deny_gid),
+ dbesc($resource),
+ intval($channel_id)
+ );
+ }
}
/**
diff --git a/include/bbcode.php b/include/bbcode.php
index 66bf6b5ec..db5824237 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -437,7 +437,7 @@ function bb_observer($Text) {
// BBcode 2 HTML was written by WAY2WEB.net
- // extended to work with Mistpark/Friendica/Red - Mike Macgirvin
+ // extended to work with Mistpark/Friendica/Redmatrix/Hubzilla - Mike Macgirvin
function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false) {
diff --git a/include/checksites.php b/include/checksites.php
new file mode 100644
index 000000000..e14837255
--- /dev/null
+++ b/include/checksites.php
@@ -0,0 +1,61 @@
+<?php /** @file */
+
+require_once('boot.php');
+require_once('include/cli_startup.php');
+require_once('include/zot.php');
+require_once('include/hubloc.php');
+
+
+
+function checksites_run($argv, $argc){
+
+
+ cli_startup();
+ $a = get_app();
+
+ logger('checksites: start');
+
+ if(($argc > 1) && ($argv[1]))
+ $site_id = $argv[1];
+
+ if($site_id)
+ $sql_options = " and site_url = '" . dbesc($argv[1]) . "' ";
+
+ $days = intval(get_config('system','sitecheckdays'));
+ if($days < 1)
+ $days = 30;
+
+ $r = q("select * from site where site_dead = 0 and site_update < %s - INTERVAL %s $sql_options ",
+ db_utcnow(), db_quoteinterval($days . ' DAY')
+ );
+
+ if(! $r)
+ return;
+
+ foreach($r as $rr) {
+ if(! strcasecmp($rr['site_url'],z_root()))
+ continue;
+
+ $x = ping_site($rr['site_url']);
+ if($x['success']) {
+ logger('checksites: ' . $rr['site_url']);
+ q("update site set site_update = '%s' where site_url = '%s' ",
+ dbesc(datetime_convert()),
+ dbesc($rr['site_url'])
+ );
+ }
+ else {
+ logger('marking dead site: ' . $x['message']);
+ q("update site set site_dead = 1 where site_url = '%s' ",
+ dbesc($rr['site_url'])
+ );
+ }
+ }
+
+ return;
+}
+
+if (array_search(__file__,get_included_files())===0){
+ checksites_run($argv,$argc);
+ killme();
+}
diff --git a/include/conversation.php b/include/conversation.php
index fb8ef8585..0f6f8685b 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -943,9 +943,9 @@ function item_photo_menu($item){
t("View Status") => $status_link,
t("View Profile") => $profile_link,
t("View Photos") => $photos_link,
- t("Matrix Activity") => $posts_link,
+ t("Activity/Posts") => $posts_link,
t("Connect") => $follow_url,
- t("Edit Contact") => $contact_url,
+ t("Edit Connection") => $contact_url,
t("Send PM") => $pm_url,
t("Poke") => $poke_link
);
diff --git a/include/deliver.php b/include/deliver.php
index 5ab44a620..26739fb06 100644
--- a/include/deliver.php
+++ b/include/deliver.php
@@ -92,12 +92,12 @@ function deliver_run($argv, $argc) {
$m = json_decode($r[0]['outq_msg'],true);
if(array_key_exists('message_list',$m)) {
foreach($m['message_list'] as $mm) {
- $msg = array('body' => json_encode(array('pickup' => array(array('notify' => $notify,'message' => $mm)))));
+ $msg = array('body' => json_encode(array('success' => true, 'pickup' => array(array('notify' => $notify,'message' => $mm)))));
zot_import($msg,z_root());
}
}
else {
- $msg = array('body' => json_encode(array('pickup' => array(array('notify' => $notify,'message' => $m)))));
+ $msg = array('body' => json_encode(array('success' => true, 'pickup' => array(array('notify' => $notify,'message' => $m)))));
zot_import($msg,z_root());
}
$r = q("delete from outq where outq_hash = '%s'",
diff --git a/include/hubloc.php b/include/hubloc.php
index 396f4ddfa..674a3885f 100644
--- a/include/hubloc.php
+++ b/include/hubloc.php
@@ -275,4 +275,34 @@ function xchan_fetch($arr) {
$ret[str_replace('xchan_','',$k)] = $v;
}
return $ret;
-} \ No newline at end of file
+}
+
+
+
+function ping_site($url) {
+
+ $ret = array('success' => false);
+
+ $sys = get_sys_channel();
+
+ $m = zot_build_packet($sys,'ping');
+ $r = zot_zot($url . '/post',$m);
+ if(! $r['success']) {
+ $ret['message'] = 'no answer from ' . $url;
+ return $ret;
+ }
+ $packet_result = json_decode($r['body'],true);
+ if(! $packet_result['success']) {
+ $ret['message'] = 'packet failure from ' . $url;
+ return $ret;
+ }
+
+ if($packet_result['success']) {
+ $ret['success'] = true;
+ }
+ else {
+ $ret['message'] = 'unknown error from ' . $url;
+ }
+
+ return $ret;
+}
diff --git a/include/items.php b/include/items.php
index 28fd8502b..657168601 100755
--- a/include/items.php
+++ b/include/items.php
@@ -3441,6 +3441,8 @@ function post_is_importable($item,$abook) {
if($exclude) {
foreach($exclude as $word) {
$word = trim($word);
+ if(! $word)
+ continue;
if(substr($word,0,1) === '#' && $tags) {
foreach($tags as $t)
if(($t['type'] == TERM_HASHTAG) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
@@ -3460,6 +3462,8 @@ function post_is_importable($item,$abook) {
if($include) {
foreach($include as $word) {
$word = trim($word);
+ if(! $word)
+ continue;
if(substr($word,0,1) === '#' && $tags) {
foreach($tags as $t)
if(($t['type'] == TERM_HASHTAG) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
diff --git a/include/nav.php b/include/nav.php
index 898805bba..59a7c83a3 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -172,8 +172,8 @@ EOT;
if(local_channel()) {
- $nav['network'] = array('network', t('Matrix'), "", t('Your matrix'),'network_nav_btn');
- $nav['network']['mark'] = array('', t('Mark all matrix notifications seen'), '','');
+ $nav['network'] = array('network', t('Grid'), "", t('Your grid'),'network_nav_btn');
+ $nav['network']['mark'] = array('', t('Mark all grid notifications seen'), '','');
$nav['home'] = array('channel/' . $channel['channel_address'], t('Channel Home'), "", t('Channel home'),'home_nav_btn');
$nav['home']['mark'] = array('', t('Mark all channel notifications seen'), '','');
diff --git a/include/network.php b/include/network.php
index d3320f3ee..41e1ff37c 100644
--- a/include/network.php
+++ b/include/network.php
@@ -1053,16 +1053,20 @@ function discover_by_webbie($webbie) {
$webbie = strtolower($webbie);
- $x = webfinger_rfc7033($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);
- $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('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;
+ }
}
}
}
@@ -1282,7 +1286,7 @@ LSIeXnd14lQYK/uxW/8cTFjcmddsKxeXysoQxbSa9VdDK+KkpZdgYXYrTTofXs6v+
}
-function webfinger_rfc7033($webbie) {
+function webfinger_rfc7033($webbie,$zot = false) {
if(! strpos($webbie,'@'))
@@ -1292,7 +1296,7 @@ function webfinger_rfc7033($webbie) {
$resource = 'acct:' . $webbie;
- $s = z_fetch_url('https://' . $rhs . '/.well-known/webfinger?resource=' . $resource);
+ $s = z_fetch_url('https://' . $rhs . '/.well-known/webfinger?f=&resource=' . $resource . (($zot) ? '&zot=1' : ''));
if($s['success'])
$j = json_decode($s['body'],true);
diff --git a/include/notifier.php b/include/notifier.php
index 62aea4106..e16f80ecf 100644
--- a/include/notifier.php
+++ b/include/notifier.php
@@ -486,20 +486,6 @@ function notifier_run($argv, $argc){
if($details) {
foreach($details as $d) {
- // If the recipient is federated from a traditional network they won't be able to
- // handle nomadic identity. If we're publishing from a site that they aren't
- // directly connected with, ignore them.
-
- // FIXME: make sure we run through a notifier loop on the hub they're connected
- // with if this post comes in from a different hub - so that we will deliver to them.
-
- // On the down side, these channels will stop working if the hub they connected with
- // goes down permanently, as they are (doh) not nomadic.
-
- if(($d['xchan_instance_url']) && ($d['xchan_instance_url'] != z_root()))
- continue;
-
-
$recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')';
if($private)
$env_recips[] = array('guid' => $d['xchan_guid'],'guid_sig' => $d['xchan_guid_sig'],'hash' => $d['xchan_hash']);
@@ -526,31 +512,10 @@ function notifier_run($argv, $argc){
// Now we have collected recipients (except for external mentions, FIXME)
// Let's reduce this to a set of hubs.
- logger('notifier: hub choice: ' . intval($relay_to_owner) . ' ' . intval($private) . ' ' . $cmd, LOGGER_DEBUG);
-
- // FIXME: I think we need to remove the private bit or this clause will never execute. Needs more coffee to think it through.
- // We may in fact have to send it to clones in case the one we pick recently died.
-
- if($relay_to_owner && (! $private) && ($cmd !== 'relay')) {
-
- // If sending a followup to the post owner, only send it to one channel clone - to avoid race conditions.
- // In this case we'll pick the most recently contacted hub, as their primary might be down and the most
- // recently contacted has the best chance of being alive.
-
- // For private posts or uplinks we have to do things differently as only the sending clone will have the recipient list.
- // We have to send to all clone channels of the owner to find out who has the definitive list. Posts with
- // item_private set (but no ACL list) will return empty recipients (except for the sender and owner) in
- // collect_recipients() above. The end result is we should get only one delivery per delivery chain if we
- // aren't the owner or author.
-
-
- $r = q("select * from hubloc
- where hubloc_hash in (" . implode(',',$recipients) . ") order by hubloc_connected desc limit 1");
- }
- else {
- $r = q("select * from hubloc where hubloc_hash in (" . implode(',',$recipients) . ")
- and hubloc_error = 0 and hubloc_deleted = 0");
- }
+ $r = q("select * from hubloc where hubloc_hash in (" . implode(',',$recipients) . ")
+ and hubloc_error = 0 and hubloc_deleted = 0"
+ );
+
if(! $r) {
logger('notifier: no hubs');
@@ -559,6 +524,15 @@ function notifier_run($argv, $argc){
$hubs = $r;
+ $dead_hubs = array();
+
+ $dh = q("select site_url from site where site_dead = 1");
+ if(dh) {
+ foreach($dh as $dead) {
+ $dead_hubs[] = $dead['site_url'];
+ }
+ }
+
/**
* Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey, since it may have been
@@ -574,6 +548,11 @@ function notifier_run($argv, $argc){
foreach($hubs as $hub) {
+ if(in_array($hub['hubloc_url'],$dead_hubs)) {
+ logger('skipping dead hub: ' . $hub['hubloc_url'], LOGGER_DEBUG);
+ continue;
+ }
+
if($hub['hubloc_network'] == 'zot') {
if(! in_array($hub['hubloc_sitekey'],$keys)) {
$hublist[] = $hub['hubloc_host'];
diff --git a/include/poller.php b/include/poller.php
index a1b25bf41..72f22d946 100644
--- a/include/poller.php
+++ b/include/poller.php
@@ -175,7 +175,10 @@ function poller_run($argv, $argc){
logger('regdir: ' . print_r(z_fetch_url(get_directory_primary() . '/regdir?f=&url=' . urlencode(z_root()) . '&realm=' . urlencode(get_directory_realm())),true));
}
+ // Check for dead sites
+ proc_run('php', 'include/checksites.php');
+ // update searchable doc indexes
proc_run('php', 'include/importdoc.php');
/**
diff --git a/include/zot.php b/include/zot.php
index 0e00f39b4..ebdcb4cfb 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -537,7 +537,7 @@ function zot_refresh($them, $channel = null, $force = false) {
* @returns array|null null if site is blacklisted or not found, otherwise an
* array with an hubloc record
*/
-function zot_gethub($arr) {
+function zot_gethub($arr,$multiple = false) {
if($arr['guid'] && $arr['guid_sig'] && $arr['url'] && $arr['url_sig']) {
@@ -556,18 +556,20 @@ function zot_gethub($arr) {
return null;
}
+ $limit = (($multiple) ? '' : ' limit 1 ');
+
$r = q("select * from hubloc
where hubloc_guid = '%s' and hubloc_guid_sig = '%s'
and hubloc_url = '%s' and hubloc_url_sig = '%s'
- limit 1",
+ $limit",
dbesc($arr['guid']),
dbesc($arr['guid_sig']),
dbesc($arr['url']),
dbesc($arr['url_sig'])
);
- if($r && count($r)) {
+ if($r) {
logger('zot_gethub: found', LOGGER_DEBUG);
- return $r[0];
+ return (($multiple) ? $r : $r[0]);
}
}
logger('zot_gethub: not found: ' . print_r($arr,true), LOGGER_DEBUG);
@@ -951,7 +953,7 @@ function zot_process_response($hub, $arr, $outq) {
// update the timestamp for this site
- q("update site set site_update = '%s' where site_url = '%s'",
+ q("update site set site_dead = 0, site_update = '%s' where site_url = '%s'",
dbesc(datetime_convert()),
dbesc(dirname($hub))
);
@@ -996,27 +998,38 @@ function zot_fetch($arr) {
$url = $arr['sender']['url'] . $arr['callback'];
- $ret_hub = zot_gethub($arr['sender']);
- if(! $ret_hub) {
+ // set $multiple param on zot_gethub() to return all matching hubs
+ // This allows us to recover from re-installs when a redundant (but invalid) hubloc for
+ // this identity is widely dispersed throughout the network.
+
+ $ret_hubs = zot_gethub($arr['sender'],true);
+ if(! $ret_hubs) {
logger('zot_fetch: no hub: ' . print_r($arr['sender'],true));
return;
}
- $data = array(
- 'type' => 'pickup',
- 'url' => z_root(),
- 'callback_sig' => base64url_encode(rsa_sign(z_root() . '/post',get_config('system','prvkey'))),
- 'callback' => z_root() . '/post',
- 'secret' => $arr['secret'],
- 'secret_sig' => base64url_encode(rsa_sign($arr['secret'],get_config('system','prvkey')))
- );
+ foreach($ret_hubs as $ret_hub) {
+ $data = array(
+ 'type' => 'pickup',
+ 'url' => z_root(),
+ 'callback_sig' => base64url_encode(rsa_sign(z_root() . '/post',get_config('system','prvkey'))),
+ 'callback' => z_root() . '/post',
+ 'secret' => $arr['secret'],
+ 'secret_sig' => base64url_encode(rsa_sign($arr['secret'],get_config('system','prvkey')))
+ );
- $datatosend = json_encode(crypto_encapsulate(json_encode($data),$ret_hub['hubloc_sitekey']));
+ $datatosend = json_encode(crypto_encapsulate(json_encode($data),$ret_hub['hubloc_sitekey']));
- $fetch = zot_zot($url,$datatosend);
- $result = zot_import($fetch, $arr['sender']['url']);
+ $fetch = zot_zot($url,$datatosend);
+
+ $result = zot_import($fetch, $arr['sender']['url']);
+
+ if($result)
+ return $result;
+ }
+
+ return;
- return $result;
}
/**
@@ -1055,6 +1068,12 @@ function zot_import($arr, $sender_url) {
$data = json_decode(crypto_unencapsulate($data,get_config('system','prvkey')),true);
}
+ if(! $data['success']) {
+ if($data['message'])
+ logger('remote pickup failed: ' . $data['message']);
+ return false;
+ }
+
$incoming = $data['pickup'];
$return = array();
@@ -2663,7 +2682,7 @@ function import_site($arr, $pubkey) {
// logger('import_site: input: ' . print_r($arr,true));
// logger('import_site: stored: ' . print_r($siterecord,true));
- $r = q("update site set site_location = '%s', site_flags = %d, site_access = %d, site_directory = '%s', site_register = %d, site_update = '%s', site_sellpage = '%s', site_realm = '%s'
+ $r = q("update site set site_dead = 0, site_location = '%s', site_flags = %d, site_access = %d, site_directory = '%s', site_register = %d, site_update = '%s', site_sellpage = '%s', site_realm = '%s'
where site_url = '%s'",
dbesc($site_location),
intval($site_directory),
@@ -2681,7 +2700,7 @@ function import_site($arr, $pubkey) {
}
else {
// update the timestamp to indicate we communicated with this site
- q("update site set site_update = '%s' where site_url = '%s'",
+ q("update site set site_dead = 0, site_update = '%s' where site_url = '%s'",
dbesc(datetime_convert()),
dbesc($url)
);
@@ -3385,3 +3404,291 @@ function zot_process_message_request($data) {
return $ret;
}
+
+
+function zotinfo($arr) {
+
+ $ret = array('success' => false);
+
+ $zhash = ((x($arr,'guid_hash')) ? $arr['guid_hash'] : '');
+ $zguid = ((x($arr,'guid')) ? $arr['guid'] : '');
+ $zguid_sig = ((x($arr,'guid_sig')) ? $arr['guid_sig'] : '');
+ $zaddr = ((x($arr,'address')) ? $arr['address'] : '');
+ $ztarget = ((x($arr,'target')) ? $arr['target'] : '');
+ $zsig = ((x($arr,'target_sig')) ? $arr['target_sig'] : '');
+ $zkey = ((x($arr,'key')) ? $arr['key'] : '');
+ $mindate = ((x($arr,'mindate')) ? $arr['mindate'] : '');
+ $feed = ((x($arr,'feed')) ? intval($arr['feed']) : 0);
+
+ if($ztarget) {
+ if((! $zkey) || (! $zsig) || (! rsa_verify($ztarget,base64url_decode($zsig),$zkey))) {
+ logger('zfinger: invalid target signature');
+ $ret['message'] = t("invalid target signature");
+ return($ret);
+ }
+ }
+
+ $r = null;
+
+ if(strlen($zhash)) {
+ $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
+ where channel_hash = '%s' limit 1",
+ dbesc($zhash)
+ );
+ }
+ elseif(strlen($zguid) && strlen($zguid_sig)) {
+ $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
+ where channel_guid = '%s' and channel_guid_sig = '%s' limit 1",
+ dbesc($zguid),
+ dbesc($zguid_sig)
+ );
+ }
+ elseif(strlen($zaddr)) {
+ if(strpos($zaddr,'[system]') === false) { /* normal address lookup */
+ $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
+ where ( channel_address = '%s' or xchan_addr = '%s' ) limit 1",
+ dbesc($zaddr),
+ dbesc($zaddr)
+ );
+ }
+
+ else {
+
+ /**
+ * The special address '[system]' will return a system channel if one has been defined,
+ * Or the first valid channel we find if there are no system channels.
+ *
+ * This is used by magic-auth if we have no prior communications with this site - and
+ * returns an identity on this site which we can use to create a valid hub record so that
+ * we can exchange signed messages. The precise identity is irrelevant. It's the hub
+ * information that we really need at the other end - and this will return it.
+ *
+ */
+
+ $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
+ where channel_system = 1 order by channel_id limit 1");
+ if(! $r) {
+ $r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
+ where channel_removed = 0 order by channel_id limit 1");
+ }
+ }
+ }
+ else {
+ $ret['message'] = 'Invalid request';
+ return($ret);
+ }
+
+ if(! $r) {
+ $ret['message'] = 'Item not found.';
+ return($ret);
+ }
+
+ $e = $r[0];
+
+ $id = $e['channel_id'];
+
+ $sys_channel = (intval($e['channel_system']) ? true : false);
+ $special_channel = (($e['channel_pageflags'] & PAGE_PREMIUM) ? true : false);
+ $adult_channel = (($e['channel_pageflags'] & PAGE_ADULT) ? true : false);
+ $censored = (($e['channel_pageflags'] & PAGE_CENSORED) ? true : false);
+ $searchable = (($e['channel_pageflags'] & PAGE_HIDDEN) ? false : true);
+ $deleted = (intval($e['xchan_deleted']) ? true : false);
+
+ if($deleted || $censored || $sys_channel)
+ $searchable = false;
+
+ $public_forum = false;
+
+ $role = get_pconfig($e['channel_id'],'system','permissions_role');
+ if($role === 'forum' || $role === 'repository') {
+ $public_forum = true;
+ }
+ else {
+ // check if it has characteristics of a public forum based on custom permissions.
+ $t = q("select abook_my_perms from abook where abook_channel = %d and abook_self = 1 limit 1",
+ intval($e['channel_id'])
+ );
+ if(($t) && (($t[0]['abook_my_perms'] & PERMS_W_TAGWALL) && (! ($t[0]['abook_my_perms'] & PERMS_W_STREAM))))
+ $public_forum = true;
+ }
+
+
+ // This is for birthdays and keywords, but must check access permissions
+ $p = q("select * from profile where uid = %d and is_default = 1",
+ intval($e['channel_id'])
+ );
+
+ $profile = array();
+
+ if($p) {
+
+ if(! intval($p[0]['publish']))
+ $searchable = false;
+
+ $profile['description'] = $p[0]['pdesc'];
+ $profile['birthday'] = $p[0]['dob'];
+ if(($profile['birthday'] != '0000-00-00') && (($bd = z_birthday($p[0]['dob'],$e['channel_timezone'])) !== ''))
+ $profile['next_birthday'] = $bd;
+
+ if($age = age($p[0]['dob'],$e['channel_timezone'],''))
+ $profile['age'] = $age;
+ $profile['gender'] = $p[0]['gender'];
+ $profile['marital'] = $p[0]['marital'];
+ $profile['sexual'] = $p[0]['sexual'];
+ $profile['locale'] = $p[0]['locality'];
+ $profile['region'] = $p[0]['region'];
+ $profile['postcode'] = $p[0]['postal_code'];
+ $profile['country'] = $p[0]['country_name'];
+ $profile['about'] = $p[0]['about'];
+ $profile['homepage'] = $p[0]['homepage'];
+ $profile['hometown'] = $p[0]['hometown'];
+
+ if($p[0]['keywords']) {
+ $tags = array();
+ $k = explode(' ',$p[0]['keywords']);
+ if($k) {
+ foreach($k as $kk) {
+ if(trim($kk," \t\n\r\0\x0B,")) {
+ $tags[] = trim($kk," \t\n\r\0\x0B,");
+ }
+ }
+ }
+ if($tags)
+ $profile['keywords'] = $tags;
+ }
+ }
+
+ $ret['success'] = true;
+
+ // Communication details
+
+ $ret['guid'] = $e['xchan_guid'];
+ $ret['guid_sig'] = $e['xchan_guid_sig'];
+ $ret['key'] = $e['xchan_pubkey'];
+ $ret['name'] = $e['xchan_name'];
+ $ret['name_updated'] = $e['xchan_name_date'];
+ $ret['address'] = $e['xchan_addr'];
+ $ret['photo_mimetype'] = $e['xchan_photo_mimetype'];
+ $ret['photo'] = $e['xchan_photo_l'];
+ $ret['photo_updated'] = $e['xchan_photo_date'];
+ $ret['url'] = $e['xchan_url'];
+ $ret['connections_url']= (($e['xchan_connurl']) ? $e['xchan_connurl'] : z_root() . '/poco/' . $e['channel_address']);
+ $ret['target'] = $ztarget;
+ $ret['target_sig'] = $zsig;
+ $ret['searchable'] = $searchable;
+ $ret['adult_content'] = $adult_channel;
+ $ret['public_forum'] = $public_forum;
+ if($deleted)
+ $ret['deleted'] = $deleted;
+
+ // premium or other channel desiring some contact with potential followers before connecting.
+ // This is a template - %s will be replaced with the follow_url we discover for the return channel.
+
+ if($special_channel)
+ $ret['connect_url'] = z_root() . '/connect/' . $e['channel_address'];
+
+ // This is a template for our follow url, %s will be replaced with a webbie
+
+ $ret['follow_url'] = z_root() . '/follow?f=&url=%s';
+
+ $ztarget_hash = (($ztarget && $zsig)
+ ? make_xchan_hash($ztarget,$zsig)
+ : '' );
+
+ $permissions = get_all_perms($e['channel_id'],$ztarget_hash,false);
+
+ if($ztarget_hash) {
+ $permissions['connected'] = false;
+ $b = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
+ dbesc($ztarget_hash),
+ intval($e['channel_id'])
+ );
+ if($b)
+ $permissions['connected'] = true;
+ }
+
+ $ret['permissions'] = (($ztarget && $zkey) ? crypto_encapsulate(json_encode($permissions),$zkey) : $permissions);
+
+ if($permissions['view_profile'])
+ $ret['profile'] = $profile;
+
+ // array of (verified) hubs this channel uses
+
+ $x = zot_encode_locations($e);
+ if($x)
+ $ret['locations'] = $x;
+
+ $ret['site'] = array();
+ $ret['site']['url'] = z_root();
+ $ret['site']['url_sig'] = base64url_encode(rsa_sign(z_root(),$e['channel_prvkey']));
+
+ $dirmode = get_config('system','directory_mode');
+ if(($dirmode === false) || ($dirmode == DIRECTORY_MODE_NORMAL))
+ $ret['site']['directory_mode'] = 'normal';
+
+ if($dirmode == DIRECTORY_MODE_PRIMARY)
+ $ret['site']['directory_mode'] = 'primary';
+ elseif($dirmode == DIRECTORY_MODE_SECONDARY)
+ $ret['site']['directory_mode'] = 'secondary';
+ elseif($dirmode == DIRECTORY_MODE_STANDALONE)
+ $ret['site']['directory_mode'] = 'standalone';
+ if($dirmode != DIRECTORY_MODE_NORMAL)
+ $ret['site']['directory_url'] = z_root() . '/dirsearch';
+
+
+ // hide detailed site information if you're off the grid
+
+ if($dirmode != DIRECTORY_MODE_STANDALONE) {
+
+ $register_policy = intval(get_config('system','register_policy'));
+
+ if($register_policy == REGISTER_CLOSED)
+ $ret['site']['register_policy'] = 'closed';
+ if($register_policy == REGISTER_APPROVE)
+ $ret['site']['register_policy'] = 'approve';
+ if($register_policy == REGISTER_OPEN)
+ $ret['site']['register_policy'] = 'open';
+
+
+ $access_policy = intval(get_config('system','access_policy'));
+
+ if($access_policy == ACCESS_PRIVATE)
+ $ret['site']['access_policy'] = 'private';
+ if($access_policy == ACCESS_PAID)
+ $ret['site']['access_policy'] = 'paid';
+ if($access_policy == ACCESS_FREE)
+ $ret['site']['access_policy'] = 'free';
+ if($access_policy == ACCESS_TIERED)
+ $ret['site']['access_policy'] = 'tiered';
+
+ $ret['site']['accounts'] = account_total();
+
+ require_once('include/identity.php');
+ $ret['site']['channels'] = channel_total();
+
+
+ $ret['site']['version'] = PLATFORM_NAME . ' ' . RED_VERSION . '[' . DB_UPDATE_VERSION . ']';
+
+ $ret['site']['admin'] = get_config('system','admin_email');
+
+ $a = get_app();
+
+ $visible_plugins = array();
+ if(is_array($a->plugins) && count($a->plugins)) {
+ $r = q("select * from addon where hidden = 0");
+ if($r)
+ foreach($r as $rr)
+ $visible_plugins[] = $rr['name'];
+ }
+
+ $ret['site']['plugins'] = $visible_plugins;
+ $ret['site']['sitehash'] = get_config('system','location_hash');
+ $ret['site']['sitename'] = get_config('system','sitename');
+ $ret['site']['sellpage'] = get_config('system','sellpage');
+ $ret['site']['location'] = get_config('system','site_location');
+ $ret['site']['realm'] = get_directory_realm();
+
+ }
+ call_hooks('zot_finger',$ret);
+ return($ret);
+} \ No newline at end of file