From 4274a2d06c9ee2c28acba0dac3d5353e13776581 Mon Sep 17 00:00:00 2001 From: friendica Date: Sun, 2 Nov 2014 00:06:52 -0700 Subject: add some more safety checks before turning the conversation request messages back on --- include/zot.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'include/zot.php') diff --git a/include/zot.php b/include/zot.php index 24ace9cbb..153fa28bf 100644 --- a/include/zot.php +++ b/include/zot.php @@ -1448,11 +1448,13 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque // 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). + // that has a message_id element in the initial zot packet (just like the corresponding 'request' packet type which makes the request). + // We'll also check the send_stream permission, because if it isn't allowed the top level post is unlikely to be imported and + // this is just an exercise in futility. - if((! $relay) && (! $request)) + if((! $relay) && (! $request) && (! $public) && perm_is_allowed($channel['channel_id'],$sender['hash'],'send_stream')) { proc_run('php', 'include/notifier.php', 'request', $channel['channel_id'], $sender['hash'], $arr['parent_mid']); - + } continue; } if($relay) { -- cgit v1.2.3 From 285d6f61e4bf8aeaa3294ac4b7af43366a1448e9 Mon Sep 17 00:00:00 2001 From: friendica Date: Sun, 2 Nov 2014 15:28:20 -0800 Subject: I'm going to try again with the conversation request packets. I've looked this over and tested a lot of edge cases, and thought about from every angle I can think of to prevent looping. I don't *think* this can loop. I also doubt that this is the problem at friendicared.de, but I don't know for sure what that problem might be. --- include/zot.php | 66 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 11 deletions(-) (limited to 'include/zot.php') diff --git a/include/zot.php b/include/zot.php index 153fa28bf..f18830e78 100644 --- a/include/zot.php +++ b/include/zot.php @@ -1082,6 +1082,8 @@ function zot_import($arr, $sender_url) { } $message_request = ((array_key_exists('message_id',$i['notify'])) ? true : false); + if($message_request) + logger('processing message request'); $i['notify']['sender']['hash'] = make_xchan_hash($i['notify']['sender']['guid'],$i['notify']['sender']['guid_sig']); $deliveries = null; @@ -1444,15 +1446,22 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque 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). - // We'll also check the send_stream permission, because if it isn't allowed the top level post is unlikely to be imported and + // 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). + // We'll also check the send_stream permission - because if it isn't allowed, + // the top level post is unlikely to be imported and // this is just an exercise in futility. - if((! $relay) && (! $request) && (! $public) && perm_is_allowed($channel['channel_id'],$sender['hash'],'send_stream')) { + if((! $relay) && (! $request) && (! $public) + && perm_is_allowed($channel['channel_id'],$sender['hash'],'send_stream')) { proc_run('php', 'include/notifier.php', 'request', $channel['channel_id'], $sender['hash'], $arr['parent_mid']); } continue; @@ -2812,12 +2821,25 @@ function import_author_zot($x) { return false; } + +/** + * @function zot_process_message_request($data) + * 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. + * + * include/deliver.php (for local delivery) and mod/post.php (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. + * + * Called from mod/post.php + */ + + 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'); @@ -2827,6 +2849,10 @@ function zot_process_message_request($data) { $sender = $data['sender']; $sender_hash = make_xchan_hash($sender['guid'],$sender['guid_sig']); + /* + * Find the local channel in charge of this post (the first and only recipient of the request packet) + */ + $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", @@ -2837,13 +2863,20 @@ function zot_process_message_request($data) { $ret['message'] .= 'recipient not found.' . EOL; return $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_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) + from hubloc where hubloc_hash = '%s' and not (hubloc_flags & %d) and not (hubloc_status & %d) group by hubloc_sitekey", + dbesc($sender_hash), intval(HUBLOC_FLAGS_DELETED), intval(HUBLOC_OFFLINE) ); @@ -2858,10 +2891,16 @@ function zot_process_message_request($data) { $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 = 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 ) @@ -2877,6 +2916,11 @@ function zot_process_message_request($data) { dbesc($n), dbesc($data_packet) ); + + /* + * invoke delivery to send out the notify packet + */ + proc_run('php','include/deliver.php',$hash); } -- cgit v1.2.3 From 0e4f318b71fc454c3a0ce6f0e073d9808ff00269 Mon Sep 17 00:00:00 2001 From: friendica Date: Sun, 2 Nov 2014 19:22:18 -0800 Subject: php warnings --- include/zot.php | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'include/zot.php') diff --git a/include/zot.php b/include/zot.php index f18830e78..f1ff084ac 100644 --- a/include/zot.php +++ b/include/zot.php @@ -5,7 +5,7 @@ require_once('include/items.php'); require_once('include/hubloc.php'); /** - * Red implementation of zot protocol. + * Red implementation of zot protocol. * * https://github.com/friendica/red/wiki/zot * https://github.com/friendica/red/wiki/Zot---A-High-Level-Overview @@ -20,8 +20,8 @@ require_once('include/hubloc.php'); * Generates a unique string for use as a zot guid using our DNS-based url, the channel nickname and some entropy. * The entropy ensures uniqueness against re-installs where the same URL and nickname are chosen. * NOTE: zot doesn't require this to be unique. Internally we use a whirlpool hash of this guid and the signature - * of this guid signed with the channel private key. This can be verified and should make the probability of - * collision of the verified result negligible within the constraints of our immediate universe. + * of this guid signed with the channel private key. This can be verified and should make the probability of + * collision of the verified result negligible within the constraints of our immediate universe. * * @param string channel_nickname = unique nickname of controlling entity * @@ -51,7 +51,7 @@ function make_xchan_hash($guid,$guid_sig) { /** * @function zot_get_hublocs($hash) - * Given a zot hash, return all distinct hubs. + * Given a zot hash, return all distinct hubs. * This function is used in building the zot discovery packet * and therefore should only be used by channels which are defined * on this hub @@ -71,7 +71,7 @@ function make_xchan_hash($guid,$guid_sig) { * hubloc_connect char(255) * hubloc_sitekey text * hubloc_updated datetime - * hubloc_connected datetime + * hubloc_connected datetime * */ @@ -85,21 +85,21 @@ function zot_get_hublocs($hash) { ); return $ret; } - + /** * * @function zot_build_packet($channel,$type = 'notify',$recipients = null, $remote_key = null, $secret = null) * builds a zot notification packet that you can either - * store in the queue with a message array or call zot_zot to immediately + * store in the queue with a message array or call zot_zot to immediately * zot it to the other side * * @param array $channel => sender channel structure * @param string $type => packet type: one of 'ping', 'pickup', 'purge', 'refresh', 'force_refresh', 'notify', 'auth_check' * @param array $recipients => envelope information, array ( 'guid' => string, 'guid_sig' => string ); empty for public posts * @param string $remote_key => optional public site key of target hub used to encrypt entire packet - * NOTE: remote_key and encrypted packets are required for 'auth_check' packets, optional for all others + * NOTE: remote_key and encrypted packets are required for 'auth_check' packets, optional for all others * @param string $secret => random string, required for packets which require verification/callback - * e.g. 'pickup', 'purge', 'notify', 'auth_check'. Packet types 'ping', 'force_refresh', and 'refresh' do not require verification + * e.g. 'pickup', 'purge', 'notify', 'auth_check'. Packet types 'ping', 'force_refresh', and 'refresh' do not require verification * * @returns string json encoded zot packet */ @@ -1071,7 +1071,7 @@ function zot_import($arr, $sender_url) { if(array_key_exists('iv',$i['notify'])) { $i['notify'] = json_decode(crypto_unencapsulate($i['notify'],get_config('system','prvkey')),true); - } + } logger('zot_import: notify: ' . print_r($i['notify'],true), LOGGER_DATA); @@ -1107,7 +1107,7 @@ function zot_import($arr, $sender_url) { // It's a specifically targetted post. If we were sent a public_scope hint (likely), // get rid of it so that it doesn't get stored and cause trouble. - if(array_key_exists('message',$i) && array_key_exists('public_scope',$i['message'])) + if(($i) && is_array($i) && array_key_exists('message',$i) && is_array($i['message']) && array_key_exists('public_scope',$i['message'])) unset($i['message']['public_scope']); $deliveries = $r; @@ -2460,8 +2460,8 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { $channel = $r[0]; - $max_friends = service_class_fetch($channel['channel_id'],'total_channels'); - $max_feeds = account_service_class_fetch($channel['channel_account_id'],'total_feeds'); + $max_friends = service_class_fetch($channel['channel_id'],'total_channels'); + $max_feeds = account_service_class_fetch($channel['channel_account_id'],'total_feeds'); if($channel['channel_hash'] != $sender['hash']) { @@ -2547,7 +2547,7 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { continue; } $j = json_decode($f['body'],true); - if(! ($j['success'] && $j['guid'])) { + if(! ($j['success'] && $j['guid'])) { logger('process_channel_sync_delivery: probe failed.'); continue; } @@ -2646,8 +2646,8 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { intval($channel['channel_id']), intval($cl['visible']), intval($cl['deleted']), - dbesc($cl['name']) - ); + dbesc($cl['name']) + ); } // now look for any collections locally which weren't in the list we just received. @@ -2877,13 +2877,13 @@ function zot_process_message_request($data) { from hubloc where hubloc_hash = '%s' and not (hubloc_flags & %d) and not (hubloc_status & %d) group by hubloc_sitekey", dbesc($sender_hash), - intval(HUBLOC_FLAGS_DELETED), - intval(HUBLOC_OFFLINE) - ); - if(! $r) { - logger('no hubs'); - return $ret; - } + intval(HUBLOC_FLAGS_DELETED), + intval(HUBLOC_OFFLINE) + ); + if(! $r) { + logger('no hubs'); + return $ret; + } $hubs = $r; $hublist = array(); $keys = array(); -- cgit v1.2.3 From d5d6158973ecb83b63d42c57c96dce849842c83b Mon Sep 17 00:00:00 2001 From: friendica Date: Tue, 4 Nov 2014 17:11:02 -0800 Subject: ok heads up - potentially destabilising change. I've tried to sort out all the default connection permissions for those who don't have a predefined (or therefore have a "custom") permissions role. Unfortunately this includes most people that were using this software more than a month ago. The real changes are that the SELF address book entry no longer holds "auto-permissions" but instead holds your "default permissions" (if you have a pre-defined role, the defaults will be pulled from the role table). The auto permissions have moved to a pconfig (uid.system.autoperms). A DB update will move these settings into their new homes. What used to be the "Auto-permissions settings" page is now the "default permissions settings" page and a checkbox therein decides whether or not to apply the permissions automatically. A link to this page will only be shown when you have the "custom" role selected. With luck nobody will notice anything wrong. But at least for the next few days, please review permissions that have been assigned to new connections (either automatically or manually) and make sure they make sense (e.g. they aren't "nothing"). You still need to take action when seeing a message "permissions have changed but not yet submitted" as we always let you review and perhaps adjust the settings _before_ a connection is established (unless you have autoperms turned on). --- include/zot.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'include/zot.php') diff --git a/include/zot.php b/include/zot.php index f1ff084ac..9f22bc30b 100644 --- a/include/zot.php +++ b/include/zot.php @@ -439,15 +439,15 @@ function zot_refresh($them,$channel = null, $force = false) { } } else { - $default_perms = 0; - // look for default permissions to apply in return - e.g. auto-friend - $z = q("select * from abook where abook_channel = %d and (abook_flags & %d) limit 1", - intval($channel['channel_id']), - intval(ABOOK_FLAG_SELF) - ); - - if($z) - $default_perms = intval($z[0]['abook_my_perms']); + $role = get_pconfig($channel['channel_id'],'system','permissions_role'); + if($role) { + $x = get_role_perms($role); + if($x['perms_auto']) + $default_perms = $x['perms_accept']; + } + if(! $default_perms) + $default_perms = intval(get_pconfig($channel['channel_id'],'system','autoperms')); + // Keep original perms to check if we need to notify them $previous_perms = get_all_perms($channel['channel_id'],$x['hash']); -- cgit v1.2.3 From 1f35d9432ff6391c183fe9e268cbf3b76ac8dd0d Mon Sep 17 00:00:00 2001 From: zottel Date: Thu, 6 Nov 2014 17:24:05 +0100 Subject: don't overwrite $x (contains import_xchan result) with role permissions --- include/zot.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/zot.php') diff --git a/include/zot.php b/include/zot.php index 9f22bc30b..bdc1f607f 100644 --- a/include/zot.php +++ b/include/zot.php @@ -441,9 +441,9 @@ function zot_refresh($them,$channel = null, $force = false) { else { $role = get_pconfig($channel['channel_id'],'system','permissions_role'); if($role) { - $x = get_role_perms($role); - if($x['perms_auto']) - $default_perms = $x['perms_accept']; + $xx = get_role_perms($role); + if($xx['perms_auto']) + $default_perms = $xx['perms_accept']; } if(! $default_perms) $default_perms = intval(get_pconfig($channel['channel_id'],'system','autoperms')); -- cgit v1.2.3 From 62094652333514e92f9f00699e14b9f49680bb64 Mon Sep 17 00:00:00 2001 From: friendica Date: Mon, 10 Nov 2014 15:21:04 -0800 Subject: add public forum identification to libzot. No attempt is made to identify other types of forums or weird custom channel permissions. If the channel is auto-accept and taggable, it's a public forum. --- include/zot.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'include/zot.php') diff --git a/include/zot.php b/include/zot.php index bdc1f607f..ac68c0035 100644 --- a/include/zot.php +++ b/include/zot.php @@ -699,10 +699,14 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $dirmode = get_config('system','directory_mode'); - if((($arr['site']['directory_mode'] === 'standalone') || ($dirmode & DIRECTORY_MODE_STANDALONE)) -&& ($arr['site']['url'] != z_root())) + if((($arr['site']['directory_mode'] === 'standalone') || ($dirmode & DIRECTORY_MODE_STANDALONE)) && ($arr['site']['url'] != z_root())) $arr['searchable'] = false; + $public_forum = (($r[0]['xchan_flags'] & XCHAN_FLAGS_PUBFORUM) ? true : false); + $pubforum_changed = ((intval($public_forum) != intval($arr['public_forum'])) ? true : false); + if($pubforum_changed) + $new_flags = $r[0]['xchan_flags'] ^ XCHAN_FLAGS_PUBFORUM; + $hidden = (1 - intval($arr['searchable'])); // Be careful - XCHAN_FLAGS_HIDDEN should evaluate to 1 -- cgit v1.2.3 From 56199027768a07d7f1f980df08fb9c5dc7b1278e Mon Sep 17 00:00:00 2001 From: friendica Date: Mon, 10 Nov 2014 17:44:02 -0800 Subject: indicate public forums in directory results (there will be some [possibly considerable] lag time before existing forums are correctly tagged). --- include/zot.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'include/zot.php') diff --git a/include/zot.php b/include/zot.php index ac68c0035..2954408b9 100644 --- a/include/zot.php +++ b/include/zot.php @@ -702,10 +702,6 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { if((($arr['site']['directory_mode'] === 'standalone') || ($dirmode & DIRECTORY_MODE_STANDALONE)) && ($arr['site']['url'] != z_root())) $arr['searchable'] = false; - $public_forum = (($r[0]['xchan_flags'] & XCHAN_FLAGS_PUBFORUM) ? true : false); - $pubforum_changed = ((intval($public_forum) != intval($arr['public_forum'])) ? true : false); - if($pubforum_changed) - $new_flags = $r[0]['xchan_flags'] ^ XCHAN_FLAGS_PUBFORUM; $hidden = (1 - intval($arr['searchable'])); @@ -725,6 +721,11 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { if($deleted_changed) $new_flags = $new_flags ^ XCHAN_FLAGS_DELETED; + $public_forum = (($r[0]['xchan_flags'] & XCHAN_FLAGS_PUBFORUM) ? true : false); + $pubforum_changed = ((intval($public_forum) != intval($arr['public_forum'])) ? true : false); + if($pubforum_changed) + $new_flags = $r[0]['xchan_flags'] ^ XCHAN_FLAGS_PUBFORUM; + if(($r[0]['xchan_name_date'] != $arr['name_updated']) || ($r[0]['xchan_connurl'] != $arr['connections_url']) || ($r[0]['xchan_flags'] != $new_flags) -- cgit v1.2.3