diff options
Diffstat (limited to 'include/zot.php')
-rw-r--r-- | include/zot.php | 154 |
1 files changed, 139 insertions, 15 deletions
diff --git a/include/zot.php b/include/zot.php index fda2a2bea..24ace9cbb 100644 --- a/include/zot.php +++ b/include/zot.php @@ -2,6 +2,7 @@ require_once('include/crypto.php'); require_once('include/items.php'); +require_once('include/hubloc.php'); /** * Red implementation of zot protocol. @@ -103,7 +104,7 @@ function zot_get_hublocs($hash) { * @returns string json encoded zot packet */ -function zot_build_packet($channel,$type = 'notify',$recipients = null, $remote_key = null, $secret = null) { +function zot_build_packet($channel,$type = 'notify',$recipients = null, $remote_key = null, $secret = null, $extra = null) { $data = array( 'type' => $type, @@ -128,6 +129,12 @@ function zot_build_packet($channel,$type = 'notify',$recipients = null, $remote_ $data['secret_sig'] = base64url_encode(rsa_sign($secret,$channel['channel_prvkey'])); } + if($extra) { + foreach($extra as $k => $v) + $data[$k] = $v; + } + + logger('zot_build_packet: ' . print_r($data,true), LOGGER_DATA); // Hush-hush ultra top-secret mode @@ -1074,6 +1081,7 @@ function zot_import($arr, $sender_url) { continue; } + $message_request = ((array_key_exists('message_id',$i['notify'])) ? true : false); $i['notify']['sender']['hash'] = make_xchan_hash($i['notify']['sender']['guid'],$i['notify']['sender']['guid_sig']); $deliveries = null; @@ -1175,7 +1183,7 @@ function zot_import($arr, $sender_url) { logger('Activity recipients: ' . print_r($deliveries,true), LOGGER_DATA); $relay = ((array_key_exists('flags',$i['message']) && in_array('relay',$i['message']['flags'])) ? true : false); - $result = process_delivery($i['notify']['sender'],$arr,$deliveries,$relay); + $result = process_delivery($i['notify']['sender'],$arr,$deliveries,$relay,false,$message_request); } elseif($i['message']['type'] === 'mail') { @@ -1372,7 +1380,7 @@ function allowed_public_recips($msg) { } -function process_delivery($sender,$arr,$deliveries,$relay,$public = false) { +function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$request = false) { $result = array(); @@ -1435,6 +1443,16 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false) { ); if(! $r) { $result[] = array($d['hash'],'comment parent not found',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); + + // We don't seem to have a copy of this conversation or at least the parent - so request a copy of the entire conversation to date. + // Don't do this if it's a relay post as we're the ones who are supposed to have the copy and we don't want the request to loop. + // Also don't do this if this comment came from a conversation request packet. It's possible that comments are allowed but posting + // isn't and that could cause a conversation fetch loop. We can detect these packets since they are delivered via a 'notify' packet type + // that has a message_id element in the initial zot packet (just like the corresponding 'request' packet type which makes the request). + + if((! $relay) && (! $request)) + proc_run('php', 'include/notifier.php', 'request', $channel['channel_id'], $sender['hash'], $arr['parent_mid']); + continue; } if($relay) { @@ -1475,11 +1493,13 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false) { continue; } - $r = q("select id, edited from item where mid = '%s' and uid = %d limit 1", + $r = q("select id, edited, item_flags, mid, parent_mid from item where mid = '%s' and uid = %d limit 1", dbesc($arr['mid']), intval($channel['channel_id']) ); if($r) { + // We already have this post. + // Maybe it has been edited? $item_id = $r[0]['id']; if($arr['edited'] > $r[0]['edited']) { $arr['id'] = $r[0]['id']; @@ -1491,6 +1511,10 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false) { } else { $result[] = array($d['hash'],'update ignored',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); + // We need this line to ensure wall-to-wall comments are relayed (by falling through to the relay bit), + // and at the same time not relay any other relayable posts more than once, because to do so is very wasteful. + if(! ($r[0]['item_flags'] & ITEM_ORIGIN)) + continue; } } else { @@ -1714,9 +1738,14 @@ function process_location_delivery($sender,$arr,$deliveries) { ); if($r) $sender['key'] = $r[0]['xchan_pubkey']; - - $x = sync_locations($sender,$arr,true); - logger('process_location_delivery: results: ' . print_r($x,true), LOGGER_DATA); + if(array_key_exists('locations',$arr) && $arr['locations']) { + $x = sync_locations($sender,$arr,true); + logger('process_location_delivery: results: ' . print_r($x,true), LOGGER_DEBUG); + if($x['changed']) { + $guid = random_string() . '@' . get_app()->get_hostname(); + update_modtime($sender['hash'],$sender['guid'],$arr['locations'][0]['address'],UPDATE_FLAGS_UPDATED); + } + } } @@ -1740,6 +1769,11 @@ function sync_locations($sender,$arr,$absolute = false) { } } + // Ensure that they have one primary hub + + if(! $has_primary) + $arr['locations'][0]['primary'] = true; + foreach($arr['locations'] as $location) { if(! rsa_verify($location['url'],base64url_decode($location['url_sig']),$sender['key'])) { logger('sync_locations: Unable to verify site signature for ' . $location['url']); @@ -1747,10 +1781,6 @@ function sync_locations($sender,$arr,$absolute = false) { continue; } - // Ensure that they have one primary hub - - if(! $has_primary) - $location['primary'] = true; for($x = 0; $x < count($xisting); $x ++) { if(($xisting[$x]['hubloc_url'] === $location['url']) @@ -1824,22 +1854,35 @@ function sync_locations($sender,$arr,$absolute = false) { q("delete from hubloc where hubloc_id = %d limit 1", intval($r[$h]['hubloc_id']) ); + $what .= 'duplicate_hubloc_removed '; + $changed = true; } } if((($r[0]['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY) && (! $location['primary'])) || ((! ($r[0]['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY)) && ($location['primary']))) { - $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_id = %d limit 1", + $m = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_id = %d limit 1", intval(HUBLOC_FLAGS_PRIMARY), dbesc(datetime_convert()), intval($r[0]['hubloc_id']) ); + // make sure hubloc_change_primary() has current data + $r[0]['hubloc_flags'] = $r[0]['hubloc_flags'] ^ HUBLOC_FLAGS_PRIMARY; + hubloc_change_primary($r[0]); $what .= 'primary_hub '; $changed = true; } + elseif($absolute) { + // Absolute sync - make sure the current primary is correctly reflected in the xchan + $pr = hubloc_change_primary($r[0]); + if($pr) { + $what .= 'xchan_primary'; + $changed = true; + } + } if((($r[0]['hubloc_flags'] & HUBLOC_FLAGS_DELETED) && (! $location['deleted'])) || ((! ($r[0]['hubloc_flags'] & HUBLOC_FLAGS_DELETED)) && ($location['deleted']))) { - $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_id = %d limit 1", + $n = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_id = %d limit 1", intval(HUBLOC_FLAGS_DELETED), dbesc(datetime_convert()), intval($r[0]['hubloc_id']) @@ -1850,7 +1893,8 @@ function sync_locations($sender,$arr,$absolute = false) { continue; } - // new hub claiming to be primary. Make it so. + // Existing hubs are dealt with. Now let's process any new ones. + // New hub claiming to be primary. Make it so by removing any existing primaries. if(intval($location['primary'])) { $r = q("update hubloc set hubloc_flags = (hubloc_flags ^ %d), hubloc_updated = '%s' where hubloc_hash = '%s' and (hubloc_flags & %d )", @@ -1880,6 +1924,14 @@ function sync_locations($sender,$arr,$absolute = false) { $what .= 'newhub '; $changed = true; + if($location['primary']) { + $r = q("select * from hubloc where hubloc_addr = '%s' and hubloc_sitekey = '%s' limit 1", + dbesc($location['address']), + dbesc($location['sitekey']) + ); + if($r) + hubloc_change_primary($r[0]); + } } // get rid of any hubs we have for this channel which weren't reported. @@ -1893,7 +1945,7 @@ function sync_locations($sender,$arr,$absolute = false) { dbesc(datetime_convert()), intval($x['hubloc_id']) ); - $what .= 'removed_hub'; + $what .= 'removed_hub '; $changed = true; } } @@ -2758,3 +2810,75 @@ function import_author_zot($x) { return false; } +function zot_process_message_request($data) { + $ret = array('success' => false); + +// note: disabled until the loops stop. + return $ret; + + if(! $data['message_id']) { + $ret['message'] = 'no message_id'; + logger('no message_id'); + return $ret; + } + + $sender = $data['sender']; + $sender_hash = make_xchan_hash($sender['guid'],$sender['guid_sig']); + + $arr = $data['recipients'][0]; + $recip_hash = make_xchan_hash($arr['guid'],$arr['guid_sig']); + $c = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_hash = '%s' limit 1", + dbesc($recip_hash) + ); + if(! $c) { + logger('recipient channel not found.'); + $ret['message'] .= 'recipient not found.' . EOL; + return $ret; + } + $messages = zot_feed($c[0]['channel_id'],$sender_hash,array('message_id' => $data['message_id'])); + if($messages) { + $env_recips = null; + + $r = q("select hubloc_guid, hubloc_url, hubloc_sitekey, hubloc_network, hubloc_flags, hubloc_callback, hubloc_host + from hubloc where hubloc_hash = '" . dbesc($sender_hash) . "' and not (hubloc_flags & %d) + and not (hubloc_status & %d) group by hubloc_sitekey", + intval(HUBLOC_FLAGS_DELETED), + intval(HUBLOC_OFFLINE) + ); + if(! $r) { + logger('no hubs'); + return $ret; + } + $hubs = $r; + $hublist = array(); + $keys = array(); + + $private = ((array_key_exists('flags',$messages[0]) && in_array('private',$messages[0]['flags'])) ? true : false); + if($private) + $env_recips = array('guid' => $sender['guid'],'guid_sig' => $sender['guid_sig'],'hash' => $sender_hash); + $data_packet = json_encode(array('message_list' => $messages)); + + foreach($hubs as $hub) { + $hash = random_string(); + $n = zot_build_packet($c[0],'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hash,array('message_id' => $data['message_id'])); + q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, + outq_created, outq_updated, outq_notify, outq_msg ) + values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )", + dbesc($hash), + intval($c[0]['channel_account_id']), + intval($c[0]['channel_id']), + dbesc('zot'), + dbesc($hub['hubloc_callback']), + intval(1), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + dbesc($n), + dbesc($data_packet) + ); + proc_run('php','include/deliver.php',$hash); + } + + } + $ret['success'] = true; + return $ret; +} |