aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Zotlabs/Lib')
-rw-r--r--Zotlabs/Lib/Activity.php148
-rw-r--r--Zotlabs/Lib/Enotify.php12
-rw-r--r--Zotlabs/Lib/Libsync.php16
-rw-r--r--Zotlabs/Lib/Libzot.php61
-rw-r--r--Zotlabs/Lib/ThreadItem.php4
-rw-r--r--Zotlabs/Lib/ThreadStream.php2
6 files changed, 175 insertions, 68 deletions
diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
index d883eac67..9a31304d1 100644
--- a/Zotlabs/Lib/Activity.php
+++ b/Zotlabs/Lib/Activity.php
@@ -314,17 +314,29 @@ class Activity {
else {
$objtype = self::activity_obj_mapper($i['obj_type']);
}
-
- if(intval($i['item_deleted'])) {
+
+ if ($i['obj']) {
+ $ret = Activity::encode_object($i['obj']);
+ }
+
+ if (intval($i['item_deleted'])) {
$ret['type'] = 'Tombstone';
$ret['formerType'] = $objtype;
- $ret['id'] = ((strpos($i['mid'],'http') === 0) ? $i['mid'] : z_root() . '/item/' . urlencode($i['mid']));
+ $ret['id'] = $i['mid'];
+ if($i['id'] != $i['parent'])
+ $ret['inReplyTo'] = $i['thr_parent'];
+
+ $ret['to'] = [ ACTIVITY_PUBLIC_INBOX ];
return $ret;
}
-
if ($i['obj']) {
- $ret = Activity::encode_object($i['obj']);
+ if (is_array($i['obj'])) {
+ $ret = $i['obj'];
+ }
+ else {
+ $ret = json_decode($i['obj'],true);
+ }
}
$ret['type'] = $objtype;
@@ -640,7 +652,7 @@ class Activity {
- static function encode_activity($i) {
+ static function encode_activity($i, $dismiss_deleted = false) {
$ret = [];
$reply = false;
@@ -651,20 +663,47 @@ class Activity {
$ret['obj'] = [];
}
- if(intval($i['item_deleted'])) {
- $ret['type'] = 'Tombstone';
- $ret['formerType'] = self::activity_obj_mapper($i['obj_type']);
- $ret['id'] = ((strpos($i['mid'],'http') === 0) ? $i['mid'] : z_root() . '/item/' . urlencode($i['mid']));
+ $ret['type'] = self::activity_mapper($i['verb']);
+ $fragment = '';
+
+ if (intval($i['item_deleted']) && !$dismiss_deleted) {
+ $is_response = false;
+
+ if (in_array($ret['type'], [ 'Like', 'Dislike', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject' ])) {
+ $ret['type'] = 'Undo';
+ $fragment = 'undo';
+ $is_response = true;
+ }
+ else {
+ $ret['type'] = 'Delete';
+ $fragment = 'delete';
+ }
+
+ $ret['id'] = str_replace('/item/','/activity/',$i['mid']) . '#' . $fragment;
$actor = self::encode_person($i['author'],false);
- if($actor)
+ if ($actor)
$ret['actor'] = $actor;
else
return [];
- return $ret;
- }
+// $ret['object'] = str_replace('/item/','/activity/',$i['mid']);
- $ret['type'] = self::activity_mapper($i['verb']);
+ $obj = (($is_response) ? self::encode_activity($i,true) : self::encode_item($i,true));
+ if ($obj) {
+ // do not leak private content in deletes
+ unset($obj['object']);
+ unset($obj['cc']);
+ $obj['to'] = [ ACTIVITY_PUBLIC_INBOX ];
+ $ret['object'] = $obj;
+ }
+ else
+ return [];
+
+ $ret['to'] = [ ACTIVITY_PUBLIC_INBOX ];
+
+ return $ret;
+
+ }
if($ret['type'] === 'emojiReaction') {
// There may not be an object for these items for legacy reasons - it should be the conversation parent.
@@ -1060,6 +1099,8 @@ class Activity {
'http://purl.org/zot/activity/attendno' => 'Reject',
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept',
'Invite' => 'Invite',
+ 'Delete' => 'Delete',
+ 'Undo' => 'Undo'
];
call_hooks('activity_mapper',$acts);
@@ -1107,6 +1148,8 @@ class Activity {
'http://purl.org/zot/activity/attendno' => 'Reject',
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept',
'Invite' => 'Invite',
+ 'Delete' => 'Delete',
+ 'Undo' => 'Undo'
];
call_hooks('activity_decode_mapper',$acts);
@@ -1143,7 +1186,9 @@ class Activity {
'Question' => 'Question',
'Document' => 'Document',
'Audio' => 'Audio',
- 'Video' => 'Video'
+ 'Video' => 'Video',
+ 'Delete' => 'Delete',
+ 'Undo' => 'Undo'
];
call_hooks('activity_obj_decode_mapper',$objs);
@@ -1180,7 +1225,9 @@ class Activity {
'Invite' => 'Invite',
'Question' => 'Question',
'Audio' => 'Audio',
- 'Video' => 'Video'
+ 'Video' => 'Video',
+ 'Delete' => 'Delete',
+ 'Undo' => 'Undo'
];
call_hooks('activity_obj_mapper',$objs);
@@ -1456,11 +1503,35 @@ class Activity {
$icon = $person_obj['icon'];
}
- if(is_array($person_obj['url']) && array_key_exists('href', $person_obj['url']))
- $profile = $person_obj['url']['href'];
- else
- $profile = $url;
+ $links = false;
+ $profile = false;
+ if (is_array($person_obj['url'])) {
+ if (! array_key_exists(0,$person_obj['url'])) {
+ $links = [ $person_obj['url'] ];
+ }
+ else {
+ $links = $person_obj['url'];
+ }
+ }
+
+ if ($links) {
+ foreach ($links as $link) {
+ if (array_key_exists('mediaType',$link) && $link['mediaType'] === 'text/html') {
+ $profile = $link['href'];
+ }
+ }
+ if (! $profile) {
+ $profile = $links[0]['href'];
+ }
+ }
+ elseif (isset($person_obj['url']) && is_string($person_obj['url'])) {
+ $profile = $person_obj['url'];
+ }
+
+ if (! $profile) {
+ $profile = $url;
+ }
$inbox = $person_obj['inbox'];
@@ -1492,6 +1563,7 @@ class Activity {
);
if(! $r) {
// create a new record
+
$r = xchan_store_lowlevel(
[
'xchan_hash' => $url,
@@ -1985,8 +2057,8 @@ class Activity {
$response_activity = true;
$s['mid'] = $act->id;
- $s['parent_mid'] = $act->obj['id'];
- $s['uuid'] = $act->{'diaspora:guid'};
+ // $s['parent_mid'] = $act->obj['id'];
+ $s['uuid'] = $act->data['diaspora:guid'];
// over-ride the object timestamp with the activity
@@ -2052,12 +2124,10 @@ class Activity {
$s['edited'] = datetime_convert();
}
- if($act->type === 'Tombstone' || $act->type === 'Delete' || ($act->type === 'Create' && $act->obj['type'] === 'Tombstone')) {
+ if(in_array($act->type, [ 'Delete', 'Undo', 'Tombstone' ]) || ($act->type === 'Create' && $act->obj['type'] === 'Tombstone')) {
$s['item_deleted'] = 1;
}
-
-
$s['obj_type'] = self::activity_obj_decode_mapper($act->obj['type']);
if($s['obj_type'] === ACTIVITY_OBJ_NOTE && $s['mid'] !== $s['parent_mid']) {
$s['obj_type'] = ACTIVITY_OBJ_COMMENT;
@@ -2561,8 +2631,8 @@ class Activity {
switch($a->type) {
case 'Create':
case 'Update':
- case 'Like':
- case 'Dislike':
+ //case 'Like':
+ //case 'Dislike':
case 'Announce':
$item = self::decode_note($a);
break;
@@ -3069,5 +3139,29 @@ class Activity {
return $content;
}
+ // Find either an Authorization: Bearer token or 'token' request variable
+ // in the current web request and return it
+
+ static function token_from_request() {
+
+ foreach ( [ 'REDIRECT_REMOTE_USER', 'HTTP_AUTHORIZATION' ] as $s ) {
+ $auth = ((array_key_exists($s,$_SERVER) && strpos($_SERVER[$s],'Bearer ') === 0)
+ ? str_replace('Bearer ', EMPTY_STR, $_SERVER[$s])
+ : EMPTY_STR
+ );
+ if ($auth) {
+ break;
+ }
+ }
+
+ if (! $auth) {
+ if (array_key_exists('token',$_REQUEST) && $_REQUEST['token']) {
+ $auth = $_REQUEST['token'];
+ }
+ }
+
+ return $auth;
+ }
+
}
diff --git a/Zotlabs/Lib/Enotify.php b/Zotlabs/Lib/Enotify.php
index f706b0fb9..03a824b9b 100644
--- a/Zotlabs/Lib/Enotify.php
+++ b/Zotlabs/Lib/Enotify.php
@@ -856,11 +856,11 @@ class Enotify {
'photo' => $item[$who]['xchan_photo_s'],
'when' => (($edit) ? datetime_convert('UTC', date_default_timezone_get(), $item['edited']) : datetime_convert('UTC', date_default_timezone_get(), $item['created'])),
'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
- 'b64mid' => 'b64.' . base64url_encode($item['mid']),
+ 'b64mid' => (($item['mid']) ? 'b64.' . base64url_encode($item['mid']) : ''),
//'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? 'b64.' . base64url_encode($item['thr_parent']) : 'b64.' . base64url_encode($item['mid'])),
- 'notify_id' => 'undefined',
'thread_top' => (($item['item_thread_top']) ? true : false),
'message' => bbcode(escape_tags($itemem_text)),
+ 'body' => htmlentities(html2plain(bbcode($item['body']), 75, true), ENT_COMPAT, 'UTF-8', false),
// these are for the superblock addon
'hash' => $item[$who]['xchan_hash'],
'uid' => $item['uid'],
@@ -885,7 +885,6 @@ class Enotify {
$mid = basename($tt['link']);
$b64mid = ((strpos($mid, 'b64.') === 0) ? $mid : 'b64.' . base64url_encode($mid));
-
$x = [
'notify_link' => z_root() . '/notify/view/' . $tt['id'],
'name' => $tt['xname'],
@@ -893,8 +892,8 @@ class Enotify {
'photo' => $tt['photo'],
'when' => datetime_convert('UTC', date_default_timezone_get(), $tt['created']),
'hclass' => (($tt['seen']) ? 'notify-seen' : 'notify-unseen'),
- 'b64mid' => (($tt['otype'] == 'item') ? $b64mid : 'undefined'),
- 'notify_id' => (($tt['otype'] == 'item') ? $tt['id'] : 'undefined'),
+ 'b64mid' => (($tt['otype'] == 'item') ? $b64mid : ''),
+ 'notify_id' => (($tt['otype'] == 'item') ? $tt['id'] : ''),
'message' => $message
];
@@ -980,8 +979,7 @@ class Enotify {
$x = [
'notify_link' => z_root() . '/admin/accounts',
'name' => $rr['account_email'],
- 'addr' => $rr['account_email'],
- 'url' => '',
+ //'addr' => $rr['account_email'],
'photo' => z_root() . '/' . get_default_profile_photo(48),
'when' => datetime_convert('UTC', date_default_timezone_get(),$rr['account_created']),
'hclass' => ('notify-unseen'),
diff --git a/Zotlabs/Lib/Libsync.php b/Zotlabs/Lib/Libsync.php
index b7cda1770..cff320e11 100644
--- a/Zotlabs/Lib/Libsync.php
+++ b/Zotlabs/Lib/Libsync.php
@@ -819,9 +819,9 @@ class Libsync {
}
if(intval($r[0]['hubloc_primary']) && (! $location['primary'])) {
- $m = q("update hubloc set hubloc_primary = 0, hubloc_updated = '%s' where hubloc_id = %d",
+ $m = q("update hubloc set hubloc_primary = 0, hubloc_updated = '%s' where hubloc_id_url = '%s'",
dbesc(datetime_convert()),
- intval($r[0]['hubloc_id'])
+ dbesc($r[0]['hubloc_id_url'])
);
$r[0]['hubloc_primary'] = intval($location['primary']);
hubloc_change_primary($r[0]);
@@ -848,18 +848,18 @@ class Libsync {
}
}
if(intval($r[0]['hubloc_deleted']) && (! intval($location['deleted']))) {
- $n = q("update hubloc set hubloc_deleted = 0, hubloc_updated = '%s' where hubloc_id = %d",
+ $n = q("update hubloc set hubloc_deleted = 0, hubloc_updated = '%s' where hubloc_id_url = '%s'",
dbesc(datetime_convert()),
- intval($r[0]['hubloc_id'])
+ dbesc($r[0]['hubloc_id_url'])
);
$what .= 'undelete_hub ';
$changed = true;
}
elseif((! intval($r[0]['hubloc_deleted'])) && (intval($location['deleted']))) {
logger('deleting hubloc: ' . $r[0]['hubloc_addr']);
- $n = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id = %d",
+ $n = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id_url = '%s'",
dbesc(datetime_convert()),
- intval($r[0]['hubloc_id'])
+ dbesc($r[0]['hubloc_id_url'])
);
$what .= 'delete_hub ';
$changed = true;
@@ -918,9 +918,9 @@ class Libsync {
foreach($xisting as $x) {
if(! array_key_exists('updated',$x)) {
logger('Deleting unreferenced hub location ' . $x['hubloc_addr']);
- $r = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id = %d",
+ $r = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id_url = '%s'",
dbesc(datetime_convert()),
- intval($x['hubloc_id'])
+ dbesc($x['hubloc_id_url'])
);
$what .= 'removed_hub ';
$changed = true;
diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php
index dda6d5d95..f16f5258a 100644
--- a/Zotlabs/Lib/Libzot.php
+++ b/Zotlabs/Lib/Libzot.php
@@ -316,14 +316,22 @@ class Libzot {
$x = self::import_xchan($record['data'], (($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
+
if(! $x['success'])
return false;
if($channel && $record['data']['permissions']) {
$permissions = explode(',',$record['data']['permissions']);
+
if($permissions && is_array($permissions)) {
$old_read_stream_perm = get_abconfig($channel['channel_id'],$x['hash'],'their_perms','view_stream');
+ // We need to reset their_perms prior to setting the new ones.
+ // Otherwise withdrawn permissions will not take effect locally.
+ q("DELETE FROM abconfig WHERE chan = %d AND xchan = '%s' AND cat = 'their_perms'",
+ intval($channel['channel_id']),
+ dbesc($x['hash'])
+ );
foreach($permissions as $p) {
set_abconfig($channel['channel_id'],$x['hash'],'their_perms',$p,'1');
}
@@ -1133,6 +1141,7 @@ class Libzot {
}
logger($AS->debug(),LOGGER_DATA);
+
}
@@ -1193,10 +1202,6 @@ class Libzot {
if(in_array($env['type'],['activity','response'])) {
- $arr = Activity::decode_note($AS);
-
- //logger($AS->debug());
-
$r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s' ",
dbesc($AS->actor['id'])
);
@@ -1488,13 +1493,14 @@ class Libzot {
// Try again using the delivery channel credentials.
// We will also need to re-parse the $item array,
// but preserve any values that were set during anonymous parsing.
-
+
$o = Activity::fetch($act->obj,$channel);
if($o) {
$act->obj = $o;
$arr = array_merge(Activity::decode_note($act),$arr);
}
else {
+
$DR->update('Incomplete or corrupt activity');
$result[] = $DR->get();
continue;
@@ -1717,7 +1723,7 @@ class Libzot {
$arr['aid'] = $channel['channel_account_id'];
$arr['uid'] = $channel['channel_id'];
- $item_id = self::delete_imported_item($sender,$arr,$channel['channel_id'],$relay);
+ $item_id = self::delete_imported_item($sender,$act,$arr,$channel['channel_id'],$relay);
$DR->update(($item_id) ? 'deleted' : 'delete_failed');
$result[] = $DR->get();
@@ -1731,11 +1737,15 @@ class Libzot {
continue;
}
+ // reactions such as like and dislike could have an mid with /activity/ in it.
+ // Check for both forms in order to prevent duplicates.
- $r = q("select * from item where mid = '%s' and uid = %d limit 1",
+ $r = q("select * from item where mid in ('%s','%s') and uid = %d limit 1",
dbesc($arr['mid']),
+ dbesc(str_replace(z_root() . '/activity/', z_root() . '/item/', $arr['mid'])),
intval($channel['channel_id'])
);
+
if($r) {
// We already have this post.
$item_id = $r[0]['id'];
@@ -2096,7 +2106,7 @@ class Libzot {
* @return boolean|int post_id
*/
- static function delete_imported_item($sender, $item, $uid, $relay) {
+ static function delete_imported_item($sender, $act, $item, $uid, $relay) {
logger('invoked', LOGGER_DEBUG);
@@ -2104,38 +2114,39 @@ class Libzot {
$item_found = false;
$post_id = 0;
+ if ($item['verb'] === 'Tombstone') {
+ // The id of the deleted thing is the item mid (activity id)
+ $mid = $item['mid'];
+ }
+ else {
+ // The id is the object id if the type is Undo or Delete
+ $mid = ((is_array($act->obj)) ? $act->obj['id'] : $act->obj);
+ }
+
+ // we may have stored either the object id or the activity id if it was a response activity (like, dislike, etc.)
+
$r = q("select * from item where ( author_xchan = '%s' or owner_xchan = '%s' or source_xchan = '%s' )
- and mid = '%s' and uid = %d limit 1",
+ and mid IN ('%s', '%s') and uid = %d limit 1",
dbesc($sender),
dbesc($sender),
dbesc($sender),
- dbesc($item['mid']),
+ dbesc($mid),
+ dbesc(str_replace('/activity/','/item/',$mid)),
intval($uid)
);
if($r) {
$stored = $r[0];
- if($stored['author_xchan'] === $sender || $stored['owner_xchan'] === $sender || $stored['source_xchan'] === $sender)
- $ownership_valid = true;
+ // we proved ownership in the sql query
+ $ownership_valid = true;
$post_id = $stored['id'];
$item_found = true;
}
else {
-
- // perhaps the item is still in transit and the delete notification got here before the actual item did. Store it with the deleted flag set.
- // item_store() won't try to deliver any notifications or start delivery chains if this flag is set.
- // This means we won't end up with potentially even more delivery threads trying to push this delete notification.
- // But this will ensure that if the (undeleted) original post comes in at a later date, we'll reject it because it will have an older timestamp.
-
- logger('delete received for non-existent item - storing item data.');
-
- if($item['author_xchan'] === $sender || $item['owner_xchan'] === $sender || $item['source_xchan'] === $sender) {
- $ownership_valid = true;
- $item_result = item_store($item);
- $post_id = $item_result['item_id'];
- }
+ // this will fail with an ownership issue, so explain the real reason
+ logger('delete received for non-existent item or not owned by sender - ignoring.');
}
if($ownership_valid === false) {
diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php
index fadc38b38..024502d2a 100644
--- a/Zotlabs/Lib/ThreadItem.php
+++ b/Zotlabs/Lib/ThreadItem.php
@@ -287,12 +287,16 @@ class ThreadItem {
$settings = '';
+ $tagger = [];
+
// FIXME - check this permission
if($conv->get_profile_owner() == local_channel()) {
+ /* disable until we agree on how to implemnt this in zot6/activitypub
$tagger = array(
'tagit' => t("Add Tag"),
'classtagger' => "",
);
+ */
$settings = t('Conversation Tools');
}
diff --git a/Zotlabs/Lib/ThreadStream.php b/Zotlabs/Lib/ThreadStream.php
index 020e8729b..68b2c70dd 100644
--- a/Zotlabs/Lib/ThreadStream.php
+++ b/Zotlabs/Lib/ThreadStream.php
@@ -23,7 +23,7 @@ class ThreadStream {
private $preview = false;
private $prepared_item = '';
public $reload = '';
- private $cipher = 'aes256';
+ private $cipher = 'AES-128-CCM';
// $prepared_item is for use by alternate conversation structures such as photos
// wherein we've already prepared a top level item which doesn't look anything like