aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs
diff options
context:
space:
mode:
Diffstat (limited to 'Zotlabs')
-rw-r--r--Zotlabs/Daemon/Cron.php12
-rw-r--r--Zotlabs/Daemon/Cron_daily.php11
-rw-r--r--Zotlabs/Daemon/Expire.php7
-rw-r--r--Zotlabs/Daemon/Onedirsync.php48
-rw-r--r--Zotlabs/Daemon/Onepoll.php12
-rw-r--r--Zotlabs/Daemon/Poller.php36
-rw-r--r--Zotlabs/Daemon/Queue.php17
-rw-r--r--Zotlabs/Daemon/Zotconvo.php32
-rw-r--r--Zotlabs/Lib/Activity.php185
-rw-r--r--Zotlabs/Lib/ActivityStreams.php3
-rw-r--r--Zotlabs/Lib/Connect.php3
-rw-r--r--Zotlabs/Lib/Libsync.php11
-rw-r--r--Zotlabs/Lib/Libzot.php137
-rw-r--r--Zotlabs/Lib/Libzotdir.php358
-rw-r--r--Zotlabs/Lib/Queue.php24
-rw-r--r--Zotlabs/Lib/QueueWorker.php7
-rw-r--r--Zotlabs/Lib/ThreadItem.php4
-rw-r--r--Zotlabs/Module/Admin/Security.php61
-rw-r--r--Zotlabs/Module/Admin/Site.php18
-rw-r--r--Zotlabs/Module/Conversation.php188
-rw-r--r--Zotlabs/Module/Dircensor.php38
-rw-r--r--Zotlabs/Module/Directory.php25
-rw-r--r--Zotlabs/Module/Dirsearch.php63
-rw-r--r--Zotlabs/Module/Item.php99
-rw-r--r--Zotlabs/Module/Like.php6
-rw-r--r--Zotlabs/Module/Owa.php3
-rw-r--r--Zotlabs/Module/Photo.php3
-rw-r--r--Zotlabs/Module/Profiles.php7
-rw-r--r--Zotlabs/Module/Search.php4
-rw-r--r--Zotlabs/Module/Wfinger.php9
-rw-r--r--Zotlabs/Thumbs/Epubthumb.php7
-rw-r--r--Zotlabs/Thumbs/Mp3audio.php9
-rw-r--r--Zotlabs/Thumbs/Pdf.php6
-rw-r--r--Zotlabs/Thumbs/Text.php5
-rw-r--r--Zotlabs/Thumbs/Video.php13
-rw-r--r--Zotlabs/Update/_1256.php36
-rw-r--r--Zotlabs/Update/_1257.php33
-rw-r--r--Zotlabs/Update/_1258.php14
-rw-r--r--Zotlabs/Widget/Pinned.php2
39 files changed, 972 insertions, 584 deletions
diff --git a/Zotlabs/Daemon/Cron.php b/Zotlabs/Daemon/Cron.php
index 640f06102..caae0ce53 100644
--- a/Zotlabs/Daemon/Cron.php
+++ b/Zotlabs/Daemon/Cron.php
@@ -3,6 +3,7 @@
namespace Zotlabs\Daemon;
use Zotlabs\Lib\Libsync;
+use Zotlabs\Lib\Libzotdir;
class Cron {
@@ -35,6 +36,17 @@ class Cron {
logger('cron: start');
+ // If this is a directory server, request a sync with an upstream
+ // directory at least once a day, up to once every poll interval.
+ // Pull remote changes and push local changes.
+ // potential issue: how do we keep from creating an endless update loop?
+
+ $dirmode = get_config('system', 'directory_mode');
+
+ if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
+ Libzotdir::sync_directories($dirmode);
+ }
+
// run queue delivery process in the background
Master::Summon(array('Queue'));
diff --git a/Zotlabs/Daemon/Cron_daily.php b/Zotlabs/Daemon/Cron_daily.php
index 6d62836c7..850d38229 100644
--- a/Zotlabs/Daemon/Cron_daily.php
+++ b/Zotlabs/Daemon/Cron_daily.php
@@ -94,17 +94,6 @@ class Cron_daily {
// expire any expired accounts
downgrade_accounts();
- // If this is a directory server, request a sync with an upstream
- // directory at least once a day, up to once every poll interval.
- // Pull remote changes and push local changes.
- // potential issue: how do we keep from creating an endless update loop?
-
- $dirmode = get_config('system', 'directory_mode');
-
- if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
- Libzotdir::sync_directories($dirmode);
- }
-
Master::Summon(array('Expire'));
Master::Summon(array('Cli_suggest'));
diff --git a/Zotlabs/Daemon/Expire.php b/Zotlabs/Daemon/Expire.php
index 5d9f14b28..84a606dc2 100644
--- a/Zotlabs/Daemon/Expire.php
+++ b/Zotlabs/Daemon/Expire.php
@@ -32,7 +32,6 @@ class Expire {
}
// physically remove anything that has been deleted for more than two months
- /** @FIXME - this is a wretchedly inefficient query */
q("delete from item where item_pending_remove = 1 and changed < %s - INTERVAL %s",
db_utcnow(),
@@ -59,8 +58,8 @@ class Expire {
continue;
// service class default (if non-zero) over-rides the site default
-
$service_class_expire = service_class_fetch($rr['channel_id'], 'expire_days');
+
if (intval($service_class_expire))
$channel_expire = $service_class_expire;
else
@@ -85,7 +84,6 @@ class Expire {
// this should probably just fetch the channel_expire_days from the sys channel,
// but there's no convenient way to set it.
-
$expire_days = get_config('system', 'sys_expire_days');
if ($expire_days === false)
$expire_days = 30;
@@ -96,8 +94,9 @@ class Expire {
logger('Expire: sys interval: ' . $expire_days, LOGGER_DEBUG);
- if ($expire_days)
+ if ($expire_days) {
item_expire($x['channel_id'], $expire_days, $commented_days);
+ }
logger('Expire: sys: done', LOGGER_DEBUG);
}
diff --git a/Zotlabs/Daemon/Onedirsync.php b/Zotlabs/Daemon/Onedirsync.php
index ea995be9e..b711b0c05 100644
--- a/Zotlabs/Daemon/Onedirsync.php
+++ b/Zotlabs/Daemon/Onedirsync.php
@@ -15,61 +15,45 @@ class Onedirsync {
$update_id = intval($argv[1]);
if (!$update_id) {
- logger('onedirsync: no update');
+ logger('onedirsync: no update id');
return;
}
- $r = q("select * from updates where ud_id = %d limit 1",
+ $r = q("select * from updates where ud_id = %d",
intval($update_id)
);
- if (!$r)
- return;
-
- if (($r[0]['ud_flags'] & UPDATE_FLAGS_UPDATED) || (!$r[0]['ud_addr']))
- return;
-
- // Have we probed this channel more recently than the other directory server
- // (where we received this update from) ?
- // If we have, we don't need to do anything except mark any older entries updated
-
- $x = q("select * from updates where ud_addr = '%s' and ud_date > '%s' and ( ud_flags & %d )>0 order by ud_date desc limit 1",
- dbesc($r[0]['ud_addr']),
- dbesc($r[0]['ud_date']),
- intval(UPDATE_FLAGS_UPDATED)
- );
- if ($x) {
- q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 and ud_date != '%s'",
- intval(UPDATE_FLAGS_UPDATED),
- dbesc($r[0]['ud_addr']),
- intval(UPDATE_FLAGS_UPDATED),
- dbesc($x[0]['ud_date'])
- );
+ if (!$r) {
+ logger('onedirsync: update id not found');
return;
}
// ignore doing an update if this ud_addr refers to a known dead hubloc
- $h = q("select * from hubloc where hubloc_addr = '%s'",
+ $h = q("select * from hubloc where hubloc_id_url = '%s' order by hubloc_id desc",
dbesc($r[0]['ud_addr']),
);
$h = Libzot::zot_record_preferred($h);
if (($h) && (($h['hubloc_status'] & HUBLOC_OFFLINE) || $h['hubloc_deleted'] || $h['hubloc_error'])) {
- q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 ",
- intval(UPDATE_FLAGS_DELETED),
- dbesc($r[0]['ud_addr']),
- intval(UPDATE_FLAGS_UPDATED)
- );
- return;
+
+ // 2023-04-12: Try to update anyway since the info is not always correct
+ // This might change after all directory servers run the new code.
+
+ // q("update updates set ud_flags = 9 where ud_hash = '%s' and ud_flags != 9",
+ // dbesc($r[0]['ud_hash'])
+ //);
+
+ // return;
}
// we might have to pull this out some day, but for now update_directory_entry()
// runs zot_finger() and is kind of zot specific
- if ($h && $h['hubloc_network'] !== 'zot6')
+ if ($h && $h['hubloc_network'] !== 'zot6') {
return;
+ }
Libzotdir::update_directory_entry($r[0]);
diff --git a/Zotlabs/Daemon/Onepoll.php b/Zotlabs/Daemon/Onepoll.php
index bde39007e..973bcf402 100644
--- a/Zotlabs/Daemon/Onepoll.php
+++ b/Zotlabs/Daemon/Onepoll.php
@@ -30,14 +30,10 @@ class Onepoll {
$sql_extra = ' and abook_feed = 0 ';
}
- $contacts = q("SELECT abook.*, xchan.*, account.*
- FROM abook LEFT JOIN account on abook_account = account_id left join xchan on xchan_hash = abook_xchan
- where abook_id = %d $sql_extra
- and abook_pending = 0 and abook_archived = 0 and abook_blocked = 0 and abook_ignored = 0
- AND (( account_flags = %d ) OR ( account_flags = %d )) limit 1",
- intval($contact_id),
- intval(ACCOUNT_OK),
- intval(ACCOUNT_UNVERIFIED)
+ $contacts = q("SELECT abook.*, xchan.* FROM abook
+ LEFT JOIN xchan ON xchan_hash = abook_xchan
+ WHERE abook_id = %d",
+ intval($contact_id)
);
if (!$contacts) {
diff --git a/Zotlabs/Daemon/Poller.php b/Zotlabs/Daemon/Poller.php
index 0fdc3da16..77a428ec3 100644
--- a/Zotlabs/Daemon/Poller.php
+++ b/Zotlabs/Daemon/Poller.php
@@ -19,24 +19,6 @@ class Poller {
$interval = get_config('queueworker', 'queue_interval', 500000);
-/*
- if (!$interval) {
- $interval = ((get_config('system', 'delivery_interval') === false) ? 3 : intval(get_config('system', 'delivery_interval')));
- }
-
- // Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
- $lockfile = 'store/[data]/poller';
- if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
- && (!get_config('system', 'override_poll_lockfile'))) {
- logger("poller: Already running");
- return;
- }
-
- // Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
- $x = '';
- file_put_contents($lockfile, $x);
-*/
-
logger('poller: start');
$manual_id = 0;
@@ -67,6 +49,11 @@ class Poller {
: ''
);
+ $allow_feeds = get_config('system', 'feed_contacts');
+ if(!$allow_feeds) {
+ $sql_extra .= ' and abook_feed = 0 ';
+ }
+
$randfunc = db_getfunc('RAND');
$contacts = q("SELECT abook.abook_updated, abook.abook_connected, abook.abook_feed,
@@ -76,7 +63,7 @@ class Poller {
account.account_lastlog, account.account_flags
FROM abook LEFT JOIN xchan on abook_xchan = xchan_hash
LEFT JOIN account on abook_account = account_id
- where abook_self = 0
+ where abook_self = 0 and abook_pending = 0 and abook_archived = 0 and abook_blocked = 0 and abook_ignored = 0
$sql_extra
AND (( account_flags = %d ) OR ( account_flags = %d )) $abandon_sql ORDER BY $randfunc",
intval(ACCOUNT_OK),
@@ -183,11 +170,12 @@ class Poller {
$dirmode = intval(get_config('system', 'directory_mode'));
if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
- $r = q("SELECT u.ud_addr, u.ud_id, u.ud_last FROM updates AS u INNER JOIN (SELECT ud_addr, max(ud_id) AS ud_id FROM updates WHERE ( ud_flags & %d ) = 0 AND ud_addr != '' AND ( ud_last <= '%s' OR ud_last > %s - INTERVAL %s ) GROUP BY ud_addr) AS s ON s.ud_id = u.ud_id ",
- intval(UPDATE_FLAGS_UPDATED),
+ $r = q("SELECT * FROM updates WHERE ud_update = 1 AND (ud_last = '%s' OR ud_last > %s - INTERVAL %s)",
dbesc(NULL_DATE),
- db_utcnow(), db_quoteinterval('7 DAY')
+ db_utcnow(),
+ db_quoteinterval('7 DAY')
);
+
if ($r) {
foreach ($r as $rr) {
@@ -209,10 +197,6 @@ class Poller {
set_config('system', 'lastpoll', datetime_convert());
- //All done - clear the lockfile
-/*
- @unlink($lockfile);
-*/
return;
}
}
diff --git a/Zotlabs/Daemon/Queue.php b/Zotlabs/Daemon/Queue.php
index b07fe369c..91aba831a 100644
--- a/Zotlabs/Daemon/Queue.php
+++ b/Zotlabs/Daemon/Queue.php
@@ -14,7 +14,7 @@ class Queue {
// delete all queue items more than 3 days old
// but first mark these sites dead if we haven't heard from them in a month
- $oldqItems = q("select outq_posturl from outq where outq_created < %s - INTERVAL %s",
+ $oldqItems = q("select outq_posturl, outq_hash from outq where outq_created < %s - INTERVAL %s",
db_utcnow(),
db_quoteinterval('3 DAY')
);
@@ -29,13 +29,13 @@ class Queue {
db_quoteinterval('1 MONTH')
);
}
- }
- logger('Removing ' . count($oldqItems) . ' old queue entries');
- q("DELETE FROM outq WHERE outq_created < %s - INTERVAL %s",
- db_utcnow(),
- db_quoteinterval('3 DAY')
- );
+ $old_hashes = ids_to_querystr($oldqItems, 'outq_hash', true);
+
+ logger('Removing ' . count($oldqItems) . ' old queue entries');
+ dbq("DELETE FROM outq WHERE outq_hash IN ($old_hashes)");
+
+ }
$deliveries = [];
@@ -47,9 +47,10 @@ class Queue {
LibQueue::deliver($qItems[0]);
}
else {
- $qItems = q("SELECT * FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s ",
+ $qItems = q("SELECT outq_hash FROM outq WHERE outq_scheduled < %s ",
db_utcnow()
);
+
if ($qItems) {
foreach ($qItems as $qItem) {
$deliveries[] = $qItem['outq_hash'];
diff --git a/Zotlabs/Daemon/Zotconvo.php b/Zotlabs/Daemon/Zotconvo.php
new file mode 100644
index 000000000..16e7f113f
--- /dev/null
+++ b/Zotlabs/Daemon/Zotconvo.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Zotlabs\Daemon;
+
+use Zotlabs\Lib\Libzot;
+
+class Zotconvo {
+
+ static public function run($argc, $argv) {
+
+ logger('Zotconvo invoked: ' . print_r($argv, true));
+
+ if ($argc != 3) {
+ return;
+ }
+
+ $mid = $argv[2];
+ if (!$mid) {
+ return;
+ }
+
+ $channel = channelx_by_n(intval($argv[1]));
+ if (!$channel) {
+ return;
+ }
+
+ Libzot::fetch_conversation($channel, $mid);
+
+ return;
+
+ }
+}
diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
index 416aaa0d8..fcf3fb172 100644
--- a/Zotlabs/Lib/Activity.php
+++ b/Zotlabs/Lib/Activity.php
@@ -289,7 +289,7 @@ class Activity {
static function encode_item_collection($items, $id, $type, $total = 0) {
- if ($total > 30) {
+ if ($total > App::$pager['itemspage']) {
$ret = [
'id' => z_root() . '/' . $id,
'type' => $type . 'Page',
@@ -591,9 +591,9 @@ class Activity {
foreach ($item['term'] as $t) {
switch ($t['ttype']) {
case TERM_HASHTAG:
- // id is required so if we don't have a url in the taxonomy, ignore it and keep going.
+ // href is required so if we don't have a url in the taxonomy, ignore it and keep going.
if ($t['url']) {
- $ret[] = ['type' => 'Hashtag', 'id' => $t['url'], 'name' => '#' . $t['term']];
+ $ret[] = ['type' => 'Hashtag', 'href' => $t['url'], 'name' => '#' . $t['term']];
}
break;
@@ -622,6 +622,10 @@ class Activity {
$atts = ((is_array($item['attach'])) ? $item['attach'] : json_decode($item['attach'], true));
if ($atts) {
foreach ($atts as $att) {
+ if (!isset($att['type'], $att['href'])) {
+ continue;
+ }
+
if (isset($att['type']) && strpos($att['type'], 'image')) {
$ret[] = ['type' => 'Image', 'url' => $att['href']];
}
@@ -676,7 +680,7 @@ class Activity {
$ret = [];
- if (isset($item['attachment'])) {
+ if (isset($item['attachment']) && is_array($item['attachment'])) {
$ptr = $item['attachment'];
if (!array_key_exists(0, $ptr)) {
$ptr = [$ptr];
@@ -1333,7 +1337,8 @@ class Activity {
}
}
- $x = PermissionRoles::role_perms('personal');
+ $role = get_pconfig($channel['channel_id'], 'system', 'permissions_role', 'personal');
+ $x = PermissionRoles::role_perms($role);
$their_perms = Permissions::FilledPerms($x['perms_connect']);
if ($contact && $contact['abook_id']) {
@@ -1358,10 +1363,15 @@ class Activity {
return;
case 'Accept':
+ // They accepted our Follow request.
+ // Set default permissions except for send_stream and post_wall
- // They accepted our Follow request - set default permissions
-
- set_abconfig($channel['channel_id'], $contact['abook_xchan'], 'system', 'their_perms', $their_perms);
+ foreach ($their_perms as $k => $v) {
+ if(in_array($k, ['send_stream', 'post_wall'])) {
+ $v = 0; // Those will be set once we accept their follow request
+ }
+ set_abconfig($channel['channel_id'], $contact['abook_xchan'], 'their_perms', $k, $v);
+ }
$abook_instance = $contact['abook_instance'];
@@ -2215,18 +2225,14 @@ class Activity {
}
static function decode_note($act) {
-
$response_activity = false;
-
$s = [];
// These activities should have been handled separately in the Inbox module and should not be turned into posts
if (
in_array($act->type, ['Follow', 'Accept', 'Reject', 'Create', 'Update']) &&
- is_array($act->obj) &&
- array_key_exists('type', $act->obj) &&
- ($act->obj['type'] === 'Follow' || ActivityStreams::is_an_actor($act->obj['type']))
+ ($act->objprop('type') === 'Follow' || ActivityStreams::is_an_actor($act->objprop('type')))
) {
return false;
}
@@ -2256,7 +2262,7 @@ class Activity {
$content = self::get_content($act->obj);
}
- $s['mid'] = ((is_array($act->obj) && isset($act->obj['id'])) ? $act->obj['id'] : $act->obj);
+ $s['mid'] = $act->objprop('id') ?: $act->obj;
if (!$s['mid']) {
return false;
@@ -2264,7 +2270,7 @@ class Activity {
// Friendica sends the diaspora guid in a nonstandard field via AP
// If no uuid is provided we will create an uuid v5 from the mid
- $s['uuid'] = ((is_array($act->obj) && isset($act->obj['diaspora:guid'])) ? $act->obj['diaspora:guid'] : uuid_from_url($s['mid']));
+ $s['uuid'] = (($act->objprop('diaspora:guid')) ?: uuid_from_url($s['mid']));
$s['parent_mid'] = $act->parent_id;
@@ -2272,24 +2278,24 @@ class Activity {
$s['created'] = datetime_convert('UTC', 'UTC', $act->data['published']);
$s['commented'] = $s['created'];
}
- elseif (is_array($act->obj) && array_key_exists('published', $act->obj)) {
+ elseif ($act->objprop('published')) {
$s['created'] = datetime_convert('UTC', 'UTC', $act->obj['published']);
$s['commented'] = $s['created'];
}
if (array_key_exists('updated', $act->data)) {
$s['edited'] = datetime_convert('UTC', 'UTC', $act->data['updated']);
}
- elseif (is_array($act->obj) && array_key_exists('updated', $act->obj)) {
+ elseif ($act->objprop('updated')) {
$s['edited'] = datetime_convert('UTC', 'UTC', $act->obj['updated']);
}
if (array_key_exists('expires', $act->data)) {
$s['expires'] = datetime_convert('UTC', 'UTC', $act->data['expires']);
}
- elseif (is_array($act->obj) && array_key_exists('expires', $act->obj)) {
+ elseif ($act->objprop('expires')) {
$s['expires'] = datetime_convert('UTC', 'UTC', $act->obj['expires']);
}
- if ($act->type === 'Invite' && is_array($act->obj) && array_key_exists('type', $act->obj) && $act->obj['type'] === 'Event') {
+ if ($act->type === 'Invite' && $act->objprop('type') === 'Event') {
$s['mid'] = $s['parent_mid'] = $act->id;
}
@@ -2298,9 +2304,18 @@ class Activity {
$response_activity = true;
$s['mid'] = $act->id;
- $s['uuid'] = ((is_array($act->data) && isset($act->data['diaspora:guid'])) ? $act->data['diaspora:guid'] : uuid_from_url($s['mid']));
+ $s['uuid'] = ((!empty($act->data['diaspora:guid'])) ? $act->data['diaspora:guid'] : uuid_from_url($s['mid']));
+
+ if ($act->objprop('inReplyTo')) {
+ $s['parent_mid'] = $act->objprop('inReplyTo');
+ }
+
+ $s['thr_parent'] = $act->objprop('id') ?: $act->obj;
- $s['parent_mid'] = ((is_array($act->obj) && isset($act->obj['id'])) ? $act->obj['id'] : $act->obj);
+ if (empty($s['parent_mid']) || empty($s['thr_parent'])) {
+ logger('response activity without parent_mid or thr_parent');
+ return;
+ }
// over-ride the object timestamp with the activity
@@ -2312,7 +2327,7 @@ class Activity {
$s['edited'] = datetime_convert('UTC', 'UTC', $act->data['updated']);
}
- $obj_actor = ((isset($act->obj['actor'])) ? $act->obj['actor'] : $act->get_actor('attributedTo', $act->obj));
+ $obj_actor = $act->objprop('actor') ?: $act->get_actor('attributedTo', $act->obj);
if (!isset($obj_actor['id'])) {
return false;
@@ -2331,7 +2346,7 @@ class Activity {
}
// handle event RSVPs
- if (($act->obj['type'] === 'Event') || ($act->obj['type'] === 'Invite' && array_path_exists('object/type', $act->obj) && $act->obj['object']['type'] === 'Event')) {
+ if (($act->objprop('type') === 'Event') || ($act->objprop('type') === 'Invite' && array_path_exists('object/type', $act->obj) && $act->obj['object']['type'] === 'Event')) {
if ($act->type === 'Accept') {
$content['content'] = sprintf(t('Will attend %s\'s event'), $mention) . EOL . EOL . $content['content'];
}
@@ -2366,7 +2381,7 @@ class Activity {
$s['item_thread_top'] = 1;
// it is a parent node - decode the comment policy info if present
- if (isset($act->obj['commentPolicy'])) {
+ if ($act->objprop('commentPolicy')) {
$until = strpos($act->obj['commentPolicy'], 'until=');
if ($until !== false) {
$s['comments_closed'] = datetime_convert('UTC', 'UTC', substr($act->obj['commentPolicy'], $until + 6));
@@ -2392,7 +2407,7 @@ class Activity {
$s['summary'] = self::bb_content($content, 'summary');
$s['body'] = ((self::bb_content($content, 'bbcode') && (!$response_activity)) ? self::bb_content($content, 'bbcode') : self::bb_content($content, 'content'));
- if (isset($act->obj['quoteUrl'])) {
+ if ($act->objprop('quoteUrl')) {
$quote_bbcode = self::get_quote_bbcode($act->obj['quoteUrl']);
if ($s['body']) {
@@ -2405,21 +2420,24 @@ class Activity {
$s['verb'] = self::activity_decode_mapper($act->type);
// Mastodon does not provide update timestamps when updating poll tallies which means race conditions may occur here.
- if ($act->type === 'Update' && $act->obj['type'] === 'Question' && $s['edited'] === $s['created']) {
+ if ($act->type === 'Update' && $act->objprop('type') === 'Question' && $s['edited'] === $s['created']) {
$s['edited'] = datetime_convert();
}
- if (in_array($act->type, ['Delete', 'Undo', 'Tombstone']) || ($act->type === 'Create' && $act->obj['type'] === 'Tombstone')) {
+ if (in_array($act->type, ['Delete', 'Undo', 'Tombstone']) || ($act->type === 'Create' && (isset($act->obj['type']) && $act->obj['type'] === 'Tombstone'))) {
$s['item_deleted'] = 1;
}
- $s['obj_type'] = self::activity_obj_decode_mapper($act->obj['type']);
+ if (isset($act->obj['type'])) {
+ $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;
}
$s['obj'] = $act->obj;
- if (is_array($s['obj']) && array_path_exists('actor/id', $s['obj'])) {
+ if (array_path_exists('actor/id', $s['obj'])) {
$s['obj']['actor'] = $s['obj']['actor']['id'];
}
@@ -2501,23 +2519,21 @@ class Activity {
}
}
- if (array_key_exists('type', $act->obj)) {
- // Objects that might have media attachments which aren't already provided in the content element.
- // We'll check specific media objects separately.
+ // Objects that might have media attachments which aren't already provided in the content element.
+ // We'll check specific media objects separately.
- if (in_array($act->obj['type'], ['Article', 'Document', 'Event', 'Note', 'Page', 'Place', 'Question']) && isset($s['attach']) && $s['attach']) {
- $s = self::bb_attach($s);
- }
+ if (in_array($act->objprop('type',''), ['Article', 'Document', 'Event', 'Note', 'Page', 'Place', 'Question']) && !empty($s['attach'])) {
+ $s = self::bb_attach($s);
+ }
- if ($act->obj['type'] === 'Question' && in_array($act->type, ['Create', 'Update'])) {
- if (array_key_exists('endTime', $act->obj)) {
- $s['comments_closed'] = datetime_convert('UTC', 'UTC', $act->obj['endTime']);
- }
+ if ($act->objprop('type') === 'Question' && in_array($act->type, ['Create', 'Update'])) {
+ if ($act->objprop('endTime')) {
+ $s['comments_closed'] = datetime_convert('UTC', 'UTC', $act->obj['endTime']);
}
}
- if (array_key_exists('closed', $act->obj)) {
+ if ($act->objprop('closed')) {
$s['comments_closed'] = datetime_convert('UTC', 'UTC', $act->obj['closed']);
}
@@ -2536,7 +2552,7 @@ class Activity {
// right now just link to the largest mp4 we find that will fit in our
// standard content region
- if ($act->obj['type'] === 'Video') {
+ if ($act->objprop('type') === 'Video') {
$vtypes = [
'video/mp4',
@@ -2550,7 +2566,7 @@ class Activity {
// try to find a poster to display on the video element
- if (array_key_exists('icon',$act->obj)) {
+ if ($act->objprop('icon')) {
if (is_array($act->obj['icon'])) {
if (array_key_exists(0,$act->obj['icon'])) {
$ptr = $act->obj['icon'];
@@ -2571,7 +2587,7 @@ class Activity {
$tag = (($poster) ? '[video poster=&quot;' . $poster . '&quot;]' : '[video]' );
$ptr = null;
- if (array_key_exists('url',$act->obj)) {
+ if ($act->objprop('url')) {
if (is_array($act->obj['url'])) {
if (array_key_exists(0,$act->obj['url'])) {
$ptr = $act->obj['url'];
@@ -2617,7 +2633,7 @@ class Activity {
}
}
- if ($act->obj['type'] === 'Audio') {
+ if ($act->objprop('type') === 'Audio') {
$atypes = [
'audio/mpeg',
@@ -2649,7 +2665,7 @@ class Activity {
}
- if ($act->obj['type'] === 'Image' && strpos($s['body'], 'zrl=') === false) {
+ if ($act->objprop('type') === 'Image' && strpos($s['body'], 'zrl=') === false) {
$ptr = null;
@@ -2678,7 +2694,7 @@ class Activity {
}
- if ($act->obj['type'] === 'Page' && !$s['body']) {
+ if ($act->objprop('type') === 'Page' && !$s['body']) {
$ptr = null;
$purl = EMPTY_STR;
@@ -2718,7 +2734,7 @@ class Activity {
}
}
- if (in_array($act->obj['type'], ['Note', 'Article', 'Page'])) {
+ if (in_array($act->objprop('type', ''), ['Note', 'Article', 'Page'])) {
$ptr = null;
if (array_key_exists('url', $act->obj)) {
@@ -2753,10 +2769,8 @@ class Activity {
$s['item_private'] = 0;
}
- if (is_array($act->obj)) {
- if (array_key_exists('directMessage', $act->obj) && intval($act->obj['directMessage'])) {
- $s['item_private'] = 2;
- }
+ if ($act->objprop('directMessage')) {
+ $s['item_private'] = 2;
}
$ap_rawmsg = '';
@@ -2839,7 +2853,6 @@ class Activity {
];
call_hooks('decode_note', $hookinfo);
-
return $hookinfo['s'];
}
@@ -2847,6 +2860,7 @@ class Activity {
static function store($channel, $observer_hash, $act, $item, $fetch_parents = true, $force = false) {
$is_sys_channel = is_sys_channel($channel['channel_id']);
$is_child_node = false;
+ $parent = null;
// TODO: not implemented
// Pleroma scrobbles can be really noisy and contain lots of duplicate activities. Disable them by default.
@@ -2863,25 +2877,26 @@ class Activity {
}
$allowed = false;
-
- // TODO: not implemented
$permit_mentions = intval(PConfig::Get($channel['channel_id'], 'system','permit_all_mentions') && i_am_mentioned($channel, $item));
if ($is_child_node) {
- $p = q("select * from item where mid = '%s' and uid = %d and item_wall = 1",
+ $parent = q("select * from item where mid = '%s' and uid = %d",
dbesc($item['parent_mid']),
intval($channel['channel_id'])
);
- if ($p) {
+
+ // TODO: if we do not have a parent stop here and move the fetch to background?
+
+ if ($parent && $parent[0]['item_wall']) {
// set the owner to the owner of the parent
- $item['owner_xchan'] = $p[0]['owner_xchan'];
+ $item['owner_xchan'] = $parent[0]['owner_xchan'];
// quietly reject group comment boosts by group owner
// (usually only sent via ActivityPub so groups will work on microblog platforms)
// This catches those activities if they slipped in via a conversation fetch
- if ($p[0]['parent_mid'] !== $item['parent_mid']) {
+ if ($parent[0]['parent_mid'] !== $item['parent_mid']) {
if ($item['verb'] === 'Announce' && $item['author_xchan'] === $item['owner_xchan']) {
logger('group boost activity by group owner rejected');
return;
@@ -2891,7 +2906,7 @@ class Activity {
// check permissions against the author, not the sender
$allowed = perm_is_allowed($channel['channel_id'], $item['author_xchan'], 'post_comments');
if ((!$allowed) && $permit_mentions) {
- if ($p[0]['owner_xchan'] === $channel['channel_hash']) {
+ if ($parent[0]['owner_xchan'] === $channel['channel_hash']) {
$allowed = false;
}
else {
@@ -2900,7 +2915,7 @@ class Activity {
}
// TODO: not implemented
- /*if (absolutely_no_comments($p[0])) {
+ /*if (absolutely_no_comments($parent[0])) {
$allowed = false;
}*/
@@ -2922,13 +2937,14 @@ class Activity {
else {
$allowed = true;
+
// reject public stream comments that weren't sent by the conversation owner
if ($is_sys_channel && $item['owner_xchan'] !== $observer_hash && !$fetch_parents) {
$allowed = false;
}
}
- if ($p && $p[0]['obj_type'] === 'Question') {
+ if ($parent && $parent[0]['obj_type'] === 'Question') {
if ($item['obj_type'] === ACTIVITY_OBJ_COMMENT && $item['title'] && (!$item['body'])) {
$item['obj_type'] = 'Answer';
}
@@ -2941,7 +2957,7 @@ class Activity {
if (perm_is_allowed($channel['channel_id'], ((!empty($item['item_fetched'])) ? $item['author_xchan'] : $observer_hash), 'send_stream') || $is_sys_channel) {
$allowed = true;
}
- // TODO: not implemented
+
if ($permit_mentions) {
$allowed = true;
}
@@ -3057,34 +3073,25 @@ class Activity {
$item['item_verified'] = 1;
}
- $parent = null;
-
if ($is_child_node) {
-
- $parent = q("select * from item where mid = '%s' and uid = %d limit 1",
- dbesc($item['parent_mid']),
- intval($item['uid'])
- );
-
if (!$parent) {
if (!plugin_is_installed('pubcrawl')) {
return;
}
- else {
- $fetch = false;
- // TODO: debug
- // if (perm_is_allowed($channel['channel_id'],$observer_hash,'send_stream') && (PConfig::Get($channel['channel_id'],'system','hyperdrive',true) || $act->type === 'Announce')) {
- if (perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') || $is_sys_channel) {
- $fetch = (($fetch_parents) ? self::fetch_and_store_parents($channel, $observer_hash, $item, $force) : false);
- }
+ $fetch = false;
- if ($fetch) {
- $parent = q("select * from item where mid = '%s' and uid = %d limit 1",
- dbesc($item['parent_mid']),
- intval($item['uid'])
- );
- }
+ // TODO: debug
+ // if (perm_is_allowed($channel['channel_id'],$observer_hash,'send_stream') && (PConfig::Get($channel['channel_id'],'system','hyperdrive',true) || $act->type === 'Announce')) {
+ if (perm_is_allowed($channel['channel_id'], $observer_hash, 'send_stream') || $is_sys_channel) {
+ $fetch = (($fetch_parents) ? self::fetch_and_store_parents($channel, $observer_hash, $item, $force) : false);
+ }
+
+ if ($fetch) {
+ $parent = q("select * from item where mid = '%s' and uid = %d",
+ dbesc($item['parent_mid']),
+ intval($item['uid'])
+ );
}
}
@@ -3093,6 +3100,7 @@ class Activity {
return;
}
+/*
if ($parent[0]['parent_mid'] !== $item['parent_mid']) {
$item['thr_parent'] = $item['parent_mid'];
}
@@ -3100,6 +3108,7 @@ class Activity {
$item['thr_parent'] = $parent[0]['parent_mid'];
}
$item['parent_mid'] = $parent[0]['parent_mid'];
+*/
/*
*
@@ -3988,18 +3997,18 @@ class Activity {
switch ($options) {
case 'activitypub':
- $hublocs = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_hash = '%s' and hubloc_deleted = 0 ",
+ $hublocs = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_hash = '%s' and hubloc_deleted = 0 order by hubloc_id desc",
dbesc($url)
);
break;
case 'zot6':
- $hublocs = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_id_url = '%s' and hubloc_deleted = 0 ",
+ $hublocs = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where hubloc_id_url = '%s' and hubloc_deleted = 0 order by hubloc_id desc",
dbesc($url)
);
break;
case 'all':
default:
- $hublocs = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where ( hubloc_id_url = '%s' OR hubloc_hash = '%s' ) and hubloc_deleted = 0 ",
+ $hublocs = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash where ( hubloc_id_url = '%s' OR hubloc_hash = '%s' ) and hubloc_deleted = 0 order by hubloc_id desc",
dbesc($url),
dbesc($url)
);
@@ -4059,9 +4068,9 @@ class Activity {
if ($act->is_valid()) {
$content = self::get_content($act->obj);
- $ret .= "[share author='" . urlencode($act->actor['name']) .
+ $ret .= "[share author='" . urlencode($act->actor['name'] ?? $act->actor['preferredUsername']) .
"' profile='" . $act->actor['id'] .
- "' avatar='" . $act->actor['icon']['url'] .
+ "' avatar='" . ($act->actor['icon']['url'] ?? z_root() . '/' . get_default_profile_photo(80)) .
"' link='" . $act->obj['id'] .
"' auth='" . ((is_matrix_url($act->actor['id'])) ? 'true' : 'false') .
"' posted='" . $act->obj['published'] .
diff --git a/Zotlabs/Lib/ActivityStreams.php b/Zotlabs/Lib/ActivityStreams.php
index cfed53b3c..f07f99ac3 100644
--- a/Zotlabs/Lib/ActivityStreams.php
+++ b/Zotlabs/Lib/ActivityStreams.php
@@ -126,6 +126,7 @@ class ActivityStreams {
if ((!$this->parent_id) && is_array($this->obj) && isset($this->obj['inReplyTo'])) {
$this->parent_id = $this->obj['inReplyTo'];
}
+
if ((!$this->parent_id) && is_array($this->obj) && isset($this->obj['id'])) {
$this->parent_id = $this->obj['id'];
}
@@ -154,7 +155,7 @@ class ActivityStreams {
* @return mixed
*/
public function objprop(string $property, mixed $default = false): mixed {
- $x = $this->get_property_obj($property,$this->obj);
+ $x = $this->get_property_obj($property, $this->obj);
return (isset($x)) ? $x : $default;
}
diff --git a/Zotlabs/Lib/Connect.php b/Zotlabs/Lib/Connect.php
index 802bbe0f5..4de41526b 100644
--- a/Zotlabs/Lib/Connect.php
+++ b/Zotlabs/Lib/Connect.php
@@ -69,7 +69,8 @@ class Connect {
$xchan_hash = '';
$sql_options = (($protocol) ? " and xchan_network = '" . dbesc($protocol) . "' " : '');
- $r = q("SELECT * FROM xchan LEFT JOIN hubloc ON xchan_hash = hubloc_hash WHERE ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s') $sql_options ORDER BY hubloc_id DESC",
+ // We need both, the xchan and the hubloc here hence use JOIN instead of LEFT JOIN
+ $r = q("SELECT * FROM xchan JOIN hubloc ON xchan_hash = hubloc_hash WHERE ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s') $sql_options ORDER BY hubloc_id DESC",
dbesc($url),
dbesc($url),
dbesc($url)
diff --git a/Zotlabs/Lib/Libsync.php b/Zotlabs/Lib/Libsync.php
index d52b501e4..0d383c697 100644
--- a/Zotlabs/Lib/Libsync.php
+++ b/Zotlabs/Lib/Libsync.php
@@ -141,7 +141,7 @@ class Libsync {
$total = count($synchubs);
foreach ($synchubs as $hub) {
- $hash = random_string();
+ $hash = new_uuid();
$n = Libzot::build_packet($channel, 'sync', $env_recips, json_encode($info), 'hz', $hub['hubloc_sitekey'], $hub['site_crypto']);
Queue::insert([
'hash' => $hash,
@@ -771,7 +771,12 @@ class Libsync {
static function sync_locations($sender, $arr) {
- $ret = [];
+ $ret = [
+ 'change_message' => '',
+ 'changed' => false,
+ 'message' => ''
+ ];
+
$what = '';
$changed = false;
@@ -786,7 +791,7 @@ class Libsync {
if (isset($arr['locations']) && $arr['locations']) {
- $xisting = q("select * from hubloc where hubloc_hash = '%s'",
+ $xisting = q("select * from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0",
dbesc($sender['hash'])
);
diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php
index a8334595f..093670338 100644
--- a/Zotlabs/Lib/Libzot.php
+++ b/Zotlabs/Lib/Libzot.php
@@ -328,7 +328,7 @@ class Libzot {
logger('zot-info: ' . print_r($record, true), LOGGER_DATA, LOG_DEBUG);
- $x = self::import_xchan($record['data'], (($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
+ $x = self::import_xchan($record['data']);
if (!$x['success']) {
return false;
@@ -635,23 +635,18 @@ class Libzot {
* all internal data structures which need to be updated as a result.
*
* @param array $arr => json_decoded discovery packet
- * @param int $ud_flags
- * Determines whether to create a directory update record if any changes occur, default is UPDATE_FLAGS_UPDATED
- * $ud_flags = UPDATE_FLAGS_FORCED indicates a forced refresh where we unconditionally create a directory update record
- * this typically occurs once a month for each channel as part of a scheduled ping to notify the directory
- * that the channel still exists
- * @param array $ud_arr
- * If set [typically by update_directory_entry()] indicates a specific update table row and more particularly
- * contains a particular address (ud_addr) which needs to be updated in that table.
- *
+
* @return array An associative array with:
* * \e boolean \b success boolean true or false
* * \e string \b message (optional) error string only if success is false
*/
- static function import_xchan($arr, $ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
+ static function import_xchan($arr) {
- $ret = ['success' => false];
+ $ret = [
+ 'success' => false,
+ 'message' => ''
+ ];
if (!is_array($arr)) {
logger('Not an array: ' . print_r($arr, true), LOGGER_DEBUG);
@@ -665,7 +660,7 @@ class Libzot {
*/
call_hooks('import_xchan', $arr);
- $dirmode = intval(get_config('system', 'directory_mode'));
+ $dirmode = intval(get_config('system', 'directory_mode', DIRECTORY_MODE_NORMAL));
$changed = false;
$what = '';
@@ -683,15 +678,11 @@ class Libzot {
$sig_methods = ((array_key_exists('signing', $arr) && is_array($arr['signing'])) ? $arr['signing'] : ['sha256']);
$verified = false;
- if (!self::verify($arr['id'], $arr['id_sig'], $arr['public_key'])) {
- logger('Unable to verify channel signature for ' . $arr['primary_location']['address']);
- return $ret;
- }
- else {
+ if (self::verify($arr['id'], $arr['id_sig'], $arr['public_key'])) {
$verified = true;
}
-
- if (!$verified) {
+ else {
+ logger('Unable to verify channel signature for ' . $xchan_hash . ' (' . $arr['primary_location']['address']) . ')';
$ret['message'] = t('Unable to verify channel signature');
return $ret;
}
@@ -714,6 +705,7 @@ class Libzot {
if ($arr['photo'] && array_key_exists('updated', $arr['photo']) && $arr['photo']['updated'] > $r[0]['xchan_photo_date'])
$import_photos = true;
+
// if we import an entry from a site that's not ours and either or both of us is off the grid - hide the entry.
/** @TODO: check if we're the same directory realm, which would mean we are allowed to see it */
@@ -730,7 +722,7 @@ class Libzot {
$hidden_changed = 1;
if (isset($arr['adult_content']) && intval($r[0]['xchan_selfcensored']) != intval($arr['adult_content']))
$adult_changed = 1;
- if (isset($arr['xchan_deleted']) && intval($r[0]['xchan_deleted']) != intval($arr['deleted']))
+ if (isset($arr['deleted']) && intval($r[0]['xchan_deleted']) != intval($arr['deleted']))
$deleted_changed = 1;
// new style 6-MAR-2019
@@ -920,30 +912,26 @@ class Libzot {
$s = Libsync::sync_locations($arr, $arr);
if ($s) {
- if (isset($s['change_message']))
+ if (!empty($s['change_message']))
$what .= $s['change_message'];
- if (isset($s['changed']))
- $changed = $s['changed'];
- if (isset($s['message']))
+ if (!empty($s['changed']))
+ $changed .= $s['changed'];
+ if (!empty($s['message']))
$ret['message'] .= $s['message'];
}
- // Which entries in the update table are we interested in updating?
-
- $address = (($ud_arr && $ud_arr['ud_addr']) ? $ud_arr['ud_addr'] : $arr['primary_location']['address']);
-
-
- // Are we a directory server of some kind?
$other_realm = false;
$realm = get_directory_realm();
- if (array_key_exists('site', $arr)
- && array_key_exists('realm', $arr['site'])
- && (strpos($arr['site']['realm'], $realm) === false))
+ if (array_key_exists('site', $arr) && array_key_exists('realm', $arr['site']) && (strpos($arr['site']['realm'], $realm) === false)) {
$other_realm = true;
+ }
+ $address = $arr['primary_location']['url'];
- if ($dirmode != DIRECTORY_MODE_NORMAL) {
+ // Are we a directory server of some kind?
+
+ if ($dirmode !== DIRECTORY_MODE_NORMAL) {
// We're some kind of directory server. However we can only add directory information
// if the entry is in the same realm (or is a sub-realm). Sub-realms are denoted by
@@ -951,7 +939,7 @@ class Libzot {
// be in directories for the local realm (foo) and also the RED_GLOBAL realm.
if (array_key_exists('profile', $arr) && is_array($arr['profile']) && (!$other_realm)) {
- $profile_changed = Libzotdir::import_directory_profile($xchan_hash, $arr['profile'], $address, $ud_flags, 1);
+ $profile_changed = Libzotdir::import_directory_profile($xchan_hash, $arr['profile']);
if ($profile_changed) {
$what .= 'profile ';
$changed = true;
@@ -977,21 +965,10 @@ class Libzot {
}
}
- if (($changed) || ($ud_flags == UPDATE_FLAGS_FORCED)) {
- $guid = random_string() . '@' . \App::get_hostname();
- Libzotdir::update_modtime($xchan_hash, $guid, $address, $ud_flags);
- logger('Changed: ' . $what, LOGGER_DEBUG);
- }
- elseif (!$ud_flags) {
- // nothing changed but we still need to update the updates record
- q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and (ud_flags & %d) = 0 ",
- intval(UPDATE_FLAGS_UPDATED),
- dbesc($address),
- intval(UPDATE_FLAGS_UPDATED)
- );
- }
+ // update updates if anything changed bump the ud_date
+ Libzotdir::update($xchan_hash, $address, $changed);
- if (!x($ret, 'message')) {
+ if (empty($ret['message'])) {
$ret['success'] = true;
$ret['hash'] = $xchan_hash;
}
@@ -1398,7 +1375,7 @@ class Libzot {
$uids = ids_to_querystr($uids, 'uid');
$z = q("SELECT channel_hash FROM channel WHERE channel_hash != '%s' AND channel_id IN ($uids)",
- dbesc($msg['sender'])
+ dbesc($env['sender'])
);
if ($z) {
@@ -1746,7 +1723,7 @@ class Libzot {
// this is just an exercise in futility.
if (perm_is_allowed($channel['channel_id'], $sender, 'send_stream')) {
- self::fetch_conversation($channel, $arr['parent_mid']);
+ Master::Summon(['Zotconvo', $channel['channel_id'], $arr['parent_mid']]);
}
continue;
@@ -2037,18 +2014,12 @@ class Libzot {
continue;
}
- $r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s' order by hubloc_id desc",
- dbesc($AS->actor['id'])
- );
-
+ $r = Activity::get_actor_hublocs($AS->actor['id']);
$r = self::zot_record_preferred($r);
-
if (!$r) {
$y = import_author_xchan(['url' => $AS->actor['id']]);
if ($y) {
- $r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s'",
- dbesc($AS->actor['id'])
- );
+ $r = Activity::get_actor_hublocs($AS->actor['id']);
$r = self::zot_record_preferred($r);
}
if (!$r) {
@@ -2058,22 +2029,29 @@ class Libzot {
}
if (isset($AS->obj['actor']['id']) && $AS->obj['actor']['id'] !== $AS->actor['id']) {
- $y = import_author_xchan(['url' => $AS->obj['actor']['id']]);
- if (!$y) {
- logger('FOF Activity: no object actor');
- continue;
+ $ro = Activity::get_actor_hublocs($AS->obj['actor']['id']);
+ $ro = self::zot_record_preferred($ro);
+ if (!$ro) {
+ $y = import_author_xchan(['url' => $AS->obj['actor']['id']]);
+ if ($y) {
+ $ro = Activity::get_actor_hublocs($AS->obj['actor']['id']);
+ $ro = self::zot_record_preferred($ro);
+ }
+ if (!$ro) {
+ logger('FOF Activity: no obj actor');
+ continue;
+ }
}
}
$arr = Activity::decode_note($AS);
if (!$arr) {
+ logger('FOF Activity: could not decode');
continue;
}
- if ($r) {
- $arr['author_xchan'] = $r['hubloc_hash'];
- }
+ $arr['author_xchan'] = $r['hubloc_hash'];
if ($signer) {
$arr['owner_xchan'] = $signer[0]['hubloc_hash'];
@@ -2377,19 +2355,6 @@ class Libzot {
'deleted' => (intval($hub['hubloc_deleted']) ? true : false)
];
- // version compatibility tweaks
-
- if (!strpos($z['url_sig'], '.')) {
- $z['url_sig'] = 'sha256.' . $z['url_sig'];
- }
-
- if (!$z['id_url']) {
- $z['id_url'] = $z['url'] . '/channel/' . substr($z['address'], 0, strpos($z['address'], '@'));
- }
- if (!$z['site_id']) {
- $z['site_id'] = Libzot::make_xchan_hash($z['url'], $z['sitekey']);
- }
-
$ret[] = $z;
}
}
@@ -2761,12 +2726,12 @@ class Libzot {
$e = $r[0];
$id = $e['channel_id'];
- $sys_channel = (intval($e['channel_system']) ? true : false);
+ $sys_channel = ((empty($e['channel_system'])) ? false : true);
$special_channel = (($e['channel_pageflags'] & PAGE_PREMIUM) ? true : false);
$adult_channel = (($e['channel_pageflags'] & PAGE_ADULT) ? true : false);
$censored = (($e['channel_pageflags'] & PAGE_CENSORED) ? true : false);
$searchable = (($e['channel_pageflags'] & PAGE_HIDDEN) ? false : true);
- $deleted = (intval($e['xchan_deleted']) ? true : false);
+ $deleted = ((empty($e['xchan_deleted'])) ? false : true);
if ($deleted || $censored || $sys_channel)
$searchable = false;
@@ -2818,8 +2783,8 @@ class Libzot {
// Communication details
- $ret['id'] = $e['xchan_guid'];
- $ret['id_sig'] = self::sign($e['xchan_guid'], $e['channel_prvkey']);
+ $ret['id'] = $e['channel_guid'];
+ $ret['id_sig'] = self::sign($e['channel_guid'], $e['channel_prvkey']);
$ret['primary_location'] = [
'address' => $e['xchan_addr'],
@@ -2828,10 +2793,10 @@ class Libzot {
'follow_url' => $e['xchan_follow'],
];
- $ret['public_key'] = $e['xchan_pubkey'];
+ $ret['public_key'] = $e['channel_pubkey'];
$ret['signing_algorithm'] = 'rsa-sha256';
$ret['username'] = $e['channel_address'];
- $ret['name'] = $e['xchan_name'];
+ $ret['name'] = $e['channel_name'];
$ret['name_updated'] = $e['xchan_name_date'];
$ret['photo'] = [
'url' => $e['xchan_photo_l'],
diff --git a/Zotlabs/Lib/Libzotdir.php b/Zotlabs/Lib/Libzotdir.php
index dfedd0bc8..58138850c 100644
--- a/Zotlabs/Lib/Libzotdir.php
+++ b/Zotlabs/Lib/Libzotdir.php
@@ -172,13 +172,12 @@ class Libzotdir {
}
/**
- * @brief Checks the directory mode of this hub.
+ * @brief fetches updates from known directories
*
* Checks the directory mode of this hub to see if it is some form of directory server. If it is,
* get the directory realm of this hub. Fetch a list of all other directory servers in this realm and request
- * a directory sync packet. This will contain both directory updates and new ratings. Store these all in the DB.
- * In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored
- * directly if the rater's signature matches.
+ * a directory sync packet. Store these all in the DB.
+ * In the case of updates, we will query each of them asynchronously from a poller task.
*
* @param int $dirmode;
*/
@@ -233,6 +232,8 @@ class Libzotdir {
if (! $r)
return;
+ $dir_trusted_hosts = array_merge(get_directory_fallback_servers(), get_config('system', 'trusted_directory_servers', []));
+
foreach ($r as $rr) {
if (! $rr['site_directory'])
continue;
@@ -264,31 +265,65 @@ class Libzotdir {
if (is_array($j['transactions']) && count($j['transactions'])) {
foreach ($j['transactions'] as $t) {
-
- if (empty($t['hash']) || empty($t['transaction_id']) || empty($t['address'])) {
+ if (empty($t['hash']) || empty($t['host']) || empty($t['address'])) {
continue;
}
- $r = q("select * from updates where ud_guid = '%s' limit 1",
- dbesc($t['transaction_id'])
+ $r = q("select * from updates where ud_hash = '%s' limit 1",
+ dbesc($t['hash'])
);
- if($r)
- continue;
- $ud_flags = 0;
- if (is_array($t['flags']) && in_array('deleted',$t['flags']))
- $ud_flags |= UPDATE_FLAGS_DELETED;
- if (is_array($t['flags']) && in_array('forced',$t['flags']))
- $ud_flags |= UPDATE_FLAGS_FORCED;
-
- $z = q("insert into updates ( ud_hash, ud_guid, ud_date, ud_flags, ud_addr )
- values ( '%s', '%s', '%s', %d, '%s' ) ",
- dbesc($t['hash']),
- dbesc($t['transaction_id']),
- dbesc($t['timestamp']),
- intval($ud_flags),
- dbesc($t['address'])
- );
+ if ($r) {
+ $update = 0;
+
+ // no need to look at updates that originated from our own site
+ if ($t['host'] === z_root()) {
+ continue;
+ }
+
+ // there is more recent xchan information
+ if ($r[0]['ud_date'] <= $t['timestamp']) {
+ $update = 1;
+ }
+
+ // the host is trusted and flags have changed - update flags immediately
+ if (in_array($t['host'], $dir_trusted_hosts) &&
+ $rr['site_url'] === $t['host'] &&
+ intval($r[0]['ud_flags']) !== intval($t['flags'])) {
+
+ q("UPDATE updates SET ud_update = %d, ud_flags = %d WHERE ud_id = %d",
+ intval($update),
+ intval($t['flags']),
+ dbesc($r[0]['ud_id'])
+ );
+
+ q("UPDATE xchan SET xchan_censored = %d WHERE xchan_hash = '%s'",
+ intval($t['flags']),
+ dbesc($r[0]['ud_hash'])
+ );
+
+ continue;
+ }
+
+ if (!$update) {
+ continue;
+ }
+
+ q("UPDATE updates SET ud_update = %d WHERE ud_id = %d",
+ intval($update),
+ dbesc($r[0]['ud_id'])
+ );
+ }
+ else {
+ q("insert into updates ( ud_hash, ud_host, ud_date, ud_addr, ud_update, ud_flags )
+ values ( '%s', '%s', '%s', '%s', 1, %d) ",
+ dbesc($t['hash']),
+ dbesc($t['host']),
+ dbesc($t['timestamp']),
+ dbesc($t['address']),
+ dbesc(in_array($t['host'], $dir_trusted_hosts) ? $t['flags'] : 0)
+ );
+ }
}
}
}
@@ -303,8 +338,9 @@ class Libzotdir {
*
* Ignore updating records marked as deleted.
*
- * If successful, sets ud_last in the DB to the current datetime for this
+ * If successful, sets ud_updated in the DB to the current datetime for this
* reddress/webbie.
+ * Else update ud_last so we can stop trying after 7 days (Daemon/Poller.php)
*
* @param array $ud Entry from update table
*/
@@ -313,31 +349,47 @@ class Libzotdir {
logger('update_directory_entry: ' . print_r($ud,true), LOGGER_DATA);
- if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
- $success = false;
- $zf = [];
+ // TODO: remove this check after all directory servers have version > 8.4
+ // ud_addr will always be the channel url at that time
+ $href = ((strpos($ud['ud_addr'], '://') === false) ? Webfinger::zot_url(punify($ud['ud_addr'])) : punify($ud['ud_addr']));
+ if($href) {
+ $zf = Zotfinger::exec($href);
+ if($zf && array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
+ $xc = Libzot::import_xchan($zf['data']);
+
+ // xchan_hash mismatch - this can happen after a site re-install at the same url
+ if ($xc['success'] && $xc['hash'] !== $ud['ud_hash']) {
+ self::delete_by_hash($ud['ud_hash']);
+ }
+
+ // backwards compatibility: Libzot::import_xchan(), where self::update() is called,
+ // will fail with versions < 8.4 if the channel has been locally deleted.
+ // In this case we will update the updates record here without bumping the date
+ // since we could not verify if anything changed.
+ if (!$xc['success'] && !empty($zf['data']['deleted_locally'])) {
+ self::update($ud['ud_hash'], $ud['ud_addr'], false);
+ }
- $href = Webfinger::zot_url(punify($ud['ud_addr']));
- if($href) {
- $zf = Zotfinger::exec($href);
- }
- if(array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
- $xc = Libzot::import_xchan($zf['data'], 0, $ud);
// This is a workaround for a missing xchan_updated column
// TODO: implement xchan_updated in the xchan table and update this column instead
- if($zf['data']['primary_location']['address'] && $zf['data']['primary_location']['url']) {
+ if(!empty($zf['data']['primary_location']['url'])) {
q("UPDATE hubloc SET hubloc_updated = '%s' WHERE hubloc_id_url = '%s' AND hubloc_primary = 1",
dbesc(datetime_convert()),
dbesc($zf['data']['primary_location']['url'])
);
}
- q("update updates set ud_last = '%s' where ud_addr = '%s'",
- dbesc(datetime_convert()),
- dbesc($ud['ud_addr'])
- );
+ return true;
}
}
+
+ q("UPDATE updates SET ud_addr = '%s', ud_last = '%s' WHERE ud_hash = '%s'",
+ dbesc($href ? $href : $ud['ud_addr']),
+ dbesc(datetime_convert()),
+ dbesc($ud['ud_hash'])
+ );
+
+ return false;
}
@@ -352,85 +404,78 @@ class Libzotdir {
*/
static function local_dir_update($uid, $force) {
+ logger('local_dir_update uid: ' . $uid, LOGGER_DEBUG);
-
- logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG);
-
- $p = q("select channel.channel_hash, channel_address, channel_timezone, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1",
+ $p = q("select channel.channel_hash, channel_address, channel_timezone, profile.*, xchan.xchan_hidden, xchan.xchan_url from profile left join channel on channel_id = uid left join xchan on channel_hash = xchan_hash where profile.uid = %d and profile.is_default = 1",
intval($uid)
);
- $profile = array();
+ if (!$p) {
+ logger('profile not found');
+ return;
+ }
+
+ $profile = [];
$profile['encoding'] = 'zot';
- if ($p) {
- $hash = $p[0]['channel_hash'];
-
- $profile['description'] = $p[0]['pdesc'];
- $profile['birthday'] = $p[0]['dob'];
- if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
- $profile['age'] = $age;
-
- $profile['gender'] = $p[0]['gender'];
- $profile['marital'] = $p[0]['marital'];
- $profile['sexual'] = $p[0]['sexual'];
- $profile['locale'] = $p[0]['locality'];
- $profile['region'] = $p[0]['region'];
- $profile['postcode'] = $p[0]['postal_code'];
- $profile['country'] = $p[0]['country_name'];
- $profile['about'] = $p[0]['about'];
- $profile['homepage'] = $p[0]['homepage'];
- $profile['hometown'] = $p[0]['hometown'];
-
- if ($p[0]['keywords']) {
- $tags = array();
- $k = explode(' ', $p[0]['keywords']);
- if ($k)
- foreach ($k as $kk)
- if (trim($kk))
- $tags[] = trim($kk);
-
- if ($tags)
- $profile['keywords'] = $tags;
- }
+ $hash = $p[0]['channel_hash'];
+
+ $profile['description'] = $p[0]['pdesc'];
+ $profile['birthday'] = $p[0]['dob'];
+ if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
+ $profile['age'] = $age;
+
+ $profile['gender'] = $p[0]['gender'];
+ $profile['marital'] = $p[0]['marital'];
+ $profile['sexual'] = $p[0]['sexual'];
+ $profile['locale'] = $p[0]['locality'];
+ $profile['region'] = $p[0]['region'];
+ $profile['postcode'] = $p[0]['postal_code'];
+ $profile['country'] = $p[0]['country_name'];
+ $profile['about'] = $p[0]['about'];
+ $profile['homepage'] = $p[0]['homepage'];
+ $profile['hometown'] = $p[0]['hometown'];
+
+ if ($p[0]['keywords']) {
+ $tags = array();
+ $k = explode(' ', $p[0]['keywords']);
+ if ($k)
+ foreach ($k as $kk)
+ if (trim($kk))
+ $tags[] = trim($kk);
+
+ if ($tags)
+ $profile['keywords'] = $tags;
+ }
- $hidden = (1 - intval($p[0]['publish']));
+ $hidden = (1 - intval($p[0]['publish']));
- logger('hidden: ' . $hidden);
+ logger('hidden: ' . $hidden);
- $r = q("select xchan_hidden from xchan where xchan_hash = '%s'",
- dbesc($p[0]['channel_hash'])
+ if(intval($p[0]['xchan_hidden']) !== $hidden) {
+ q("update xchan set xchan_hidden = %d where xchan_hash = '%s'",
+ intval($hidden),
+ dbesc($hash)
);
+ }
- if(intval($r[0]['xchan_hidden']) != $hidden) {
- $r = q("update xchan set xchan_hidden = %d where xchan_hash = '%s'",
- intval($hidden),
- dbesc($hash)
- );
- }
-
- $arr = [ 'channel_id' => $uid, 'hash' => $hash, 'profile' => $profile ];
- call_hooks('local_dir_update', $arr);
-
- $address = channel_reddress($p[0]);
-
- if (perm_is_allowed($uid, '', 'view_profile')) {
- self::import_directory_profile($hash, $arr['profile'], $address, 0);
- }
- else {
- // they may have made it private
- q("delete from xprof where xprof_hash = '%s'",
- dbesc($hash)
- );
- q("delete from xtag where xtag_hash = '%s'",
- dbesc($hash)
- );
- }
+ $arr = [ 'channel_id' => $uid, 'hash' => $hash, 'profile' => $profile ];
+ call_hooks('local_dir_update', $arr);
+ if (perm_is_allowed($uid, '', 'view_profile')) {
+ self::import_directory_profile($hash, $arr['profile']);
+ }
+ else {
+ // they may have made it private
+ q("delete from xprof where xprof_hash = '%s'",
+ dbesc($hash)
+ );
+ q("delete from xtag where xtag_hash = '%s'",
+ dbesc($hash)
+ );
}
- $ud_hash = random_string() . '@' . \App::get_hostname();
- self::update_modtime($hash, $ud_hash, channel_reddress($p[0]),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
+ self::update($hash, $p[0]['xchan_url']);
}
@@ -440,13 +485,10 @@ class Libzotdir {
*
* @param string $hash
* @param array $profile
- * @param string $addr
- * @param number $ud_flags (optional) UPDATE_FLAGS_UPDATED
- * @param number $suppress_update (optional) default 0
* @return boolean $updated if something changed
*/
- static function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLAGS_UPDATED, $suppress_update = 0) {
+ static function import_directory_profile($hash, $profile) {
logger('import_directory_profile', LOGGER_DEBUG);
if (! $hash)
@@ -479,7 +521,12 @@ class Libzotdir {
$clean = array();
if (array_key_exists('keywords', $profile) and is_array($profile['keywords'])) {
self::import_directory_keywords($hash,$profile['keywords']);
+
foreach ($profile['keywords'] as $kw) {
+ if (in_array($kw, $clean)) {
+ continue;
+ }
+
$kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false));
$kw = trim($kw, ',');
$clean[] = $kw;
@@ -586,9 +633,6 @@ class Libzotdir {
*/
call_hooks('import_directory_profile', $d);
- if (($d['update']) && (! $suppress_update))
- self::update_modtime($arr['xprof_hash'],random_string() . '@' . \App::get_hostname(), $addr, $ud_flags);
-
return $d['update'];
}
@@ -606,6 +650,10 @@ class Libzotdir {
dbesc($hash)
);
+ $xchan = q("select xchan_censored from xchan where xchan_hash = '%s'",
+ dbesc($hash)
+ );
+
if($r) {
foreach($r as $rr)
$existing[] = $rr['xtag_term'];
@@ -613,6 +661,10 @@ class Libzotdir {
$clean = array();
foreach($keywords as $kw) {
+ if (in_array($kw, $clean)) {
+ continue;
+ }
+
$kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false));
$kw = trim($kw, ',');
$clean[] = $kw;
@@ -627,9 +679,10 @@ class Libzotdir {
}
foreach($clean as $x) {
if(! in_array($x, $existing)) {
- $r = q("insert into xtag ( xtag_hash, xtag_term, xtag_flags) values ( '%s' ,'%s', 0 )",
+ $r = q("insert into xtag ( xtag_hash, xtag_term, xtag_flags) values ( '%s' ,'%s', %d )",
dbesc($hash),
- dbesc($x)
+ dbesc($x),
+ intval($xchan[0]['xchan_censored'])
);
}
}
@@ -639,13 +692,12 @@ class Libzotdir {
/**
* @brief
*
- * @param string $hash
- * @param string $guid
- * @param string $addr
- * @param int $flags (optional) default 0
+ * @param string $hash the channel hash
+ * @param string $addr the channel url
+ * @param bool $bump_date (optional) default true
*/
- static function update_modtime($hash, $guid, $addr, $flags = 0) {
+ static function update($hash, $addr, $bump_date = true, $flag = null) {
$dirmode = intval(get_config('system', 'directory_mode'));
@@ -653,26 +705,70 @@ class Libzotdir {
return;
}
- if (empty($hash) || empty($guid) || empty($addr)) {
+ if (empty($hash) || empty($addr)) {
return;
}
- if($flags) {
- q("insert into updates (ud_hash, ud_guid, ud_date, ud_flags, ud_addr ) values ( '%s', '%s', '%s', %d, '%s' )",
- dbesc($hash),
- dbesc($guid),
- dbesc(datetime_convert()),
- intval($flags),
- dbesc($addr)
- );
+ $u = q("SELECT * FROM updates WHERE ud_hash = '%s' LIMIT 1",
+ dbesc($hash)
+ );
+
+ $date_sql = '';
+ if ($bump_date) {
+ $date_sql = "ud_date = '" . dbesc(datetime_convert()) . "',";
}
- else {
- q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and not (ud_flags & %d)>0 ",
- intval(UPDATE_FLAGS_UPDATED),
+
+ $flag_sql = '';
+ if ($flag !== null) {
+ $flag_sql = "ud_flags = '" . intval($flag) . "',";
+ }
+
+
+ if ($u) {
+ $x = q("UPDATE updates SET $date_sql $flag_sql ud_last = '%s', ud_host = '%s', ud_addr = '%s', ud_update = 0 WHERE ud_id = %d",
+ dbesc(NULL_DATE),
+ dbesc(z_root()),
dbesc($addr),
- intval(UPDATE_FLAGS_UPDATED)
+ intval($u[0]['ud_id'])
);
+
+ return;
+ }
+
+ q("INSERT INTO updates (ud_hash, ud_host, ud_date, ud_addr, ud_flags) VALUES ( '%s', '%s', '%s', '%s', %d )",
+ dbesc($hash),
+ dbesc(z_root()),
+ dbesc(datetime_convert()),
+ dbesc($addr),
+ intval($flag)
+ );
+
+ return;
+
+ }
+
+
+ /**
+ * @brief deletes a entry in updates by hash
+ *
+ * @param string $hash the channel hash
+ * @return boolean
+ */
+
+ static function delete_by_hash($hash) {
+ if (!$hash) {
+ return false;
+ }
+
+ $x = q("DELETE FROM updates WHERE ud_hash = '%s'",
+ dbesc($hash)
+ );
+
+ if ($x) {
+ return true;
}
+
+ return false;
}
}
diff --git a/Zotlabs/Lib/Queue.php b/Zotlabs/Lib/Queue.php
index 348a2a079..942a633ef 100644
--- a/Zotlabs/Lib/Queue.php
+++ b/Zotlabs/Lib/Queue.php
@@ -57,7 +57,6 @@ class Queue {
outq_priority = outq_priority + %d,
outq_scheduled = '%s'
WHERE outq_hash = '%s'",
-
dbesc(datetime_convert()),
intval($add_priority),
dbesc($next),
@@ -85,29 +84,16 @@ class Queue {
// entries still exist for it. This fixes an issue where one immediate delivery left everything
// else for that site undeliverable since all the other entries had been pushed far into the future.
- $x = null;
- $sql_quirks = ((get_config('system', 'db_skip_locked_supported')) ? 'SKIP LOCKED' : 'NOWAIT');
-
- q("START TRANSACTION");
-
- $r = q("SELECT outq_hash FROM outq WHERE outq_posturl = '%s' LIMIT 1 FOR UPDATE $sql_quirks",
+ $r = q("SELECT outq_hash, outq_posturl FROM outq WHERE outq_posturl = '%s' LIMIT 1",
dbesc($record[0]['outq_posturl'])
);
if ($r) {
- $x = q("UPDATE outq SET outq_scheduled = '%s' WHERE outq_hash = '%s'",
- dbesc(datetime_convert()),
- dbesc($r[0]['outq_hash'])
+ $hashes = ids_to_querystr($r, 'outq_hash', true);
+ $x = q("UPDATE outq SET outq_scheduled = '%s' WHERE outq_hash IN ($hashes)",
+ dbesc(datetime_convert())
);
}
-
- if ($x) {
- q("COMMIT");
- }
- else {
- q("ROLLBACK");
- }
-
}
}
@@ -260,7 +246,7 @@ class Queue {
if($result['success']) {
logger('deliver: remote zot delivery succeeded to ' . $outq['outq_posturl']);
- Libzot::process_response($outq['outq_posturl'],$result, $outq);
+ Libzot::process_response($outq['outq_posturl'], $result, $outq);
}
else {
logger('deliver: remote zot delivery failed to ' . $outq['outq_posturl']);
diff --git a/Zotlabs/Lib/QueueWorker.php b/Zotlabs/Lib/QueueWorker.php
index a1c13ef8a..1c74b42d8 100644
--- a/Zotlabs/Lib/QueueWorker.php
+++ b/Zotlabs/Lib/QueueWorker.php
@@ -24,7 +24,8 @@ class QueueWorker {
// Exceptions for processtimeout ($workermaxage) value.
// Currently the value is overriden with 3600 seconds (1h).
public static $long_running_cmd = [
- 'Queue'
+ 'Queue',
+ 'Expire'
];
private static function qstart() {
@@ -147,6 +148,10 @@ class QueueWorker {
);
if ($r) {
+ // TODO: some long running services store their pid in config.procid.daemon
+ // we could possibly check if a pid exist and check if the process is still alive
+ // prior to reseting workerq_reservationid
+
$ids = ids_to_querystr($r, 'workerq_id');
$u = dbq("update workerq set workerq_reservationid = null where workerq_id in ($ids)");
}
diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php
index d1b386c42..cf877ed92 100644
--- a/Zotlabs/Lib/ThreadItem.php
+++ b/Zotlabs/Lib/ThreadItem.php
@@ -197,7 +197,7 @@ class ThreadItem {
$response_verbs = array('like');
if(feature_enabled($conv->get_profile_owner(),'dislike'))
$response_verbs[] = 'dislike';
- if($item['obj_type'] === ACTIVITY_OBJ_EVENT) {
+ if(in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
$response_verbs[] = 'attendyes';
$response_verbs[] = 'attendno';
$response_verbs[] = 'attendmaybe';
@@ -299,7 +299,7 @@ class ThreadItem {
}
$has_event = false;
- if(($item['obj_type'] === ACTIVITY_OBJ_EVENT) && $conv->get_profile_owner() == local_channel())
+ if((in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) && $conv->get_profile_owner() == local_channel())
$has_event = true;
$like = [];
diff --git a/Zotlabs/Module/Admin/Security.php b/Zotlabs/Module/Admin/Security.php
index 16045f9ed..499572170 100644
--- a/Zotlabs/Module/Admin/Security.php
+++ b/Zotlabs/Module/Admin/Security.php
@@ -7,12 +7,12 @@ class Security {
function post() {
check_form_security_token_redirectOnErr('/admin/security', 'admin_security');
-
+
$allowed_email = ((x($_POST,'allowed_email')) ? notags(trim($_POST['allowed_email'])) : '');
$not_allowed_email = ((x($_POST,'not_allowed_email')) ? notags(trim($_POST['not_allowed_email'])) : '');
set_config('system','allowed_email', $allowed_email);
- set_config('system','not_allowed_email', $not_allowed_email);
+ set_config('system','not_allowed_email', $not_allowed_email);
$block_public = ((x($_POST,'block_public')) ? True : False);
set_config('system','block_public',$block_public);
@@ -25,22 +25,22 @@ class Security {
$ws = $this->trim_array_elems(explode("\n",$_POST['whitelisted_sites']));
set_config('system','whitelisted_sites',$ws);
-
+
$bs = $this->trim_array_elems(explode("\n",$_POST['blacklisted_sites']));
set_config('system','blacklisted_sites',$bs);
-
+
$wc = $this->trim_array_elems(explode("\n",$_POST['whitelisted_channels']));
set_config('system','whitelisted_channels',$wc);
-
+
$bc = $this->trim_array_elems(explode("\n",$_POST['blacklisted_channels']));
set_config('system','blacklisted_channels',$bc);
-
+
$embed_sslonly = ((x($_POST,'embed_sslonly')) ? True : False);
set_config('system','embed_sslonly',$embed_sslonly);
-
+
$we = $this->trim_array_elems(explode("\n",$_POST['embed_allow']));
set_config('system','embed_allow',$we);
-
+
$be = $this->trim_array_elems(explode("\n",$_POST['embed_deny']));
set_config('system','embed_deny',$be);
@@ -49,47 +49,54 @@ class Security {
$inline_pdf = ((x($_POST,'inline_pdf')) ? intval($_POST['inline_pdf']) : 0);
set_config('system', 'inline_pdf' , $inline_pdf);
-
+
$ts = ((x($_POST,'transport_security')) ? True : False);
set_config('system','transport_security_header',$ts);
$cs = ((x($_POST,'content_security')) ? True : False);
set_config('system','content_security_policy',$cs);
+ $trusted_directory_servers = $this->trim_array_elems(explode("\n", $_POST['trusted_directory_servers']));
+ set_config('system', 'trusted_directory_servers', $trusted_directory_servers);
+
goaway(z_root() . '/admin/security');
}
-
-
+
+
function get() {
-
+
$whitesites = get_config('system','whitelisted_sites');
$whitesites_str = ((is_array($whitesites)) ? implode("\n",$whitesites) : '');
-
+
$blacksites = get_config('system','blacklisted_sites');
$blacksites_str = ((is_array($blacksites)) ? implode("\n",$blacksites) : '');
-
-
+
+
$whitechannels = get_config('system','whitelisted_channels');
$whitechannels_str = ((is_array($whitechannels)) ? implode("\n",$whitechannels) : '');
-
+
$blackchannels = get_config('system','blacklisted_channels');
$blackchannels_str = ((is_array($blackchannels)) ? implode("\n",$blackchannels) : '');
-
-
+
+
$whiteembeds = get_config('system','embed_allow');
$whiteembeds_str = ((is_array($whiteembeds)) ? implode("\n",$whiteembeds) : '');
-
+
$blackembeds = get_config('system','embed_deny');
$blackembeds_str = ((is_array($blackembeds)) ? implode("\n",$blackembeds) : '');
-
+
+ $trusted_directory_servers = get_config('system', 'trusted_directory_servers');
+ $trusted_directory_servers_str = ((is_array($trusted_directory_servers)) ? implode("\n", $trusted_directory_servers) : '');
+ $is_dir = (intval(get_config('system', 'directory_mode', DIRECTORY_MODE_NORMAL)) !== DIRECTORY_MODE_NORMAL);
+
$embed_coop = intval(get_config('system','embed_coop'));
-
+
if((! $whiteembeds) && (! $blackembeds)) {
$embedhelp1 = t("By default, unfiltered HTML is allowed in embedded media. This is inherently insecure.");
}
- $embedhelp2 = t("The recommended setting is to only allow unfiltered HTML from the following sites:");
+ $embedhelp2 = t("The recommended setting is to only allow unfiltered HTML from the following sites:");
$embedhelp3 = t("https://youtube.com/<br />https://www.youtube.com/<br />https://youtu.be/<br />https://vimeo.com/<br />https://soundcloud.com/<br />");
$embedhelp4 = t("All other embedded content will be filtered, <strong>unless</strong> embedded content from that site is explicitly blocked.");
@@ -99,7 +106,7 @@ class Security {
'$page' => t('Security'),
'$form_security_token' => get_form_security_token('admin_security'),
'$block_public' => array('block_public', t("Block public"), get_config('system','block_public'), t("Check to block public access to all otherwise public personal pages on this site unless you are currently authenticated.")),
- '$cloud_noroot' => [ 'cloud_noroot', t('Provide a cloud root directory'), 1 - intval(get_config('system','cloud_disable_siteroot')), t('The cloud root directory lists all channel names which provide public files') ],
+ '$cloud_noroot' => [ 'cloud_noroot', t('Provide a cloud root directory'), 1 - intval(get_config('system','cloud_disable_siteroot')), t('The cloud root directory lists all channel names which provide public files') ],
'$cloud_disksize' => [ 'cloud_disksize', t('Show total disk space available to cloud uploads'), intval(get_config('system','cloud_report_disksize')), '' ],
'$transport_security' => array('transport_security', t('Set "Transport Security" HTTP header'),intval(get_config('system','transport_security_header')),''),
'$content_security' => array('content_security', t('Set "Content Security Policy" HTTP header'),intval(get_config('system','content_security_policy')),''),
@@ -115,6 +122,8 @@ class Security {
'$thumbnail_security' => [ 'thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system','thumbnail_security',0), t("WARNING: SVG images may contain malicious code.") ],
'$inline_pdf' => [ 'inline_pdf', t("Allow embedded (inline) PDF files"), get_config('system','inline_pdf',0), '' ],
+ '$trusted_directory_servers' => (($is_dir) ? ['trusted_directory_servers', t('Additional trusted directory server URLs'), $trusted_directory_servers_str, t('Accept directory flags (spam, nsfw) from those servers. One per line like https://example.tld')] : ''),
+
// '$embed_coop' => array('embed_coop', t('Cooperative embed security'), $embed_coop, t('Enable to share embed security with other compatible sites/hubs')),
'$submit' => t('Submit')
@@ -124,7 +133,7 @@ class Security {
function trim_array_elems($arr) {
$narr = array();
-
+
if($arr && is_array($arr)) {
for($x = 0; $x < count($arr); $x ++) {
$y = trim($arr[$x]);
@@ -134,6 +143,6 @@ class Security {
}
return $narr;
}
-
-
+
+
}
diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php
index 42cf064c9..b24821b28 100644
--- a/Zotlabs/Module/Admin/Site.php
+++ b/Zotlabs/Module/Admin/Site.php
@@ -67,7 +67,6 @@ class Site {
$open_pubstream = ((x($_POST,'open_pubstream')) ? True : False);
$login_on_homepage = ((x($_POST,'login_on_homepage')) ? True : False);
$enable_context_help = ((x($_POST,'enable_context_help')) ? True : False);
- $global_directory = ((x($_POST,'directory_submit_url')) ? notags(trim($_POST['directory_submit_url'])) : '');
$no_community_page = !((x($_POST,'no_community_page')) ? True : False);
$default_expire_days = ((array_key_exists('default_expire_days',$_POST)) ? intval($_POST['default_expire_days']) : 0);
$active_expire_days = ((array_key_exists('active_expire_days',$_POST)) ? intval($_POST['active_expire_days']) : 7);
@@ -181,7 +180,7 @@ class Site {
set_config('system', 'admininfo', $admininfo);
}
set_config('system','siteinfo',$siteinfo);
- set_config('system', 'language', $language);
+ //set_config('system', 'language', $language);
set_config('system', 'theme', $theme);
// if ( $theme_mobile === '---' ) {
// del_config('system', 'mobile_theme');
@@ -206,11 +205,6 @@ class Site {
set_config('system','site_firehose', $site_firehose);
set_config('system','open_pubstream', $open_pubstream);
//set_config('system','force_queue_threshold', $force_queue);
- if ($global_directory == '') {
- del_config('system', 'directory_submit_url');
- } else {
- set_config('system', 'directory_submit_url', $global_directory);
- }
set_config('system','no_community_page', $no_community_page);
set_config('system','no_utf', $no_utf);
@@ -283,7 +277,7 @@ class Site {
}
$dir_choices = null;
- $dirmode = get_config('system','directory_mode');
+ $dirmode = get_config('system', 'directory_mode', DIRECTORY_MODE_NORMAL);
$realm = get_directory_realm();
// directory server should not be set or settable unless we are a directory client
@@ -301,6 +295,12 @@ class Site {
$dir_choices[$xx['site_url']] = $xx['site_url'];
}
}
+ if ($realm === DIRECTORY_REALM) {
+ $fallback_servers = get_directory_fallback_servers();
+ foreach ($fallback_servers as $fallback_server) {
+ $dir_choices[$fallback_server] = $fallback_server;
+ }
+ }
}
/* Banner */
@@ -425,7 +425,7 @@ class Site {
'$banner' => array('banner', t("Banner/Logo"), $banner, t('Unfiltered HTML/CSS/JS is allowed')),
'$admininfo' => array('admininfo', t("Administrator Information"), $admininfo, t("Contact information for site administrators. Displayed on siteinfo page. BBCode can be used here")),
'$siteinfo' => array('siteinfo', t('Site Information'), get_config('system','siteinfo'), t("Publicly visible description of this site. Displayed on siteinfo page. BBCode can be used here")),
- '$language' => array('language', t("System language"), get_config('system','language'), "", $lang_choices),
+ //'$language' => array('language', t("System language"), get_config('system','language'), "", $lang_choices),
'$theme' => array('theme', t("System theme"), get_config('system','theme'), t("Default system theme - may be over-ridden by user profiles - <a href='#' id='cnftheme'>change theme settings</a>"), $theme_choices),
// '$theme_mobile' => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile),
// '$site_channel' => array('site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel")),
diff --git a/Zotlabs/Module/Conversation.php b/Zotlabs/Module/Conversation.php
new file mode 100644
index 000000000..86ce66caa
--- /dev/null
+++ b/Zotlabs/Module/Conversation.php
@@ -0,0 +1,188 @@
+<?php
+
+namespace Zotlabs\Module;
+
+use Zotlabs\Web\Controller;
+use Zotlabs\Lib\ActivityStreams;
+use Zotlabs\Lib\Activity;
+use Zotlabs\Lib\Libzot;
+use Zotlabs\Web\HTTPSig;
+use Zotlabs\Lib\LDSignatures;
+use Zotlabs\Lib\ThreadListener;
+use Zotlabs\Lib\Config;
+use App;
+
+class Conversation extends Controller {
+
+ public function init() {
+
+ if (ActivityStreams::is_as_request()) {
+ $item_id = argv(1);
+
+ if (!$item_id) {
+ http_status_exit(404, 'Not found');
+ }
+
+ $portable_id = EMPTY_STR;
+
+ $item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
+ dbesc(ACTIVITY_FOLLOW),
+ dbesc(ACTIVITY_UNFOLLOW)
+ );
+
+ $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
+
+ $i = null;
+
+ // do we have the item (at all)?
+
+ $r = q("select parent_mid from item where mid = '%s' or uuid = '%s' $item_normal order by item_wall desc limit 1",
+ dbesc(z_root() . '/item/' . $item_id),
+ dbesc($item_id)
+ );
+
+ if (!$r) {
+ http_status_exit(404, 'Not found');
+ }
+
+ // process an authenticated fetch
+
+ $sigdata = HTTPSig::verify(EMPTY_STR);
+ if ($sigdata['portable_id'] && $sigdata['header_valid']) {
+ $portable_id = $sigdata['portable_id'];
+ observer_auth($portable_id);
+
+ // first see if we have a copy of this item's parent owned by the current signer
+ // include xchans for all zot-like networks - these will have the same guid and public key
+
+ $x = q(
+ "select * from xchan where xchan_hash = '%s'",
+ dbesc($sigdata['portable_id'])
+ );
+
+ if ($x) {
+ $xchans = q(
+ "select xchan_hash from xchan where xchan_hash = '%s' OR ( xchan_guid = '%s' AND xchan_pubkey = '%s' ) ",
+ dbesc($sigdata['portable_id']),
+ dbesc($x[0]['xchan_guid']),
+ dbesc($x[0]['xchan_pubkey'])
+ );
+
+ if ($xchans) {
+ $hashes = ids_to_querystr($xchans, 'xchan_hash', true);
+ $i = q(
+ "select id as item_id from item where mid = '%s' $item_normal and owner_xchan in ( " . protect_sprintf($hashes) . " ) limit 1",
+ dbesc($r[0]['parent_mid'])
+ );
+ }
+ }
+ }
+ elseif (Config::get('system', 'require_authenticated_fetch', false)) {
+ http_status_exit(403, 'Permission denied');
+ }
+
+ // if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access
+ // with a bias towards those items owned by channels on this site (item_wall = 1)
+
+ $sql_extra = item_permissions_sql(0);
+
+ if (!$i) {
+ $i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
+ dbesc($r[0]['parent_mid'])
+ );
+ }
+
+ if (!$i) {
+ http_status_exit(403, 'Forbidden');
+ }
+
+ $parents_str = ids_to_querystr($i, 'item_id');
+ $itemspage = 30;
+ $page = $_REQUEST['page'] ?? 1;
+ $offset = (intval($page) - 1) * $itemspage;
+
+ $items = dbq("SELECT item.*,
+ item.id AS item_id,
+ (SELECT count(*) FROM item WHERE item.parent IN ( $parents_str ) $item_normal) AS total
+ FROM item WHERE item.parent IN ( $parents_str ) $item_normal order by item.id LIMIT $itemspage OFFSET $offset"
+ );
+
+ if (!$items) {
+ http_status_exit(404, 'Not found');
+ }
+
+ xchan_query($items, true);
+ $items = fetch_post_tags($items);
+
+ $observer = App::get_observer();
+ $parent = $items[0];
+ $recips = (($parent['owner']['xchan_network'] === 'activitypub') ? get_iconfig($parent['id'], 'activitypub', 'recips', []) : []);
+ $to = (($recips && array_key_exists('to', $recips) && is_array($recips['to'])) ? $recips['to'] : null);
+ $nitems = [];
+ foreach ($items as $i) {
+ $mids = [];
+
+ if (intval($i['item_private'])) {
+ if (!$observer) {
+ continue;
+ }
+ /*
+ // ignore private reshare, possibly from hubzilla
+ if ($i['verb'] === 'Announce') {
+ if (!in_array($i['thr_parent'], $mids)) {
+ $mids[] = $i['thr_parent'];
+ }
+ continue;
+ }
+ // also ignore any children of the private reshares
+ if (in_array($i['thr_parent'], $mids)) {
+ continue;
+ }
+ */
+
+ if ((!$to) || (!in_array($observer['xchan_url'], $to))) {
+ continue;
+ }
+ }
+ $nitems[] = $i;
+ }
+
+ if (!$nitems) {
+ http_status_exit(404, 'Not found');
+ }
+
+ App::set_pager_total($nitems[0]['total']);
+ App::set_pager_itemspage($itemspage);
+
+ $channel = channelx_by_n($nitems[0]['uid']);
+
+ if (!$channel) {
+ http_status_exit(404, 'Not found');
+ }
+
+ if (!perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_stream')) {
+ http_status_exit(403, 'Forbidden');
+ }
+
+ $i = Activity::encode_item_collection($nitems, App::$query_string, 'OrderedCollection', $nitems[0]['total']);
+
+ if (!$i) {
+ http_status_exit(404, 'Not found');
+ }
+
+ if ($portable_id && (!intval($nitems[0]['item_private']))) {
+ $c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
+ intval($nitems[0]['uid']),
+ dbesc($portable_id)
+ );
+ if (!$c) {
+ ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
+ }
+ }
+
+ as_return_and_die($i, $channel);
+ }
+
+ goaway(z_root() . '/item/' . argv(1));
+ }
+}
diff --git a/Zotlabs/Module/Dircensor.php b/Zotlabs/Module/Dircensor.php
index 0fa65e948..4ce3a81c4 100644
--- a/Zotlabs/Module/Dircensor.php
+++ b/Zotlabs/Module/Dircensor.php
@@ -4,6 +4,7 @@ namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
+use Zotlabs\Lib\Libzotdir;
class Dircensor extends Controller {
@@ -15,11 +16,12 @@ class Dircensor extends Controller {
$dirmode = intval(get_config('system','directory_mode'));
- if (! ($dirmode == DIRECTORY_MODE_PRIMARY || $dirmode == DIRECTORY_MODE_STANDALONE)) {
+ if(!in_array($dirmode, [DIRECTORY_MODE_PRIMARY, DIRECTORY_MODE_SECONDARY, DIRECTORY_MODE_STANDALONE])) {
return;
}
$xchan = argv(1);
+
if(! $xchan) {
return;
}
@@ -32,19 +34,43 @@ class Dircensor extends Controller {
return;
}
- $val = (($r[0]['xchan_censored']) ? 0 : 1);
+ $severity = intval($_REQUEST['severity'] ?? 0);
+ $flag = DIRECTORY_FLAG_OK;
+
+ if ($severity === 1) {
+ $flag = DIRECTORY_FLAG_UNSAFE;
+ }
+
+ if ($severity === 2) {
+ $flag = DIRECTORY_FLAG_HIDDEN;
+ }
+
+ Libzotdir::update($xchan, $r[0]['xchan_url'], true, $flag);
- q("update xchan set xchan_censored = $val where xchan_hash = '%s'",
+ q("UPDATE xchan SET xchan_censored = %d WHERE xchan_hash = '%s'",
+ intval($flag),
dbesc($xchan)
);
- if($val) {
+ q("UPDATE xtag SET xtag_flags = %d WHERE xtag_hash = '%s'",
+ intval($flag),
+ dbesc($xchan)
+ );
+
+ if($flag) {
info( t('Entry censored') . EOL);
}
else {
- info( t('Entry uncensored') . EOL);
+ info( t('Entry OK') . EOL);
}
-
+
+ if (isset($_REQUEST['aj'])) {
+ json_return_and_die([
+ 'success' => 1,
+ 'flag' => $flag
+ ]);
+ }
+
goaway(z_root() . '/directory');
}
diff --git a/Zotlabs/Module/Directory.php b/Zotlabs/Module/Directory.php
index 2958e80dc..13353c108 100644
--- a/Zotlabs/Module/Directory.php
+++ b/Zotlabs/Module/Directory.php
@@ -151,7 +151,7 @@ class Directory extends Controller {
$url = '';
- if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
+ if(in_array($dirmode, [DIRECTORY_MODE_PRIMARY, DIRECTORY_MODE_SECONDARY, DIRECTORY_MODE_STANDALONE])) {
$url = z_root() . '/dirsearch';
if (is_site_admin()) {
$directory_admin = true;
@@ -191,7 +191,10 @@ class Directory extends Controller {
if(get_config('system','disable_directory_keywords'))
$kw = 0;
- $query = $url . '?f=&kw=' . $kw . (($safe_mode != 1) ? '&safe=' . $safe_mode : '');
+ if (intval($safe_mode) === 0 && $directory_admin)
+ $safe_mode = -1;
+
+ $query = $url . '?f=&kw=' . $kw . (($safe_mode < 1) ? '&safe=' . $safe_mode : '');
if($token)
$query .= '&t=' . $token;
@@ -296,10 +299,11 @@ class Directory extends Controller {
$hometown = ((x($profile,'hometown') == 1) ? html2plain($profile['hometown']) : False);
$about = ((x($profile,'about') == 1) ? zidify_links(bbcode($profile['about'], ['tryoembed' => false])) : False);
- if ($about && $safe_mode) {
- $about = html2plain($about);
+ if ($about && $safe_mode > 0) {
+ $about = strip_tags($about, '<br>');
}
+
$keywords = ((x($profile,'keywords')) ? $profile['keywords'] : '');
@@ -351,11 +355,15 @@ class Directory extends Controller {
'gender' => $gender,
'pdesc' => $pdesc,
'pdesc_label' => t('Description:'),
- 'censor' => (($directory_admin) ? 'dircensor/' . $rr['hash'] : ''),
- 'censor_label' => (($rr['censored']) ? t('Uncensor') : t('Censor')),
+ 'censor' => (($directory_admin) ? 'dircensor/' . $rr['hash'] . '?severity=' . ((intval($rr['censored']) > 0) ? 0 : 1) : ''),
+ 'censor_label' => t('Unsafe'),
+ 'censor_class' => ((intval($rr['censored']) === 1) ? 'active' : ''),
+ 'censor_2' => (($directory_admin) ? 'dircensor/' . $rr['hash'] . '?severity=' . ((intval($rr['censored']) > 1) ? 0 : 2) : ''),
+ 'censor_2_label' => t('Spam'),
+ 'censor_2_class' => ((intval($rr['censored']) > 1) ? 'active' : ''),
'marital' => $marital,
'homepage' => $homepage,
- 'homepageurl' => (($safe_mode) ? $homepageurl : linkify($homepageurl)),
+ 'homepageurl' => (($safe_mode > 0) ? $homepageurl : linkify($homepageurl)),
'hometown' => $hometown,
'hometown_label' => t('Hometown:'),
'about' => $about,
@@ -436,7 +444,8 @@ class Directory extends Controller {
'$reverse' => t('Reverse Alphabetic'),
'$date' => t('Newest to Oldest'),
'$reversedate' => t('Oldest to Newest'),
- '$suggest' => $suggest ? '&suggest=1' : ''
+ '$suggest' => $suggest ? '&suggest=1' : '',
+ '$directory_admin' => $directory_admin
));
diff --git a/Zotlabs/Module/Dirsearch.php b/Zotlabs/Module/Dirsearch.php
index c0df8a1e3..7efac6345 100644
--- a/Zotlabs/Module/Dirsearch.php
+++ b/Zotlabs/Module/Dirsearch.php
@@ -15,8 +15,7 @@ class Dirsearch extends Controller {
$ret = array('success' => false);
- // logger('request: ' . print_r($_REQUEST,true));
-
+ // logger('request: ' . print_r($_REQUEST,true));
$dirmode = intval(get_config('system','directory_mode'));
@@ -25,7 +24,6 @@ class Dirsearch extends Controller {
json_return_and_die($ret);
}
-
$access_token = $_REQUEST['t'] ?? '';
$token = get_config('system','realm_token');
@@ -41,7 +39,8 @@ class Dirsearch extends Controller {
}
$sql_extra = '';
-
+ $keywords_query = '';
+ $hub_query = '';
$tables = array('name','address','locale','region','postcode','country','gender','marital','sexual','keywords');
@@ -85,9 +84,7 @@ class Dirsearch extends Controller {
// by default use a safe search
- $safe = ((x($_REQUEST,'safe'))); // ? intval($_REQUEST['safe']) : 1 );
- if ($safe === false)
- $safe = 1;
+ $safe = $_REQUEST['safe'] ?? 1;
if(array_key_exists('sync',$_REQUEST)) {
if($_REQUEST['sync'])
@@ -102,10 +99,10 @@ class Dirsearch extends Controller {
$hub = \App::get_hostname();
}
- if($hub)
- $hub_query = " and xchan_hash in (select hubloc_hash from hubloc where hubloc_host = '" . protect_sprintf(dbesc($hub)) . "') ";
- else
- $hub_query = '';
+ if($hub) {
+ $hub_query = " and xchan_hash in (select hubloc_hash from hubloc where hubloc_deleted = 0 and hubloc_host = '" . protect_sprintf(dbesc($hub)) . "') ";
+ }
+
$sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : '');
@@ -131,9 +128,16 @@ class Dirsearch extends Controller {
$sql_extra .= $this->dir_query_build($joiner,'xprof_marital',$marital);
if($sexual)
$sql_extra .= $this->dir_query_build($joiner,'xprof_sexual',$sexual);
- if($keywords)
+ if($keywords && $name) {
+ // this is a general search
$sql_extra .= $this->dir_query_build($joiner,'xprof_keywords',$keywords);
-
+ }
+ if($keywords && !$name) {
+ // this is a search for keywords only
+ $keywords_arr = explode(',', $keywords);
+ stringify_array_elms($keywords_arr, true);
+ $keywords_query = " AND xchan_hash IN (SELECT xtag_hash FROM xtag WHERE xtag_term IN (" . protect_sprintf(implode(',', $keywords_arr)) . ")) ";
+ }
// we only support an age range currently. You must set both agege
// (greater than or equal) and agele (less than or equal)
@@ -177,9 +181,15 @@ class Dirsearch extends Controller {
$sql_extra .= " and xchan_addr like '%%" . \App::get_hostname() . "' ";
}
- $safesql = (($safe > 0) ? " and xchan_censored = 0 and xchan_selfcensored = 0 " : '');
+ $safesql = '';
+ if($safe > 0)
+ $safesql = " and xchan_censored = 0 and xchan_selfcensored = 0 ";
+
+ if($safe < 1)
+ $safesql = " and xchan_censored < 2 and xchan_selfcensored < 2 ";
+
if($safe < 0)
- $safesql = " and ( xchan_censored = 1 OR xchan_selfcensored = 1 ) ";
+ $safesql = " and xchan_censored < 3 and xchan_selfcensored < 2 ";
if($forums)
$safesql .= " and xchan_pubforum = " . ((intval($forums)) ? '1 ' : '0 ');
@@ -215,26 +225,25 @@ class Dirsearch extends Controller {
if($sync) {
$spkt = array('transactions' => array());
- $r = q("select * from updates where ud_date >= '%s' and ud_guid != '' and ud_addr != '' order by ud_date desc",
+
+ $r = q("SELECT * FROM updates WHERE ud_update = 0 AND ud_last = '%s' AND ud_date >= '%s' ORDER BY ud_date DESC",
+ dbesc(NULL_DATE),
dbesc($sync)
);
+
if($r) {
foreach($r as $rr) {
- $flags = array();
- if($rr['ud_flags'] & UPDATE_FLAGS_DELETED)
- $flags[] = 'deleted';
- if($rr['ud_flags'] & UPDATE_FLAGS_FORCED)
- $flags[] = 'forced';
-
- $spkt['transactions'][] = array(
+ $spkt['transactions'][] = [
'hash' => $rr['ud_hash'],
'address' => $rr['ud_addr'],
- 'transaction_id' => $rr['ud_guid'],
+ 'host' => $rr['ud_host'],
+ 'transaction_id' => $rr['ud_host'], // deprecated 2023-04-12 - can be removed after dir servers at version >= 8.4
'timestamp' => $rr['ud_date'],
- 'flags' => $flags
- );
+ 'flags' => $rr['ud_flags']
+ ];
}
}
+
json_return_and_die($spkt);
}
else {
@@ -264,7 +273,7 @@ class Dirsearch extends Controller {
xprof.xprof_hometown as hometown,
xprof.xprof_keywords as keywords
from xchan left join xprof on xchan_hash = xprof_hash left join hubloc on (hubloc_id_url = xchan_url and hubloc_hash = xchan_hash)
- where hubloc_primary = 1 and hubloc_updated > %s - INTERVAL %s and ( $logic $sql_extra ) $hub_query and xchan_network = 'zot6' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0
+ where hubloc_primary = 1 and hubloc_updated > %s - INTERVAL %s and ( $logic $sql_extra ) $hub_query $keywords_query and xchan_network = 'zot6' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0
$safesql $order $qlimit",
db_utcnow(),
db_quoteinterval('30 DAY')
diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php
index b3b040e96..a5f66d72e 100644
--- a/Zotlabs/Module/Item.php
+++ b/Zotlabs/Module/Item.php
@@ -63,8 +63,8 @@ class Item extends Controller {
// do we have the item (at all)?
- $r = q("select * from item where mid = '%s' $item_normal limit 1",
- dbesc(z_root() . '/item/' . $item_id)
+ $r = q("select parent_mid from item where uuid = '%s' $item_normal limit 1",
+ dbesc($item_id)
);
if (!$r) {
@@ -84,7 +84,7 @@ class Item extends Controller {
}
observer_auth($portable_id);
- $i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1",
+ $i = q("select id as item_id, uid from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1",
dbesc($r[0]['parent_mid']),
dbesc($portable_id)
);
@@ -99,7 +99,7 @@ class Item extends Controller {
$sql_extra = item_permissions_sql(0);
if (!$i) {
- $i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
+ $i = q("select id as item_id, uid from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
dbesc($r[0]['parent_mid'])
);
}
@@ -108,57 +108,53 @@ class Item extends Controller {
http_status_exit(403, 'Forbidden');
}
- $parents_str = ids_to_querystr($i, 'item_id');
-
- $items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal order by item.id asc",
- dbesc($parents_str)
- );
+ $chan = channelx_by_n($i[0]['uid']);
- if (!$items) {
+ if (!$chan) {
http_status_exit(404, 'Not found');
}
- xchan_query($items, true);
- $items = fetch_post_tags($items, true);
-
- if (!$items)
- http_status_exit(404, 'Not found');
+ if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream')) {
+ http_status_exit(403, 'Forbidden');
+ }
- $chan = channelx_by_n($items[0]['uid']);
+ $parents_str = ids_to_querystr($i, 'item_id');
- if (!$chan)
- http_status_exit(404, 'Not found');
+ $total = q("SELECT count(*) AS count FROM item WHERE parent = %d $item_normal",
+ intval($parents_str)
+ );
- if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream'))
- http_status_exit(403, 'Forbidden');
+ App::set_pager_total($total[0]['count']);
+ App::set_pager_itemspage(30);
+ if (App::$pager['total'] > App::$pager['itemspage']) {
+ // let mod conversation handle this request
+ App::$query_string = str_replace('item', 'conversation', App::$query_string);
+ $i = Activity::paged_collection_init(App::$pager['total'], App::$query_string);
+ as_return_and_die($i ,$chan);
+ }
+ else {
+ $items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent = %d $item_normal ORDER BY item.id",
+ intval($parents_str)
+ );
- $i = Activity::encode_item_collection($items, 'conversation/' . $item_id, 'OrderedCollection');
+ xchan_query($items, true);
+ $items = fetch_post_tags($items, true);
- if (!$i)
- http_status_exit(404, 'Not found');
+ $i = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection', App::$pager['total']);
+ }
if ($portable_id && (!intval($items[0]['item_private']))) {
- ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
+ $c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
+ intval($items[0]['uid']),
+ dbesc($portable_id)
+ );
+ if (!$c) {
+ ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
+ }
}
- $x = array_merge(['@context' => [
- ACTIVITYSTREAMS_JSONLD_REV,
- 'https://w3id.org/security/v1',
- z_root() . ZOT_APSCHEMA_REV
- ]], $i);
-
- $headers = [];
- $headers['Content-Type'] = 'application/x-zot+json';
- $x['signature'] = LDSignatures::sign($x, $chan);
- $ret = json_encode($x, JSON_UNESCAPED_SLASHES);
- $headers['Digest'] = HTTPSig::generate_digest_header($ret);
- $headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
- $h = HTTPSig::create_sig($headers, $chan['channel_prvkey'], channel_url($chan));
- HTTPSig::set_headers($h);
- echo $ret;
- killme();
-
+ as_return_and_die($i ,$chan);
}
if (ActivityStreams::is_as_request()) {
@@ -181,8 +177,7 @@ class Item extends Controller {
// do we have the item (at all)?
// add preferential bias to item owners (item_wall = 1)
- $r = q("select * from item where mid = '%s' or uuid = '%s' $item_normal order by item_wall desc limit 1",
- dbesc(z_root() . '/item/' . $item_id),
+ $r = q("select * from item where uuid = '%s' $item_normal order by item_wall desc limit 1",
dbesc($item_id)
);
@@ -255,23 +250,7 @@ class Item extends Controller {
}
}
- $x = array_merge(['@context' => [
- ACTIVITYSTREAMS_JSONLD_REV,
- 'https://w3id.org/security/v1',
- z_root() . ZOT_APSCHEMA_REV
- ]], $i);
-
- $headers = [];
- $headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
- $x['signature'] = LDSignatures::sign($x, $chan);
- $ret = json_encode($x, JSON_UNESCAPED_SLASHES);
- $headers['Date'] = datetime_convert('UTC', 'UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T');
- $headers['Digest'] = HTTPSig::generate_digest_header($ret);
- $headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
- $h = HTTPSig::create_sig($headers, $chan['channel_prvkey'], channel_url($chan));
- HTTPSig::set_headers($h);
- echo $ret;
- killme();
+ as_return_and_die($i ,$chan);
}
diff --git a/Zotlabs/Module/Like.php b/Zotlabs/Module/Like.php
index 2cf792c8d..5779faa19 100644
--- a/Zotlabs/Module/Like.php
+++ b/Zotlabs/Module/Like.php
@@ -451,7 +451,7 @@ class Like extends Controller {
}
else {
$post_type = (($item['resource_type'] === 'photo') ? t('photo') : t('status'));
- if ($item['obj_type'] === ACTIVITY_OBJ_EVENT)
+ if (in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT]))
$post_type = t('event');
$obj_type = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE);
@@ -507,7 +507,7 @@ class Like extends Controller {
$private = (($public) ? 0 : 1);
}
else {
- $arr['parent'] = $item['id'];
+ $arr['parent'] = $item['parent'];
$arr['thr_parent'] = $item['mid'];
$ulink = '[zrl=' . $item_author['xchan_url'] . '][bdi]' . $item_author['xchan_name'] . '[/bdi][/zrl]';
$alink = '[zrl=' . $observer['xchan_url'] . '][bdi]' . $observer['xchan_name'] . '[/bdi][/zrl]';
@@ -524,7 +524,7 @@ class Like extends Controller {
$arr['uid'] = $owner_uid;
$arr['item_flags'] = $item['item_flags'];
$arr['item_wall'] = $item['item_wall'];
- $arr['parent_mid'] = (($extended_like) ? $arr['mid'] : $item['mid']);
+ $arr['parent_mid'] = (($extended_like) ? $arr['mid'] : $item['parent_mid']);
$arr['owner_xchan'] = (($extended_like) ? $ch[0]['xchan_hash'] : $thread_owner['xchan_hash']);
$arr['author_xchan'] = $observer['xchan_hash'];
$arr['body'] = sprintf($bodyverb, $alink, $ulink, $plink);
diff --git a/Zotlabs/Module/Owa.php b/Zotlabs/Module/Owa.php
index 3400defd7..02997d3f1 100644
--- a/Zotlabs/Module/Owa.php
+++ b/Zotlabs/Module/Owa.php
@@ -32,7 +32,8 @@ class Owa extends Controller {
$keyId = $sigblock['keyId'];
if ($keyId) {
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
- WHERE hubloc_id_url = '%s' AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC",
+ WHERE ( hubloc_addr = '%s' OR hubloc_id_url = '%s' ) AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC",
+ dbesc(str_replace('acct:', '', $keyId)),
dbesc($keyId)
);
if (! $r) {
diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php
index 10d2e8f47..fa87d96e5 100644
--- a/Zotlabs/Module/Photo.php
+++ b/Zotlabs/Module/Photo.php
@@ -271,7 +271,6 @@ class Photo extends \Zotlabs\Web\Controller {
$modified = time();
header_remove('Pragma');
-
if((isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] === $etag) || (!isset($_SERVER['HTTP_IF_NONE_MATCH']) && isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $_SERVER['HTTP_IF_MODIFIED_SINCE'] === gmdate("D, d M Y H:i:s", $modified) . " GMT")) {
header_remove('Expires');
header_remove('Cache-Control');
@@ -307,6 +306,8 @@ class Photo extends \Zotlabs\Web\Controller {
// This has performance considerations but we highly recommend you
// leave it alone.
+
+
$maxage = $cache_mode['age'];
if($cache_mode['exp'] || (! isset($expires)) || (isset($expires) && $expires - 60 < time()))
diff --git a/Zotlabs/Module/Profiles.php b/Zotlabs/Module/Profiles.php
index e248cd028..ce496252b 100644
--- a/Zotlabs/Module/Profiles.php
+++ b/Zotlabs/Module/Profiles.php
@@ -217,7 +217,6 @@ class Profiles extends \Zotlabs\Web\Controller {
check_form_security_token_redirectOnErr('/profiles', 'profile_edit');
-
$is_default = (($orig[0]['is_default']) ? 1 : 0);
$profile_name = notags(trim($_POST['profile_name']));
@@ -579,12 +578,12 @@ class Profiles extends \Zotlabs\Web\Controller {
$channel = \App::get_channel();
if($namechanged && $is_default) {
- // change name on all associated xchans by matching the url
- q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_url = '%s'",
+ q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_hash = '%s'",
dbesc($name),
dbesc(datetime_convert()),
- dbesc(z_root() . '/channel/' . $channel['channel_address'])
+ dbesc($channel['xchan_hash'])
);
+
q("UPDATE channel SET channel_name = '%s' WHERE channel_hash = '%s'",
dbesc($name),
dbesc($channel['xchan_hash'])
diff --git a/Zotlabs/Module/Search.php b/Zotlabs/Module/Search.php
index 6601da29d..6b1060570 100644
--- a/Zotlabs/Module/Search.php
+++ b/Zotlabs/Module/Search.php
@@ -58,7 +58,7 @@ class Search extends Controller {
$o .= search($search, 'search-box', '/search', ((local_channel()) ? true : false));
- if (local_channel() && strpos($search, 'https://') === 0 && !$update && !$load) {
+ if (local_channel() && str_starts_with($search, 'https://') && !$update && !$load) {
$url = htmlspecialchars_decode($search);
@@ -75,7 +75,7 @@ class Search extends Controller {
if ($f) {
$mid = $f[0]['message_id'];
foreach ($f as $m) {
- if (strpos($search, $m['message_id']) === 0) {
+ if (str_starts_with($url, $m['message_id'])) {
$mid = $m['message_id'];
break;
}
diff --git a/Zotlabs/Module/Wfinger.php b/Zotlabs/Module/Wfinger.php
index 048fcde3f..43b039530 100644
--- a/Zotlabs/Module/Wfinger.php
+++ b/Zotlabs/Module/Wfinger.php
@@ -76,7 +76,10 @@ class Wfinger extends \Zotlabs\Web\Controller {
}
}
else {
- $r = channelx_by_nick($channel);
+ // Also provide already deleted channels info here.
+ // This is required in the case where we need to verify keys
+ // of updates which we have got via directory sync.
+ $r = channelx_by_nick($channel, true);
}
}
@@ -94,10 +97,6 @@ class Wfinger extends \Zotlabs\Web\Controller {
'href' => z_root() . '/owa',
],
];
-
-
-
-
}
if($resource && $r) {
diff --git a/Zotlabs/Thumbs/Epubthumb.php b/Zotlabs/Thumbs/Epubthumb.php
index 22f1a5e8f..6ebbd8933 100644
--- a/Zotlabs/Thumbs/Epubthumb.php
+++ b/Zotlabs/Thumbs/Epubthumb.php
@@ -30,9 +30,14 @@ class Epubthumb {
*/
function Thumb($attach, $preview_style, $height = 300, $width = 300) {
+ $file = dbunescbin($attach['content']);
+ if (!$file) {
+ return;
+ }
+
$photo = false;
- $ep = new \EPub(dbunescbin($attach['content']));
+ $ep = new \EPub($file);
$data = $ep->Cover();
if($data['found']) {
diff --git a/Zotlabs/Thumbs/Mp3audio.php b/Zotlabs/Thumbs/Mp3audio.php
index 000d65b22..c50338fb2 100644
--- a/Zotlabs/Thumbs/Mp3audio.php
+++ b/Zotlabs/Thumbs/Mp3audio.php
@@ -11,9 +11,16 @@ class Mp3audio {
}
function Thumb($attach,$preview_style,$height = 300, $width = 300) {
+
+ $file = dbunescbin($attach['content']);
+ if (!$file) {
+ return;
+ }
+
+ $photo = false;
$p = new ID3Parser();
- $id = $p->analyze(dbunescbin($attach['content']));
+ $id = $p->analyze($file);
$photo = isset($id['id3v2']['APIC'][0]['data']) ? $id['id3v2']['APIC'][0]['data'] : null;
if(is_null($photo) && isset($id['id3v2']['PIC'][0]['data'])) {
diff --git a/Zotlabs/Thumbs/Pdf.php b/Zotlabs/Thumbs/Pdf.php
index 11714ad53..6f9111ed3 100644
--- a/Zotlabs/Thumbs/Pdf.php
+++ b/Zotlabs/Thumbs/Pdf.php
@@ -11,9 +11,13 @@ class Pdf {
function Thumb($attach,$preview_style,$height = 300, $width = 300) {
+ $file = dbunescbin($attach['content']);
+ if (!$file) {
+ return;
+ }
+
$photo = false;
- $file = dbunescbin($attach['content']);
$tmpfile = $file . '.pdf';
$outfile = $file . '.jpg';
diff --git a/Zotlabs/Thumbs/Text.php b/Zotlabs/Thumbs/Text.php
index 31e27d014..b2f13c578 100644
--- a/Zotlabs/Thumbs/Text.php
+++ b/Zotlabs/Thumbs/Text.php
@@ -11,11 +11,12 @@ class Text {
function Thumb($attach,$preview_style,$height = 300, $width = 300) {
- if (empty($attach['content'])) {
+ $file = dbunescbin($attach['content']);
+ if (!$file) {
return;
}
- $stream = @fopen(dbunescbin($attach['content']),'rb');
+ $stream = @fopen($file,'rb');
if($stream) {
$content = trim(stream_get_contents($stream,4096));
$content = str_replace("\r",'',$content);
diff --git a/Zotlabs/Thumbs/Video.php b/Zotlabs/Thumbs/Video.php
index 15d3ace12..9df27d703 100644
--- a/Zotlabs/Thumbs/Video.php
+++ b/Zotlabs/Thumbs/Video.php
@@ -11,16 +11,19 @@ class Video {
function Thumb($attach,$preview_style,$height = 300, $width = 300) {
+ $file = dbunescbin($attach['content']);
+ if (!$file) {
+ return;
+ }
+
$photo = false;
$t = explode('/',$attach['filetype']);
if($t[1])
$extension = '.' . $t[1];
else
- return;
+ return;
-
- $file = dbunescbin($attach['content']);
$tmpfile = $file . $extension;
$outfile = $file . '.jpg';
@@ -40,7 +43,7 @@ class Video {
$ffmpeg = trim(shell_exec('which ffmpeg'));
- if($ffmpeg) {
+ if($ffmpeg) {
logger('ffmpeg not found in path. Video thumbnails may fail.');
}
@@ -59,7 +62,7 @@ class Video {
@rename($outfile,$file . '.thumb');
}
}
-
+
@unlink($tmpfile);
}
}
diff --git a/Zotlabs/Update/_1256.php b/Zotlabs/Update/_1256.php
new file mode 100644
index 000000000..dd6ded225
--- /dev/null
+++ b/Zotlabs/Update/_1256.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1256 {
+
+ function run() {
+
+ dbq("START TRANSACTION");
+
+ $r1 = dbq("TRUNCATE TABLE updates");
+
+ if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
+ $r2a = dbq("ALTER TABLE updates add ud_update numeric(1) NOT NULL DEFAULT '0'");
+ $r2b = dbq("CREATE INDEX ud_update ON updates (ud_update)");
+
+ $r2 = ($r2a && $r2b);
+ }
+
+ if(ACTIVE_DBTYPE == DBTYPE_MYSQL) {
+ $r2 = dbq("ALTER TABLE updates add ud_update tinyint(1) NOT NULL DEFAULT '0',
+ ADD INDEX (ud_update);"
+ );
+ }
+
+ if($r1 && $r2) {
+ dbq("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ q("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Update/_1257.php b/Zotlabs/Update/_1257.php
new file mode 100644
index 000000000..34c10c372
--- /dev/null
+++ b/Zotlabs/Update/_1257.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1257 {
+
+ function run() {
+
+ dbq("START TRANSACTION");
+
+ $r1 = dbq("TRUNCATE TABLE updates");
+
+ if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
+ $r2 = dbq("ALTER TABLE updates add ud_host text NOT NULL DEFAULT ''");
+ }
+
+ if(ACTIVE_DBTYPE == DBTYPE_MYSQL) {
+ $r2 = dbq("ALTER TABLE updates add ud_host varchar(191) NOT NULL DEFAULT ''");
+ }
+
+ $r3 = dbq("ALTER TABLE updates DROP COLUMN ud_guid");
+
+ if($r1 && $r2 && $r3) {
+ dbq("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ q("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Update/_1258.php b/Zotlabs/Update/_1258.php
new file mode 100644
index 000000000..13812219e
--- /dev/null
+++ b/Zotlabs/Update/_1258.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1258 {
+
+ function run() {
+
+ dbq("DELETE FROM pconfig WHERE cat = 'channelreputation'");
+ dbq("DELETE FROM iconfig WHERE cat = 'channelreputation'");
+
+ }
+
+}
diff --git a/Zotlabs/Widget/Pinned.php b/Zotlabs/Widget/Pinned.php
index 6d2618deb..bd1c0e462 100644
--- a/Zotlabs/Widget/Pinned.php
+++ b/Zotlabs/Widget/Pinned.php
@@ -67,7 +67,7 @@ class Pinned {
$conv_responses = [];
- if($item['obj_type'] === ACTIVITY_OBJ_EVENT) {
+ if(in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
$conv_responses['attendyes'] = [ 'title' => t('Attending','title') ];
$conv_responses['attendno'] = [ 'title' => t('Not attending','title') ];
$conv_responses['attendmaybe'] = [ 'title' => t('Might attend','title') ];