aboutsummaryrefslogtreecommitdiffstats
path: root/include/zot.php
diff options
context:
space:
mode:
Diffstat (limited to 'include/zot.php')
-rw-r--r--include/zot.php180
1 files changed, 143 insertions, 37 deletions
diff --git a/include/zot.php b/include/zot.php
index 98b54a04c..b09f65b7b 100644
--- a/include/zot.php
+++ b/include/zot.php
@@ -1270,12 +1270,13 @@ function zot_import($arr, $sender_url) {
// A public message with no listed recipients can be delivered to anybody who
-// has PERMS_NETWORK for that type of post, or PERMS_SITE and is one the same
+// has PERMS_NETWORK for that type of post, PERMS_AUTHED (in-network senders are
+// by definition authenticated) or PERMS_SITE and is one the same
// site, or PERMS_SPECIFIC and the sender is a contact who is granted
// permissions via their connection permissions in the address book.
// Here we take a given message and construct a list of hashes of everybody
-// on the site that we should deliver to.
-
+// on the site that we should try and deliver to.
+// Some of these will be rejected, but this gives us a place to start.
function public_recips($msg) {
@@ -1294,11 +1295,31 @@ function public_recips($msg) {
$check_mentions = true;
}
else {
+
+ // This doesn't look like it works so I have to explain what happened. These are my
+ // notes (below) from when I got this section of code working. You would think that
+ // we only have to find those with the requisite stream or comment permissions,
+ // depending on whether this is a top-level post or a comment - but you would be wrong.
+
+ // ... so public_recips and allowed_public_recips is working so much better
+ // than before, but was still not quite right. We seem to be getting all the right
+ // results for top-level posts now, but comments aren't getting through on channels
+ // for which we've allowed them to send us their stream, but not comment on our posts.
+ // The reason is we were seeing if they could comment - and we only need to do that if
+ // we own the post. If they own the post, we only need to check if they can send us their stream.
+
// if this is a comment and it wasn't sent by the post owner, check to see who is allowing them to comment.
- // We should have one specific recipient and this step shouldn't be needed unless somebody stuffed up their software.
- // We may need this step to protect us from bad guys intentionally stuffing up their software.
- // If it is sent by the post owner, we don't need to do this. We only need to see who is receiving the
- // owner's stream (which was already set above) - as they control the comment permissions
+ // We should have one specific recipient and this step shouldn't be needed unless somebody stuffed up
+ // their software. We may need this step to protect us from bad guys intentionally stuffing up their software.
+ // If it is sent by the post owner, we don't need to do this. We only need to see who is receiving the
+ // owner's stream (which was already set above) - as they control the comment permissions, not us.
+
+ // Note that by doing this we introduce another bug because some public forums have channel_w_stream
+ // permissions set to themselves only. We also need in this function to add these public forums to the
+ // public recipient list based on if they are tagged or not and have tag permissions. This is complicated
+ // by the fact that this activity doesn't have the public forum tag. It's the parent activity that
+ // contains the tag. we'll solve that further below.
+
if($msg['notify']['sender']['guid_sig'] != $msg['message']['owner']['guid_sig']) {
$col = 'channel_w_comment';
$field = PERMS_W_COMMENT;
@@ -1313,21 +1334,38 @@ function public_recips($msg) {
if(! $col)
return NULL;
-
+ $col = dbesc($col);
+
+ // First find those channels who are accepting posts from anybody, or at least
+ // something greater than just their connections.
+
if($msg['notify']['sender']['url'] === z_root())
- $sql = " where (( " . $col . " & " . PERMS_NETWORK . " )>0 or ( " . $col . " & " . PERMS_SITE . " )>0 or ( " . $col . " & " . PERMS_PUBLIC . ")>0 or ( " . $col . " & " . PERMS_AUTHED . ")>0) ";
+ $sql = " where (( " . $col . " & " . intval(PERMS_NETWORK) . " ) > 0
+ or ( " . $col . " & " . intval(PERMS_SITE) . " ) > 0
+ or ( " . $col . " & " . intval(PERMS_PUBLIC) . ") > 0
+ or ( " . $col . " & " . intval(PERMS_AUTHED) . ") > 0 ) ";
else
- $sql = " where (( " . $col . " & " . PERMS_NETWORK . " )>0 or ( " . $col . " & " . PERMS_PUBLIC . ")>0 or ( " . $col . " & " . PERMS_AUTHED . ")>0) ";
+ $sql = " where (( " . $col . " & " . intval(PERMS_NETWORK) . " ) > 0
+ or ( " . $col . " & " . intval(PERMS_PUBLIC) . ") > 0
+ or ( " . $col . " & " . intval(PERMS_AUTHED) . ") > 0 ) ";
- $r = q("select channel_hash as hash from channel $sql or channel_hash = '%s' ",
+ $r = q("select channel_hash as hash from channel $sql or channel_hash = '%s'
+ and ( channel_pageflags & " . intval(PAGE_REMOVED) . " ) = 0 ",
dbesc($msg['notify']['sender']['hash'])
);
if(! $r)
$r = array();
- $x = q("select channel_hash as hash from channel left join abook on abook_channel = channel_id where abook_xchan = '%s' and not ( channel_pageflags & " . PAGE_REMOVED . " )>0 and (( " . $col . " & " . PERMS_SPECIFIC . " )>0 and ( abook_my_perms & " . $field . " )>0) OR ( " . $col . " & " . PERMS_PENDING . " )>0 OR (( " . $col . " & " . PERMS_CONTACTS . " )>0 and not ( abook_flags & " . ABOOK_FLAG_PENDING . " )>0) ",
+ // Now we have to get a bit dirty. Find every channel that has the sender in their connections (abook)
+ // and is allowing this sender at least at a high level.
+
+ $x = q("select channel_hash as hash from channel left join abook on abook_channel = channel_id
+ where abook_xchan = '%s' and ( channel_pageflags & " . intval(PAGE_REMOVED) . " ) = 0
+ and (( " . $col . " & " . intval(PERMS_SPECIFIC) . " ) > 0 and ( abook_my_perms & " . intval($field) . " ) > 0 )
+ OR ( " . $col . " & " . intval(PERMS_PENDING) . " ) > 0
+ OR (( " . $col . " & " . intval(PERMS_CONTACTS) . " ) > 0 and ( abook_flags & " . intval(ABOOK_FLAG_PENDING) . " ) = 0 ) ",
dbesc($msg['notify']['sender']['hash'])
);
@@ -1347,22 +1385,55 @@ function public_recips($msg) {
// look for any public mentions on this site
// They will get filtered by tgroup_check() so we don't need to check permissions now
- if($check_mentions && $msg['message']['tags']) {
- if(is_array($msg['message']['tags']) && $msg['message']['tags']) {
- foreach($msg['message']['tags'] as $tag) {
- if(($tag['type'] === 'mention') && (strpos($tag['url'],z_root()) !== false)) {
- $address = basename($tag['url']);
- if($address) {
- $z = q("select channel_hash as hash from channel where channel_address = '%s' limit 1",
- dbesc($address)
- );
- if($z)
- $r = array_merge($r,$z);
+ if($check_mentions) {
+ // It's a top level post. Look at the tags. See if any of them are mentions and are on this hub.
+ if($msg['message']['tags']) {
+ if(is_array($msg['message']['tags']) && $msg['message']['tags']) {
+ foreach($msg['message']['tags'] as $tag) {
+ if(($tag['type'] === 'mention') && (strpos($tag['url'],z_root()) !== false)) {
+ $address = basename($tag['url']);
+ if($address) {
+ $z = q("select channel_hash as hash from channel where channel_address = '%s' limit 1",
+ dbesc($address)
+ );
+ if($z)
+ $r = array_merge($r,$z);
+ }
}
}
}
}
}
+ else {
+ // This is a comment. We need to find any parent with ITEM_UPLINK set. But in fact, let's just return
+ // everybody that stored a copy of the parent. This way we know we're covered. We'll check the
+ // comment permissions when we deliver them.
+
+ if($msg['message']['message_top']) {
+ $z = q("select owner_xchan as hash from item where parent_mid = '%s' ",
+ dbesc($msg['message']['message_top']),
+ intval(ITEM_UPLINK)
+ );
+ if($z)
+ $r = array_merge($r,$z);
+ }
+ }
+
+ // There are probably a lot of duplicates in $r at this point. We need to filter those out.
+ // It's a bit of work since it's a multi-dimensional array
+
+ if($r) {
+ $uniq = array();
+
+ foreach($r as $rr) {
+ if(! in_array($rr['hash'],$uniq))
+ $uniq[] = $rr['hash'];
+ }
+ $r = array();
+ foreach($uniq as $rr) {
+ $r[] = array('hash' => $rr);
+ }
+ }
logger('public_recips: ' . print_r($r,true), LOGGER_DATA);
return $r;
@@ -1373,9 +1444,16 @@ function public_recips($msg) {
function allowed_public_recips($msg) {
-
logger('allowed_public_recips: ' . print_r($msg,true),LOGGER_DATA);
+ if(array_key_exists('public_scope',$msg['message']))
+ $scope = $msg['message']['public_scope'];
+
+ // Mail won't have a public scope.
+ // in fact, it's doubtful mail will ever get here since it almost universally
+ // has a recipient, but in fact we don't require this, so it's technically
+ // possible to send mail to anybody that's listening.
+
$recips = public_recips($msg);
if(! $recips)
@@ -1384,11 +1462,6 @@ function allowed_public_recips($msg) {
if($msg['message']['type'] === 'mail')
return $recips;
- if(array_key_exists('public_scope',$msg['message']))
- $scope = $msg['message']['public_scope'];
-
- $hash = make_xchan_hash($msg['notify']['sender']['guid'],$msg['notify']['sender']['guid_sig']);
-
if($scope === 'public' || $scope === 'network: red' || $scope === 'authenticated')
return $recips;
@@ -1400,18 +1473,23 @@ function allowed_public_recips($msg) {
}
if($scope === 'self') {
+
+ $hash = make_xchan_hash($msg['notify']['sender']['guid'],$msg['notify']['sender']['guid_sig']);
+
foreach($recips as $r)
if($r['hash'] === $hash)
return array('hash' => $hash);
}
- if($scope === 'contacts') {
+ // note: we shouldn't ever see $scope === 'specific' in this function, but handle it anyway
+
+ if($scope === 'contacts' || $scope === 'any connections' || $scope === 'specific') {
$condensed_recips = array();
foreach($recips as $rr)
$condensed_recips[] = $rr['hash'];
$results = array();
- $r = q("select channel_hash as hash from channel left join abook on abook_channel = channel_id where abook_xchan = '%s' and not ( channel_pageflags & %d )>0 ",
+ $r = q("select channel_hash as hash from channel left join abook on abook_channel = channel_id where abook_xchan = '%s' and not ( channel_pageflags & %d ) > 0 ",
dbesc($hash),
intval(PAGE_REMOVED)
);
@@ -1423,6 +1501,7 @@ function allowed_public_recips($msg) {
return $results;
}
+
return array();
}
@@ -1626,6 +1705,13 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque
else {
$arr['aid'] = $channel['channel_account_id'];
$arr['uid'] = $channel['channel_id'];
+
+ // if it's a sourced post, call the post_local hooks as if it were
+ // posted locally so that crosspost connectors will be triggered.
+
+ if(check_item_source($arr['uid'],$arr))
+ call_hooks('post_local',$arr);
+
$item_result = item_store($arr);
$item_id = 0;
if($item_result['success']) {
@@ -1770,7 +1856,23 @@ function delete_imported_item($sender,$item,$uid,$relay) {
logger('delete_imported_item: item was already deleted');
if(! $relay)
return false;
+
+ // This is a bit hackish, but may have to suffice until the notification/delivery loop is optimised
+ // a bit further. We're going to strip the ITEM_ORIGIN on this item if it's a comment, because
+ // it was already deleted, and we're already relaying, and this ensures that no other process or
+ // code path downstream can relay it again (causing a loop). Since it's already gone it's not coming
+ // back, and we aren't going to (or shouldn't at any rate) delete it again in the future - so losing
+ // this information from the metadata should have no other discernible impact.
+
+ if(($r[0]['id'] != $r[0]['parent']) && ($r[0]['item_flags'] & ITEM_ORIGIN)) {
+ $x = q("update item set item_flags = %d where id = %d and uid = %d",
+ intval($r[0]['item_flags'] ^ ITEM_ORIGIN),
+ intval($r[0]['id']),
+ intval($r[0]['uid'])
+ );
+ }
}
+
require_once('include/items.php');
@@ -2244,10 +2346,11 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = UPDATE_FLAGS_
dbesc($hash)
);
- $age = intval($arr['xprof_age']);
- if($age > 150)
- $age = 150;
-
+ if($arr['xprof_age'] > 150)
+ $arr['xprof_age'] = 150;
+ if($arr['xprof_age'] < 0)
+ $arr['xprof_age'] = 0;
+
if($r) {
$update = false;
foreach($r[0] as $k => $v) {
@@ -2276,7 +2379,7 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = UPDATE_FLAGS_
where xprof_hash = '%s'",
dbesc($arr['xprof_desc']),
dbesc($arr['xprof_dob']),
- $age,
+ intval($arr['xprof_age']),
dbesc($arr['xprof_gender']),
dbesc($arr['xprof_marital']),
dbesc($arr['xprof_sexual']),
@@ -2299,7 +2402,7 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = UPDATE_FLAGS_
dbesc($arr['xprof_hash']),
dbesc($arr['xprof_desc']),
dbesc($arr['xprof_dob']),
- $age,
+ intval($arr['xprof_age']),
dbesc($arr['xprof_gender']),
dbesc($arr['xprof_marital']),
dbesc($arr['xprof_sexual']),
@@ -2793,6 +2896,9 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) {
if(count($clean)) {
foreach($clean as $k => $v) {
+ if($k == 'abook_dob')
+ $v = dbescdate($v);
+
$r = dbq("UPDATE abook set " . dbesc($k) . " = '" . dbesc($v)
. "' where abook_xchan = '" . dbesc($clean['abook_xchan']) . "' and abook_channel = " . intval($channel['channel_id']));
}