streams/Zotlabs/Zot6/Zot6Handler.php

310 lines
8.1 KiB
PHP
Raw Normal View History

2018-04-23 01:51:46 +00:00
<?php
namespace Zotlabs\Zot6;
2018-06-01 02:42:13 +00:00
use Zotlabs\Lib\Libzot;
2018-04-23 01:51:46 +00:00
class Zot6Handler implements IHandler {
2018-05-30 04:08:52 +00:00
function Notify($data,$hubs) {
2018-06-01 02:42:13 +00:00
self::reply_notify($data,$hubs);
2018-04-23 01:51:46 +00:00
}
2018-05-30 04:08:52 +00:00
function Request($data,$hubs) {
2018-06-01 02:42:13 +00:00
self::reply_message_request($data,$hubs);
2018-04-23 01:51:46 +00:00
}
2018-05-30 04:08:52 +00:00
function Rekey($sender,$data,$hubs) {
2018-06-01 02:42:13 +00:00
self::reply_rekey_request($sender,$data,$hubs);
2018-04-23 01:51:46 +00:00
}
2018-05-30 04:08:52 +00:00
function Refresh($sender,$recipients,$hubs) {
2018-06-01 02:42:13 +00:00
self::reply_refresh($sender,$recipients,$hubs);
2018-04-23 01:51:46 +00:00
}
2018-05-30 04:08:52 +00:00
function Purge($sender,$recipients,$hubs) {
2018-06-01 02:42:13 +00:00
self::reply_purge($sender,$recipients,$hubs);
}
// Implementation of specific methods follows;
// These generally do a small amout of validation and call Libzot
// to do any heavy lifting
static function reply_notify($data,$hubs) {
$ret = [ 'success' => false ];
logger('notify received from ' . $data['sender']['location']);
$x = Libzot::fetch($data,$hubs);
$ret['delivery_report'] = $x;
$ret['success'] = true;
json_return_and_die($ret);
}
/**
* @brief Remote channel info (such as permissions or photo or something)
* has been updated. Grab a fresh copy and sync it.
*
* The difference between refresh and force_refresh is that force_refresh
* unconditionally creates a directory update record, even if no changes were
* detected upon processing.
*
* @param array $sender
* @param array $recipients
*
* @return json_return_and_die()
*/
static function reply_refresh($sender, $recipients,$hubs) {
$ret = array('success' => false);
if($recipients) {
// This would be a permissions update, typically for one connection
foreach ($recipients as $recip) {
$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($recip['id']),
dbesc($recip['id_sig'])
);
$x = Libzot::refresh( [ 'hubloc_id_url' => $sender['id_url'] ], $r[0], (($msgtype === 'force_refresh') ? true : false));
}
}
else {
// system wide refresh
$x = Libzot::refresh( [ 'hubloc_id_url' => $sender['id_url'] ], null, (($msgtype === 'force_refresh') ? true : false));
}
$ret['success'] = true;
json_return_and_die($ret);
}
/**
* @brief Process a message request.
*
* If a site receives a comment to a post but finds they have no parent to attach it with, they
* may send a 'request' packet containing the message_id of the missing parent. This is the handler
* for that packet. We will create a message_list array of the entire conversation starting with
* the missing parent and invoke delivery to the sender of the packet.
*
* Zotlabs/Daemon/Deliver.php (for local delivery) and
* mod/post.php???? @fixme (for web delivery) detect the existence of
* this 'message_list' at the destination and split it into individual messages which are
* processed/delivered in order.
*
*
* @param array $data
* @return array
*/
static function reply_message_request($data,$hubs) {
$ret = [ 'success' => false ];
if (! $data['message_id']) {
$ret['message'] = 'no message_id';
logger('no message_id');
json_return_and_die($ret);
}
$sender = $data['sender'];
$sender_hash = $sender['hash'];
/*
* Find the local channel in charge of this post (the first and only recipient of the request packet)
*/
$arr = $data['recipients'][0];
//@fixme $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;
json_return_and_die($ret);
}
/*
* fetch the requested conversation
*/
$messages = zot_feed($c[0]['channel_id'],$sender_hash,array('message_id' => $data['message_id']));
if ($messages) {
$env_recips = null;
$r = q("select hubloc.*, site.site_crypto from hubloc left join site on hubloc_url = site_url where hubloc_hash = '%s' and hubloc_error = 0 and hubloc_deleted = 0 and site.site_dead = 0 ",
dbesc($sender_hash)
);
if (! $r) {
logger('no hubs');
json_return_and_die($ret);
}
$hubs = $r;
$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();
/*
* create a notify packet and drop the actual message packet in the queue for pickup
*/
$n = Libzot::build_packet($c[0],'notify',$env_recips,$data_packet,(($private) ? $hub['hubloc_sitekey'] : null),$hub['site_crypto'],$hash,array('message_id' => $data['message_id']));
queue_insert(array(
'hash' => $hash,
'account_id' => $c[0]['channel_account_id'],
'channel_id' => $c[0]['channel_id'],
'posturl' => $hub['hubloc_callback'],
'notify' => $n,
'msg' => $data_packet
));
$x = q("select count(outq_hash) as total from outq where outq_delivered = 0");
if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',300))) {
logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO);
update_queue_item($hash);
continue;
}
/*
* invoke delivery to send out the notify packet
*/
2018-06-01 04:05:09 +00:00
\Zotlabs\Daemon\Master::Summon(array('Deliver', $hash));
2018-06-01 02:42:13 +00:00
}
}
$ret['success'] = true;
json_return_and_die($ret);
}
static function rekey_request($sender,$data,$hubs) {
$ret = array('success' => false);
// newsig is newkey signed with oldkey
// The original xchan will remain. In Zot/Receiver we will have imported the new xchan and hubloc to verify
// the packet authenticity. What we will do now is verify that the keychange operation was signed by the
// oldkey, and if so change all the abook, abconfig, group, and permission elements which reference the
// old xchan_hash.
if((! $data['old_key']) && (! $data['new_key']) && (! $data['new_sig']))
json_return_and_die($ret);
$old = null;
if(Libzot::verify($data['old_guid'],$data['old_guid_sig'],$data['old_key'])) {
$oldhash = make_xchan_hash($data['old_guid'],$data['old_key']);
$old = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($oldhash)
);
}
else
json_return_and_die($ret);
if(! $old) {
json_return_and_die($ret);
}
$xchan = $old[0];
if(! Libzot::verify($data['new_key'],$data['new_sig'],$xchan['xchan_pubkey'])) {
json_return_and_die($ret);
}
if(Libzot::verify($sender['id'],$sender['id_sig'],$data['new_key'])) {
$newhash = make_xchan_hash($sender['id'],$data['new_key']);
}
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($newhash)
);
$newxchan = $r[0];
xchan_change_key($xchan,$newxchan,$data);
$ret['success'] = true;
json_return_and_die($ret);
2018-04-23 01:51:46 +00:00
}
2018-06-01 02:42:13 +00:00
/**
* @brief
*
* @param array $sender
* @param array $recipients
*
* return json_return_and_die()
*/
static function reply_purge($sender, $recipients,$hubs) {
$ret = array('success' => false);
if ($recipients) {
// basically this means "unfriend"
foreach ($recipients as $recip) {
$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($recip['id']),
dbesc($recip['id_sig'])
);
if ($r) {
$r = q("select abook_id from abook where uid = %d and abook_xchan = '%s' limit 1",
intval($r[0]['channel_id']),
//@fixme
dbesc(Libzot::make_xchan_hash($sender['guid'],$sender['guid_sig']))
);
if ($r) {
contact_remove($r[0]['channel_id'],$r[0]['abook_id']);
}
}
}
$ret['success'] = true;
}
else {
// Unfriend everybody - basically this means the channel has committed suicide
$arr = $sender;
//@fixme $sender_hash = Libzot::make_xchan_hash($arr['guid'],$arr['guid_sig']);
remove_all_xchan_resources($sender_hash);
$ret['success'] = true;
}
json_return_and_die($ret);
}
2018-04-23 01:51:46 +00:00
}