aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs
diff options
context:
space:
mode:
Diffstat (limited to 'Zotlabs')
-rw-r--r--Zotlabs/Daemon/Channel_purge.php2
-rw-r--r--Zotlabs/Daemon/Cron.php49
-rw-r--r--Zotlabs/Daemon/Expire.php4
-rw-r--r--Zotlabs/Daemon/Importdoc.php27
-rw-r--r--Zotlabs/Daemon/Notifier.php26
-rw-r--r--Zotlabs/Lib/Activity.php91
-rw-r--r--Zotlabs/Lib/Libzot.php52
-rw-r--r--Zotlabs/Lib/Mailer.php86
-rw-r--r--Zotlabs/Lib/ThreadItem.php92
-rw-r--r--Zotlabs/Module/Admin/Accounts.php258
-rw-r--r--Zotlabs/Module/Conversation.php3
-rw-r--r--Zotlabs/Module/Dreport.php8
-rw-r--r--Zotlabs/Module/Editpost.php1
-rw-r--r--Zotlabs/Module/Item.php27
-rw-r--r--Zotlabs/Module/Owa.php184
-rw-r--r--Zotlabs/Module/Pubstream.php8
-rw-r--r--Zotlabs/Module/Sse.php3
-rw-r--r--Zotlabs/Module/Sse_bs.php20
-rw-r--r--Zotlabs/Web/WebServer.php2
19 files changed, 507 insertions, 436 deletions
diff --git a/Zotlabs/Daemon/Channel_purge.php b/Zotlabs/Daemon/Channel_purge.php
index d25edf8ba..7286a791a 100644
--- a/Zotlabs/Daemon/Channel_purge.php
+++ b/Zotlabs/Daemon/Channel_purge.php
@@ -24,7 +24,7 @@ class Channel_purge {
);
if ($r) {
foreach ($r as $rv) {
- drop_item($rv['id']);
+ drop_item($rv['id'], uid: $channel_id);
}
}
} while ($r);
diff --git a/Zotlabs/Daemon/Cron.php b/Zotlabs/Daemon/Cron.php
index 186f3efcf..a38809f45 100644
--- a/Zotlabs/Daemon/Cron.php
+++ b/Zotlabs/Daemon/Cron.php
@@ -69,19 +69,18 @@ class Cron {
// expire any expired items
- $r = q("select id,item_wall from item where expires > '2001-01-01 00:00:00' and expires < %s
+ $r = q("select id, uid, item_wall from item where expires > '2001-01-01 00:00:00' and expires < %s
and item_deleted = 0 ",
db_utcnow()
);
+
if ($r) {
- require_once('include/items.php');
foreach ($r as $rr) {
+ // pass uid of the message for permission check as we are running as a daemon process with no session.
drop_item($rr['id'], (($rr['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL), uid: intval($rr['uid']));
-
if ($rr['item_wall']) {
// The notifier isn't normally invoked unless item_drop is interactive.
Master::Summon(['Notifier', 'drop', $rr['id']]);
-
if ($interval) {
usleep($interval);
}
@@ -148,37 +147,29 @@ class Cron {
// (time travel posts). Restrict to items that have come of age in the last
// couple of days to limit the query to something reasonable.
- $r = q("select id from item where item_delayed = 1 and created <= %s and created > '%s' ",
+ $r = q("select * from item where item_delayed = 1 and created <= %s and created > '%s' ",
db_utcnow(),
dbesc(datetime_convert('UTC', 'UTC', 'now - 2 days'))
);
- if ($r) {
- foreach ($r as $rr) {
- $x = q("update item set item_delayed = 0 where id = %d",
- intval($rr['id'])
- );
- if ($x) {
- $z = q("select * from item where id = %d",
- intval($rr['id'])
- );
- if ($z) {
- xchan_query($z);
- $sync_item = fetch_post_tags($z);
- Libsync::build_sync_packet($sync_item[0]['uid'],
- [
- 'item' => [encode_item($sync_item[0], true)]
- ]
- );
- }
- Master::Summon(array('Notifier', 'wall-new', $rr['id']));
- if ($interval) {
- usleep($interval);
+ if ($r) {
+ xchan_query($r);
+ $items = fetch_post_tags($r);
+ foreach ($items as $item) {
+ $item['item_delayed'] = 0;
+ $post = item_store_update($item);
+
+ if($post['success']) {
+ Master::Summon(['Notifier', 'wall-new', $post['item_id']]);
+ if (!empty($post['approval_id'])) {
+ Master::Summon(['Notifier', 'wall-new', $post['approval_id']]);
}
}
- }
- }
-
+ if ($interval) {
+ usleep($interval);
+ }
+ }
+ }
// once daily run birthday_updates and then expire in background
// FIXME: add birthday updates, both locally and for xprof for use
diff --git a/Zotlabs/Daemon/Expire.php b/Zotlabs/Daemon/Expire.php
index 3ac3dee3a..dae585578 100644
--- a/Zotlabs/Daemon/Expire.php
+++ b/Zotlabs/Daemon/Expire.php
@@ -23,13 +23,13 @@ class Expire {
// perform final cleanup on previously delete items
- $r = q("select id from item where item_deleted = 1 and item_pending_remove = 0 and changed < %s - INTERVAL %s",
+ $r = q("select id, uid from item where item_deleted = 1 and item_pending_remove = 0 and changed < %s - INTERVAL %s",
db_utcnow(),
db_quoteinterval('10 DAY')
);
if ($r) {
foreach ($r as $rr) {
- drop_item($rr['id'], DROPITEM_PHASE2);
+ drop_item($rr['id'], DROPITEM_PHASE2, uid: $rr['uid']);
}
}
diff --git a/Zotlabs/Daemon/Importdoc.php b/Zotlabs/Daemon/Importdoc.php
index 8f04e05f8..de571848e 100644
--- a/Zotlabs/Daemon/Importdoc.php
+++ b/Zotlabs/Daemon/Importdoc.php
@@ -11,6 +11,21 @@ class Importdoc {
self::update_docs_dir('doc/*');
+ $sys = get_sys_channel();
+
+ // remove old files that weren't updated (indicates they were most likely deleted).
+ $i = q("select id from item where uid = %d and item_type = 5 and edited < %s - INTERVAL %s",
+ intval($sys['channel_id']),
+ db_utcnow(),
+ db_quoteinterval('14 DAY')
+ );
+
+ if ($i) {
+ foreach ($i as $iv) {
+ drop_item($iv['id'], uid: $sys['channel_id']);
+ }
+ }
+
return;
}
@@ -41,18 +56,6 @@ class Importdoc {
}
}
}
-
- // remove old files that weren't updated (indicates they were most likely deleted).
- $i = q("select * from item where item_type = 5 and edited < %s - %s",
- db_utcnow(),
- db_quoteinterval('14 DAY', true)
- );
-
- if ($i) {
- foreach ($i as $iv) {
- drop_item($iv['id'], DROPITEM_NORMAL, true);
- }
- }
}
}
diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php
index 1693f9c9f..043b406cc 100644
--- a/Zotlabs/Daemon/Notifier.php
+++ b/Zotlabs/Daemon/Notifier.php
@@ -241,11 +241,6 @@ class Notifier {
$target_item = $r[0];
- if (in_array($target_item['author']['xchan_network'], ['rss', 'anon', 'token'])) {
- logger('notifier: target item author is not a fetchable actor', LOGGER_DEBUG);
- return;
- }
-
if (intval($target_item['item_deleted'])) {
logger('notifier: target item ITEM_DELETED', LOGGER_DEBUG);
}
@@ -268,22 +263,9 @@ class Notifier {
}
- // Check for non published items, but allow an exclusion for transmitting hidden file activities
-
- if (intval($target_item['item_unpublished']) || intval($target_item['item_delayed']) ||
- intval($target_item['item_blocked']) || intval($target_item['item_hidden'])) {
- logger('notifier: target item not published, so not forwardable', LOGGER_DEBUG);
- return;
- }
-
- // follow/unfollow is for internal use only
- if (in_array($target_item['verb'], ['Follow', 'Ignore', ACTIVITY_FOLLOW, ACTIVITY_UNFOLLOW])) {
- logger('not fowarding follow/unfollow note activity');
- return;
- }
-
- if (strpos($target_item['postopts'], 'nodeliver') !== false) {
- logger('notifier: target item is undeliverable', LOGGER_DEBUG);
+ if (!item_forwardable($target_item)) {
+ //hz_syslog(print_r($target_item,true));
+ logger('notifier: target item not forwardable', LOGGER_DEBUG);
return;
}
@@ -388,7 +370,7 @@ class Notifier {
logger('normal (downstream) distribution', LOGGER_DEBUG);
}
- if ($parent_item && $parent_item['item_private'] !== $target_item['item_private']) {
+ if (($parent_item && $parent_item['item_private'] !== $target_item['item_private']) || (intval($target_item['item_restrict']) & 1)) {
logger('conversation privacy mismatch - downstream delivery prevented');
return;
}
diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
index 54a1b8d2a..10df11174 100644
--- a/Zotlabs/Lib/Activity.php
+++ b/Zotlabs/Lib/Activity.php
@@ -2081,6 +2081,9 @@ class Activity {
$i = fetch_post_tags($i);
$i[0]['obj'] = $o;
+ $edited = datetime_convert();
+ $i[0]['edited'] = $edited;
+
// create the new object
$newObj = self::build_packet(self::encode_activity($i[0]), $channel, true);
@@ -2098,7 +2101,7 @@ class Activity {
dbesc(json_encode($o)),
intval($relatedItem['id']),
dbesc($newObj),
- dbesc(datetime_convert())
+ dbesc($edited)
);
dbq("COMMIT");
@@ -2306,6 +2309,8 @@ class Activity {
if ($s['mid'] === $s['parent_mid']) {
$s['item_thread_top'] = 1;
+ $s['item_nocomment'] = 0;
+ $s['comments_closed'] = NULL_DATE;
// it is a parent node - decode the comment policy info if present
if ($act->objprop('commentPolicy')) {
@@ -2313,7 +2318,7 @@ class Activity {
if ($until !== false) {
$s['comments_closed'] = datetime_convert('UTC', 'UTC', substr($act->obj['commentPolicy'], $until + 6));
if ($s['comments_closed'] < datetime_convert()) {
- $s['nocomment'] = true;
+ $s['item_nocomment'] = 1;
}
}
@@ -2680,6 +2685,7 @@ class Activity {
}
}
+
if (!$ap_rawmsg && array_key_exists('signed', $raw_arr)) {
// zap
$ap_rawmsg = json_encode($act->data, JSON_UNESCAPED_SLASHES);
@@ -2713,8 +2719,7 @@ class Activity {
return $hookinfo['s'];
}
-
- static function store($channel, $observer_hash, $act, $item, $fetch_parents = true, $force = false) {
+ static function store($channel, $observer_hash, $act, $item, $fetch_parents = true, $force = false, $is_collection_operation = false) {
$is_sys_channel = is_sys_channel($channel['channel_id']);
$is_child_node = false;
$parent = null;
@@ -2745,6 +2750,8 @@ class Activity {
}
$allowed = false;
+ $relay = false;
+
$permit_mentions = intval(PConfig::Get($channel['channel_id'], 'system','permit_all_mentions') && i_am_mentioned($channel, $item));
if ($is_child_node) {
@@ -2771,13 +2778,22 @@ class Activity {
return;
}
+ $relay = $channel['channel_hash'] === $parent[0]['owner_xchan'];
+
+ if (str_contains($parent[0]['tgt_type'], 'Collection') && !$relay && !$isCollectionOperation) {
+ logger('not a collection activity');
+ return;
+ }
+
if ($parent[0]['obj_type'] === 'Question') {
if (in_array($item['obj_type'], ['Note', ACTIVITY_OBJ_COMMENT]) && $item['title'] && (!$item['body'])) {
$item['obj_type'] = 'Answer';
+ $item['item_hidden'] = 1;
}
}
if ($parent[0]['item_wall']) {
+
// set the owner to the owner of the parent
$item['owner_xchan'] = $parent[0]['owner_xchan'];
@@ -3032,17 +3048,48 @@ class Activity {
dbesc($item['mid']),
intval($item['uid'])
);
+
if ($r) {
if ($item['edited'] > $r[0]['edited']) {
$item['id'] = $r[0]['id'];
- $x = item_store_update($item);
+ $x = item_store_update($item, deliver: false);
}
else {
return;
}
}
else {
- $x = item_store($item);
+ $x = item_store($item, deliver: false, addAndSync: false);
+ }
+
+ if ($x['success']) {
+
+ if ($relay && $channel['channel_hash'] === $x['item']['owner_xchan'] && $x['item']['verb'] !== 'Add' && !$isCollectionOperation) {
+ $approval = Activity::addToCollection($channel, $act->data, $x['item']['parent_mid'], $x['item'], deliver: false);
+ }
+
+ if (check_item_source($channel['channel_id'], $x['item']) && in_array($x['item']['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
+ event_addtocal($x['item_id'], $channel['channel_id']);
+ }
+
+ tag_deliver($channel['channel_id'], $x['item_id']);
+
+ if ($relay && $is_child_node) {
+ // We are the owner of this conversation, so send all received comments back downstream
+ Master::Summon(['Notifier', 'comment-import', $x['item_id']]);
+ if (!empty($approval['item_id'])) {
+ Master::Summon(['Notifier', 'comment-import', $approval['item_id']]);
+ }
+ }
+
+ $r = q("select * from item where id = %d limit 1",
+ intval($x['item_id'])
+ );
+
+ if ($r) {
+ send_status_notifications($x['item_id'], $r[0]);
+ }
+ sync_an_item($channel['channel_id'], $x['item_id']);
}
if ($fetch_parents && $parent && !intval($parent[0]['item_private'])) {
@@ -3069,28 +3116,6 @@ class Activity {
}
}
}
-
- if ($x['success']) {
-
- if (check_item_source($channel['channel_id'], $x['item']) && in_array($x['item']['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
- event_addtocal($x['item_id'], $channel['channel_id']);
- }
-
- if ($is_child_node) {
- if ($item['owner_xchan'] === $channel['channel_hash']) {
- // We are the owner of this conversation, so send all received comments back downstream
- Master::Summon(['Notifier', 'comment-import', $x['item_id']]);
- }
- $r = q("select * from item where id = %d limit 1",
- intval($x['item_id'])
- );
- if ($r) {
- send_status_notifications($x['item_id'], $r[0]);
- }
- }
- sync_an_item($channel['channel_id'], $x['item_id']);
- }
-
}
/**
@@ -3785,8 +3810,6 @@ class Activity {
->setObjType($object['type'])
->setParentMid(str_replace('/conversation/','/item/', $target))
->setThrParent(str_replace('/conversation/','/item/', $target))
- // ->setApproved($object['object']['id'] ?? '')
- // ->setReplyto(z_root() . '/channel/' . $channel['channel_address'])
->setTgtType('Collection')
->setTarget([
'id' => str_replace('/item/','/conversation/', $target),
@@ -3801,13 +3824,19 @@ class Activity {
->setDenyCid($sourceItem['deny_cid'])
->setDenyGid($sourceItem['deny_gid'])
->setPrivate($sourceItem['item_private'])
- ->setNocomment($sourceItem['item_nocomment'])
+ ->setRestrict($sourceItem['item_restrict'])
+ ->setHidden($sourceItem['item_hidden'])
+ ->setDelayed($sourceItem['item_delayed'])
+ ->setUnpublished($sourceItem['item_unpublished'])
+ ->setBlocked($sourceItem['item_blocked'])
+ ->setType($sourceItem['item_type'])
->setCommentPolicy($sourceItem['comment_policy'])
->setPublicPolicy($sourceItem['public_policy'])
->setPostopts($sourceItem['postopts']);
}
$result = post_activity_item($item->toArray(), deliver: $deliver, channel: $channel, observer: $channel, addAndSync: false);
logger('addToCollection: ' . print_r($result, true));
+
return $result;
}
diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php
index 3d499bd08..60fb5e034 100644
--- a/Zotlabs/Lib/Libzot.php
+++ b/Zotlabs/Lib/Libzot.php
@@ -655,6 +655,11 @@ class Libzot {
return $ret;
}
+ if (empty($arr['primary_location']['address'])) {
+ logger('Empty primary location address: ' . print_r($arr, true), LOGGER_DEBUG);
+ return $ret;
+ }
+
/**
* @hooks import_xchan
* Called when processing the result of zot_finger() to store the result
@@ -1148,7 +1153,7 @@ class Libzot {
$AS = new ActivityStreams($data);
// process add/remove from collection separately, as it requires a target.
- // use the raw object, as it will not include actor expansion
+ // use the data object, as it will not include actor expansion
if (in_array($AS->type, ['Add', 'Remove'])
&& is_array($AS->obj)
&& array_key_exists('object', $AS->obj)
@@ -1227,7 +1232,6 @@ class Libzot {
logger('public post');
-
// Public post. look for any site members who are or may be accepting posts from this sender
// and who are allowed to see them based on the sender's permissions
// @fixme;
@@ -1294,25 +1298,6 @@ class Libzot {
$item['item_private'] = 1;
}
- if ($item['mid'] === $item['parent_mid']) {
- if (is_array($AS->obj) && array_key_exists('commentPolicy', $AS->obj)) {
- $p = strstr($AS->obj['commentPolicy'], 'until=');
- if ($p !== false) {
- $comments_closed_at = datetime_convert('UTC', 'UTC', substr($p, 6));
- if ($comments_closed_at === $item['created']) {
- $item['item_nocomment'] = 1;
- }
- else {
- $item['comments_closed'] = $comments_closed_at;
- $aritemr['comment_policy'] = trim(str_replace($p, '', $AS->obj['commentPolicy']));
- }
- }
- else {
- $item['comment_policy'] = $AS->obj['commentPolicy'];
- }
- }
- }
-
if (!empty($AS->meta['hubloc']) || $AS->sigok) {
$item['item_verified'] = true;
}
@@ -1576,7 +1561,7 @@ class Libzot {
$conversation_operation = $is_collection_operation && isset($arr['target']['attributedTo']);
- if (str_contains($arr['tgt_type'], 'Collection') && !$relay && !$conversation_operation) {
+ if (isset($arr['tgt_type']) && str_contains($arr['tgt_type'], 'Collection') && !$relay && !$conversation_operation) {
$DR->update('not a collection activity');
$result[] = $DR->get();
continue;
@@ -1663,22 +1648,24 @@ class Libzot {
if (intval($channel['channel_system']) && (!$arr['item_private']) && (!$relay)) {
$local_public = true;
- $r = q("select xchan_selfcensored from xchan where xchan_hash = '%s' limit 1",
- dbesc($sender)
- );
- // don't import sys channel posts from selfcensored authors
- if ($r && (intval($r[0]['xchan_selfcensored']))) {
+ $incl = Config::Get('system','pubstream_incl');
+ $excl = Config::Get('system','pubstream_excl');
+
+ if(($incl || $excl) && !MessageFilter::evaluate($arr, $incl, $excl)) {
$local_public = false;
continue;
}
- $incl = Config::Get('system','pubstream_incl');
- $excl = Config::Get('system','pubstream_excl');
+ $r = q("select xchan_selfcensored, xchan_censored from xchan where xchan_hash = '%s'",
+ dbesc($sender)
+ );
- if(($incl || $excl) && !MessageFilter::evaluate($arr, $incl, $excl)) {
+ // don't import sys channel posts from selfcensored or censored authors
+ if ($r && ($r[0]['xchan_selfcensored'] || $r[0]['xchan_censored'])) {
$local_public = false;
continue;
}
+
}
$tag_delivery = tgroup_check($channel['channel_id'], $arr);
@@ -1740,6 +1727,7 @@ class Libzot {
// If this is a poll response, convert the obj_type to our (internal-only) "Answer" type
if (in_array($arr['obj_type'], ['Note', ACTIVITY_OBJ_COMMENT]) && $arr['title'] && (!$arr['body'])) {
$arr['obj_type'] = 'Answer';
+ $arr['item_hidden'] = 1;
}
}
@@ -2008,10 +1996,10 @@ class Libzot {
if ((is_array($stored)) && ($stored['id'] != $stored['parent'])
&& ($stored['author_xchan'] === $channel['channel_hash'])) {
- retain_item($stored['item']['parent']);
+ retain_item($stored['parent']);
}
- if ($relay && $item_id && $stored['item_blocked'] !== ITEM_MODERATED) {
+ if ($relay && $item_id && item_forwardable($stored)) {
logger('Invoking relay');
Master::Summon(['Notifier', 'relay', intval($item_id)]);
if (!empty($approval) && $approval['item_id']) {
diff --git a/Zotlabs/Lib/Mailer.php b/Zotlabs/Lib/Mailer.php
new file mode 100644
index 000000000..ca2d84d0d
--- /dev/null
+++ b/Zotlabs/Lib/Mailer.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Mailer class for sending emails from Hubzilla.
+ *
+ * SPDX-FileCopyrightText: 2024 Hubzilla Community
+ * SPDX-FileContributor: Harald Eilertsen
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+namespace Zotlabs\Lib;
+
+use App;
+
+/**
+ * A class for sending emails.
+ *
+ * Based on the previous `z_mail` function, but adaped and made more
+ * robust and usable as a class.
+ */
+class Mailer {
+
+ public function __construct(private array $params = []) {
+ }
+
+ public function deliver(): bool {
+
+ if(empty($this->params['fromEmail'])) {
+ $this->params['fromEmail'] = Config::Get('system','from_email');
+ if(empty($this->params['fromEmail'])) {
+ $this->params['fromEmail'] = 'Administrator@' . App::get_hostname();
+ }
+ }
+
+ if(empty($this->params['fromName'])) {
+ $this->params['fromName'] = Config::Get('system','from_email_name');
+ if(empty($this->params['fromName'])) {
+ $this->params['fromName'] = System::get_site_name();
+ }
+ }
+
+ if(empty($this->params['replyTo'])) {
+ $this->params['replyTo'] = Config::Get('system','reply_address');
+ if(empty($this->params['replyTo'])) {
+ $this->params['replyTo'] = 'noreply@' . App::get_hostname();
+ }
+ }
+
+ if (!isset($this->params['additionalMailHeader'])) {
+ $this->params['additionalMailHeader'] = '';
+ }
+
+ $this->params['sent'] = false;
+ $this->params['result'] = false;
+
+ /**
+ * @hooks email_send
+ * * \e params @see z_mail()
+ */
+ call_hooks('email_send', $this->params);
+
+ if($this->params['sent']) {
+ logger('notification: z_mail returns ' . (($this->params['result']) ? 'success' : 'failure'), LOGGER_DEBUG);
+ return $this->params['result'];
+ }
+
+ $fromName = email_header_encode(html_entity_decode($this->params['fromName'],ENT_QUOTES,'UTF-8'),'UTF-8');
+ $messageSubject = email_header_encode(html_entity_decode($this->params['messageSubject'],ENT_QUOTES,'UTF-8'),'UTF-8');
+
+ $messageHeader =
+ $this->params['additionalMailHeader'] .
+ "From: $fromName <{$this->params['fromEmail']}>" . PHP_EOL .
+ "Reply-To: $fromName <{$this->params['replyTo']}>" . PHP_EOL .
+ "Content-Type: text/plain; charset=UTF-8";
+
+ // send the message
+ $res = mail(
+ $this->params['toEmail'], // send to address
+ $messageSubject, // subject
+ $this->params['textVersion'],
+ $messageHeader // message headers
+ );
+ logger('notification: z_mail returns ' . (($res) ? 'success' : 'failure'), LOGGER_DEBUG);
+ return $res;
+ }
+}
diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php
index 90a3d3fc8..4b833f4b4 100644
--- a/Zotlabs/Lib/ThreadItem.php
+++ b/Zotlabs/Lib/ThreadItem.php
@@ -233,45 +233,6 @@ class ThreadItem {
$my_responses[$v] = ((isset($conv_responses[$v][$item['mid'] . '-m'])) ? 1 : 0);
}
-/*
-
- $like_count = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid']] : '');
- $like_list = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid'] . '-l'] : '');
- if (($like_list) && (count($like_list) > MAX_LIKERS)) {
- $like_list_part = array_slice($like_list, 0, MAX_LIKERS);
- array_push($like_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
- } else {
- $like_list_part = '';
- }
- $like_button_label = tt('Like','Likes',$like_count,'noun');
-
- $repeat_count = ((x($conv_responses['announce'],$item['mid'])) ? $conv_responses['announce'][$item['mid']] : '');
- $repeat_list = ((x($conv_responses['announce'],$item['mid'])) ? $conv_responses['announce'][$item['mid'] . '-l'] : '');
- if (($repeat_list) && (count($repeat_list) > MAX_LIKERS)) {
- $repeat_list_part = array_slice($repeat_list, 0, MAX_LIKERS);
- array_push($repeat_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#repeatModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
- } else {
- $repeat_list_part = '';
- }
- $repeat_button_label = tt('Repeat','Repeats',$repeat_count,'noun');
-
- $showdislike = '';
- if (feature_enabled($conv->get_profile_owner(),'dislike')) {
- $dislike_count = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid']] : '');
- $dislike_list = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid'] . '-l'] : '');
- $dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun');
- if (($dislike_list) && (count($dislike_list) > MAX_LIKERS)) {
- $dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS);
- array_push($dislike_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
- } else {
- $dislike_list_part = '';
- }
-
- $showdislike = ((x($conv_responses['dislike'],$item['mid'])) ? format_like($conv_responses['dislike'][$item['mid']],$conv_responses['dislike'][$item['mid'] . '-l'],'dislike',$item['mid']) : '');
- }
-
- $showlike = ((x($conv_responses['like'],$item['mid'])) ? format_like($conv_responses['like'][$item['mid']],$conv_responses['like'][$item['mid'] . '-l'],'like',$item['mid']) : '');
-*/
/*
* We should avoid doing this all the time, but it depends on the conversation mode
@@ -415,7 +376,6 @@ class ThreadItem {
'template' => $this->get_template(),
'mode' => $mode,
'item_type' => intval($item['item_type']),
- //'type' => implode("",array_slice(explode("/",$item['verb']),-1)),
'body' => $body['html'],
'tags' => $body['tags'],
'categories' => $body['categories'],
@@ -450,16 +410,15 @@ class ThreadItem {
'sparkle' => $sparkle,
'title' => $item['title'],
'title_tosource' => get_pconfig($conv->get_profile_owner(),'system','title_tosource'),
- //'ago' => relative_date($item['created']),
'app' => $item['app'],
'str_app' => sprintf( t('from %s'), $item['app']),
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'),
- 'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'),
- 'editedtime' => (($item['edited'] != $item['created']) ? sprintf( t('last edited: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r')) : ''),
- 'expiretime' => (($item['expires'] > NULL_DATE) ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')):''),
+ 'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created']),
+ 'editedtime' => (($item['edited'] != $item['created']) ? sprintf(t('Last edited %s'), relative_time($item['edited'])) : ''),
+ 'expiretime' => (($item['expires'] > NULL_DATE) ? sprintf(t('Expires %s'), relative_time($item['expires'])) : ''),
'lock' => $lock,
'locktype' => $locktype,
- 'delayed' => $item['item_delayed'],
+ 'delayed' => (($item['item_delayed']) ? sprintf(t('Published %s'), relative_time($item['created'])) : ''),
'privacy_warning' => $privacy_warning,
'verified' => $verified,
'unverified' => $unverified,
@@ -479,7 +438,7 @@ class ThreadItem {
'event' => $body['event'],
'has_tags' => $has_tags,
'reactions' => $this->reactions,
-// Item toolbar buttons
+ // Item toolbar buttons
'emojis' => (($this->is_toplevel() && $this->is_commentable() && $observer && feature_enabled($conv->get_profile_owner(),'emojis')) ? '1' : ''),
'like' => $like,
'dislike' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike : ''),
@@ -489,7 +448,7 @@ class ThreadItem {
'embed' => $embed,
'rawmid' => $item['mid'],
'plink' => get_plink($item),
- 'edpost' => $edpost, // ((feature_enabled($conv->get_profile_owner(),'edit_posts')) ? $edpost : ''),
+ 'edpost' => $edpost,
'star' => ((feature_enabled($conv->get_profile_owner(),'star_posts') && ($item['item_type'] == ITEM_TYPE_POST)) ? $star : ''),
'tagger' => ((feature_enabled($conv->get_profile_owner(),'commtag')) ? $tagger : ''),
'filer' => ((feature_enabled($conv->get_profile_owner(),'filing') && ($item['item_type'] == ITEM_TYPE_POST)) ? $filer : ''),
@@ -500,7 +459,7 @@ class ThreadItem {
'addtocal' => (($has_event) ? t('Add to Calendar') : ''),
'drop' => $drop,
'dropdown_extras' => $dropdown_extras,
-// end toolbar buttons
+ // end toolbar buttons
'unseen_comments' => $unseen_comments,
'comment_count' => $total_children,
'comment_count_txt' => $comment_count_txt,
@@ -508,30 +467,9 @@ class ThreadItem {
'markseen' => t('Mark all comments seen'),
'responses' => $responses,
'my_responses' => $my_responses,
- /*
- 'like_count' => $like_count,
- 'like_list' => $like_list,
- 'like_list_part' => $like_list_part,
- 'like_button_label' => $like_button_label,
- 'like_modal_title' => t('Likes','noun'),
-
- 'repeat_count' => $repeat_count,
- 'repeat_list' => $repeat_list,
- 'repeat_list_part' => $repeat_list_part,
- 'repeat_button_label' => $repeat_button_label,
- 'repeat_modal_title' => t('Repeats','noun'),
-
-
- 'dislike_modal_title' => t('Dislikes','noun'),
- 'dislike_count' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_count : ''),
- 'dislike_list' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list : ''),
- 'dislike_list_part' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list_part : ''),
- 'dislike_button_label' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_button_label : ''),
-*/
'modal_dismiss' => t('Close'),
- // 'showlike' => $showlike,
- // 'showdislike' => $showdislike,
'comment' => ($item['item_delayed'] ? '' : $this->get_comment_box()),
+ 'no_comment' => (($item['item_thread_top'] && $item['item_nocomment'])? t('Comments disabled') : ''),
'previewing' => ($conv->is_preview() ? true : false ),
'preview_lbl' => t('This is an unsaved preview'),
'wait' => t('Please wait'),
@@ -556,15 +494,7 @@ class ThreadItem {
$result['children'] = array();
$nb_children = count($children);
- $visible_comments = Config::Get('system','expanded_comments');
- if($visible_comments === false)
- $visible_comments = 3;
-
-// needed for scroll to comment from notification but needs more work
-// as we do not want to open all comments unless there is actually an #item_xx anchor
-// and the url fragment is not sent to the server.
-// if(in_array(\App::$module,['display','update_display']))
-// $visible_comments = 99999;
+ $visible_comments = Config::Get('system', 'expanded_comments', 3);
if(($this->get_display_mode() === 'normal') && ($nb_children > 0)) {
foreach($children as $child) {
@@ -876,7 +806,7 @@ class ThreadItem {
'$edatt' => t('Attach/Upload file'),
'$edurl' => t('Insert Link'),
'$edvideo' => t('Video'),
- '$preview' => t('Preview'), // ((feature_enabled($conv->get_profile_owner(),'preview')) ? t('Preview') : ''),
+ '$preview' => t('Preview'),
'$can_upload' => (perm_is_allowed($conv->get_profile_owner(),get_observer_hash(),'write_storage') && $conv->is_uploadable()),
'$feature_encrypt' => ((feature_enabled($conv->get_profile_owner(),'content_encrypt')) ? true : false),
'$encrypt' => t('Encrypt text'),
@@ -897,7 +827,7 @@ class ThreadItem {
}
/**
- * Check if we are a wall to wall item and set the relevant properties
+ * Check if we are a wall to wall or announce item and set the relevant properties
*/
protected function check_wall_to_wall() {
$conv = $this->get_conversation();
diff --git a/Zotlabs/Module/Admin/Accounts.php b/Zotlabs/Module/Admin/Accounts.php
index 6f7cb0311..108231d7d 100644
--- a/Zotlabs/Module/Admin/Accounts.php
+++ b/Zotlabs/Module/Admin/Accounts.php
@@ -6,133 +6,33 @@ use Zotlabs\Lib\Config;
class Accounts {
- /**
- * @brief Handle POST actions on accounts admin page.
- *
- * This function is called when on the admin user/account page the form was
- * submitted to handle multiple operations at once. If one of the icons next
- * to an entry are pressed the function admin_page_accounts() will handle this.
- *
- */
const MYP = 'ZAR'; // ZAR2x
const VERSION = '2.0.0';
- function post() {
+ /**
+ * Handle POST actions on accounts admin page.
+ */
+ public function post() {
- $pending = ( x($_POST, 'pending') ? $_POST['pending'] : array() );
- $users = ( x($_POST, 'user') ? $_POST['user'] : array() );
- $blocked = ( x($_POST, 'blocked') ? $_POST['blocked'] : array() );
+ $pending = x($_POST, 'pending') ? $_POST['pending'] : array();
check_form_security_token_redirectOnErr('/admin/accounts', 'admin_accounts');
- $isajax = is_ajax();
- $rc = 0;
-
- If (!is_site_admin()) {
- if ($isajax) {
- killme();
- exit;
- }
- goaway(z_root() . '/');
- }
-
- if ($isajax) {
- //$debug = print_r($_SESSION[self::MYP],true);
- $zarop = (x($_POST['zardo']) && preg_match('/^[ad]{1,1}$/', $_POST['zardo']) )
- ? $_POST['zardo'] : '';
- // zarat arrives with leading underscore _n
- $zarat = (x($_POST['zarat']) && preg_match('/^_{1,1}[0-9]{1,6}$/', $_POST['zarat']) )
- ? substr($_POST['zarat'],1) : '';
- $zarse = (x($_POST['zarse']) && preg_match('/^[0-9a-f]{8,8}$/', $_POST['zarse']) )
- ? hex2bin($_POST['zarse']) : '';
-
- if ($zarop && $zarat >= 0 && $zarse && $zarse == $_SESSION[self::MYP]['h'][$zarat]) {
-
- //
- if ($zarop == 'd') {
- $rd = q("UPDATE register SET reg_vital = 0 WHERE reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ",
- intval($_SESSION[self::MYP]['i'][$zarat]),
- dbesc($_SESSION[self::MYP]['h'][$zarat])
- );
- $rc = '×';
- }
- elseif ($zarop == 'a') {
- // approval, REGISTER_DENIED by user 0x0040, REGISTER_AGREED by user 0x0020 @Regate
- $rd = q("UPDATE register SET reg_flags = (reg_flags & ~ 16), "
- . " reg_vital = (CASE (reg_flags & ~ 48) WHEN 0 THEN 0 ELSE 1 END) "
- . " WHERE reg_vital = 1 AND reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ",
- intval($_SESSION[self::MYP]['i'][$zarat]),
- dbesc($_SESSION[self::MYP]['h'][$zarat])
- );
- $rc = 0;
- $rs = q("SELECT * from register WHERE reg_id = %d ",
- intval($_SESSION[self::MYP]['i'][$zarat])
- );
- if ($rs && ($rs[0]['reg_flags'] & ~ 48) == 0) {
- // create account
- $rc = 'ok'.$rs[0]['reg_id'];
- $ac = create_account_from_register($rs[0]);
- if ( $ac['success'] ) {
- $rc .= '✔';
-
- $auto_create = Config::Get('system','auto_channel_create',1);
-
- if($auto_create) {
- $reonar = json_decode($rs[0]['reg_stuff'], true);
- // prepare channel creation
- if($reonar['chan.name'])
- set_aconfig($ac['account']['account_id'], 'register', 'channel_name', $reonar['chan.name']);
-
- if($reonar['chan.did1'])
- set_aconfig($ac['account']['account_id'], 'register', 'channel_address', $reonar['chan.did1']);
-
- $permissions_role = Config::Get('system','default_permissions_role');
- if($permissions_role)
- set_aconfig($ac['account']['account_id'], 'register', 'permissions_role', $permissions_role);
-
- // create channel
- $new_channel = auto_channel_create($ac['account']['account_id']);
-
- if($new_channel['success']) {
- $rc .= ' c,ok' . $new_channel['channel']['channel_id'] . '✔';
- }
- else {
- $rc .= ' c ×';
- }
- }
-
-
- }
- } else {
- $rc='oh ×';
- }
- }
- echo json_encode(array('re' => $zarop, 'at' => '_' . $zarat, 'rc' => $rc));
- }
+ if (is_ajax()) {
+ $this->handle_ajax_request();
killme();
- exit;
}
// change to switch structure?
// account block/unblock button was submitted
if (x($_POST, 'page_accounts_block')) {
- for ($i = 0; $i < count($users); $i++) {
- // if account is blocked remove blocked bit-flag, otherwise add blocked bit-flag
- $op = ($blocked[$i]) ? '& ~' : '| ';
- q("UPDATE account SET account_flags = (account_flags $op%d) WHERE account_id = %d",
- intval(ACCOUNT_BLOCKED),
- intval($users[$i])
- );
- }
- notice( sprintf( tt("%s account blocked/unblocked", "%s account blocked/unblocked", count($users)), count($users)) );
+ $this->block_unblock_accounts();
}
+
// account delete button was submitted
if (x($_POST, 'page_accounts_delete')) {
- foreach ($users as $uid){
- account_remove($uid, true, false);
- }
- notice( sprintf( tt("%s account deleted", "%s accounts deleted", count($users)), count($users)) );
+ $this->delete_accounts();
}
// registration approved button was submitted
if (x($_POST, 'page_accounts_approve')) {
@@ -351,5 +251,143 @@ class Accounts {
return $o;
}
+ private function handle_ajax_request(): void {
+ //$debug = print_r($_SESSION[self::MYP],true);
+ $zarop = (x($_POST['zardo']) && preg_match('/^[ad]{1,1}$/', $_POST['zardo']) )
+ ? $_POST['zardo'] : '';
+ // zarat arrives with leading underscore _n
+ $zarat = (x($_POST['zarat']) && preg_match('/^_{1,1}[0-9]{1,6}$/', $_POST['zarat']) )
+ ? substr($_POST['zarat'],1) : '';
+ $zarse = (x($_POST['zarse']) && preg_match('/^[0-9a-f]{8,8}$/', $_POST['zarse']) )
+ ? hex2bin($_POST['zarse']) : '';
+
+ if ($zarop && $zarat >= 0 && $zarse && $zarse == $_SESSION[self::MYP]['h'][$zarat]) {
+
+ //
+ if ($zarop == 'd') {
+ $rd = q("UPDATE register SET reg_vital = 0 WHERE reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ",
+ intval($_SESSION[self::MYP]['i'][$zarat]),
+ dbesc($_SESSION[self::MYP]['h'][$zarat])
+ );
+ $rc = '×';
+ }
+ elseif ($zarop == 'a') {
+ // approval, REGISTER_DENIED by user 0x0040, REGISTER_AGREED by user 0x0020 @Regate
+ $rd = q("UPDATE register SET reg_flags = (reg_flags & ~ 16), "
+ . " reg_vital = (CASE (reg_flags & ~ 48) WHEN 0 THEN 0 ELSE 1 END) "
+ . " WHERE reg_vital = 1 AND reg_id = %d AND SUBSTR(reg_hash,1,4) = '%s' ",
+ intval($_SESSION[self::MYP]['i'][$zarat]),
+ dbesc($_SESSION[self::MYP]['h'][$zarat])
+ );
+ $rc = 0;
+ $rs = q("SELECT * from register WHERE reg_id = %d ",
+ intval($_SESSION[self::MYP]['i'][$zarat])
+ );
+ if ($rs && ($rs[0]['reg_flags'] & ~ 48) == 0) {
+ // create account
+ $rc = 'ok'.$rs[0]['reg_id'];
+ $ac = create_account_from_register($rs[0]);
+ if ( $ac['success'] ) {
+ $rc .= '✔';
+
+ $auto_create = Config::Get('system','auto_channel_create',1);
+
+ if($auto_create) {
+ $reonar = json_decode($rs[0]['reg_stuff'], true);
+ // prepare channel creation
+ if($reonar['chan.name'])
+ set_aconfig($ac['account']['account_id'], 'register', 'channel_name', $reonar['chan.name']);
+
+ if($reonar['chan.did1'])
+ set_aconfig($ac['account']['account_id'], 'register', 'channel_address', $reonar['chan.did1']);
+
+ $permissions_role = Config::Get('system','default_permissions_role');
+ if($permissions_role)
+ set_aconfig($ac['account']['account_id'], 'register', 'permissions_role', $permissions_role);
+
+ // create channel
+ $new_channel = auto_channel_create($ac['account']['account_id']);
+
+ if($new_channel['success']) {
+ $rc .= ' c,ok' . $new_channel['channel']['channel_id'] . '✔';
+ }
+ else {
+ $rc .= ' c ×';
+ }
+ }
+
+
+ }
+ } else {
+ $rc='oh ×';
+ }
+ }
+ echo json_encode(array('re' => $zarop, 'at' => '_' . $zarat, 'rc' => $rc));
+ }
+ }
+
+ /**
+ * Block or unblock accounts given by the `user` and `blocked` POST params.
+ *
+ * The post params `user` and `blocked` must be present and arrays of equal
+ * lengths. The `user` array should contain account id's or the accounts to
+ * process, and the `blocked` array holds a corresponding boolean value to
+ * indicate that the account at the same offset in the `user` array is or is
+ * not blocked.
+ *
+ * An account that is _not_ blocked will be blocked, and accounts that _are_
+ * blocked will be unblocked.
+ *
+ * @SuppressWarnings(PHPMD.ShortVariable)
+ */
+ private function block_unblock_accounts(): void {
+ if (!isset($_POST['user']) || !isset($_POST['blocked'])) {
+ return;
+ }
+
+ $users = $_POST['user'];
+ $blocked = $_POST['blocked'];
+
+ if (!is_array($users) || !is_array($blocked)) {
+ return;
+ }
+
+ foreach($users as $i => $id) {
+ // if account is blocked remove blocked bit-flag, otherwise add blocked bit-flag
+ $op = $blocked[$i] ? '& ~' : '| ';
+
+ q("UPDATE account SET account_flags = (account_flags $op%d) WHERE account_id = %d",
+ intval(ACCOUNT_BLOCKED),
+ intval($id)
+ );
+ }
+
+ $count = count($users);
+ $fmt = tt("%s account blocked/unblocked", "%s account blocked/unblocked", $count);
+ notice(sprintf($fmt, $count));
+ }
+
+ /**
+ * Delete multiple accounts given by the `user` POST param.
+ */
+ private function delete_accounts(): void {
+ if (!isset($_POST['user'])) {
+ return;
+ }
+
+ $users = $_POST['user'];
+
+ if (!is_array($users)) {
+ return;
+ }
+
+ foreach ($users as $uid){
+ account_remove($uid, true, false);
+ }
+
+ $count = count($users);
+ $fmt = tt("%s account deleted", "%s accounts deleted", $count);
+ notice(sprintf($fmt, $count));
+ }
}
diff --git a/Zotlabs/Module/Conversation.php b/Zotlabs/Module/Conversation.php
index c3e6ae5ec..6ceba69f2 100644
--- a/Zotlabs/Module/Conversation.php
+++ b/Zotlabs/Module/Conversation.php
@@ -36,8 +36,7 @@ class Conversation extends Controller {
// 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),
+ $r = q("select parent_mid from item where uuid = '%s' $item_normal order by item_wall desc limit 1",
dbesc($item_id)
);
diff --git a/Zotlabs/Module/Dreport.php b/Zotlabs/Module/Dreport.php
index 5db607545..d1ffb8027 100644
--- a/Zotlabs/Module/Dreport.php
+++ b/Zotlabs/Module/Dreport.php
@@ -19,7 +19,7 @@ class Dreport extends \Zotlabs\Web\Controller {
$table = 'push';
if($mid) {
- $i = q("select id from item where mid = '%s' and uid = %d and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ",
+ $i = q("select * from item where mid = '%s' and uid = %d and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ",
dbesc($mid),
intval($channel['channel_id']),
dbesc($channel['channel_hash']),
@@ -27,6 +27,12 @@ class Dreport extends \Zotlabs\Web\Controller {
);
if($i) {
\Zotlabs\Daemon\Master::Summon([ 'Notifier', 'edit_post', $i[0]['id'] ]);
+
+ $relatedItem = find_related($i[0]);
+ if (isset($relatedItem['id'])) {
+ \Zotlabs\Daemon\Master::Summon([ 'Notifier', 'edit_post', $relatedItem['id'] ]);
+ }
+
}
}
sleep(3);
diff --git a/Zotlabs/Module/Editpost.php b/Zotlabs/Module/Editpost.php
index 6f524cdb8..678ceb207 100644
--- a/Zotlabs/Module/Editpost.php
+++ b/Zotlabs/Module/Editpost.php
@@ -86,6 +86,7 @@ class Editpost extends \Zotlabs\Web\Controller {
'bbco_autocomplete'=> 'bbcode',
'return_path' => 'hq',
'button' => t('Submit'),
+ 'disable_comments' => (($itm[0]['item_thread_top']) ? false : true),
'hide_voting' => true,
'hide_future' => true,
'hide_location' => true,
diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php
index 8ded7c1d7..f542e44ff 100644
--- a/Zotlabs/Module/Item.php
+++ b/Zotlabs/Module/Item.php
@@ -53,22 +53,21 @@ class Item extends Controller {
if (argc() > 1 && argv(1) !== 'drop') {
- $x = q("select uid, item_wall, llink, mid, uuid from item where mid = '%s' or mid = '%s' or uuid = '%s'",
- dbesc(z_root() . '/item/' . argv(1)),
- dbesc(z_root() . '/activity/' . argv(1)),
+ $x = q("select uid, item_wall, llink, uuid from item where uuid = '%s' order by item_wall desc",
dbesc(argv(1))
);
+
if ($x) {
- foreach ($x as $xv) {
- if (intval($xv['item_wall'])) {
- $c = channelx_by_n($xv['uid']);
- if ($c) {
- goaway(z_root() . '/channel/' . $c['channel_address'] . '?mid=' . $xv['uuid']);
- }
+ if ($x[0]['item_wall']) {
+ $c = channelx_by_n($x[0]['uid']);
+ if ($c) {
+ goaway(z_root() . '/channel/' . $c['channel_address'] . '?mid=' . $x[0]['uuid']);
}
}
+
goaway($x[0]['llink']);
}
+
http_status_exit(404, 'Not found');
}
@@ -101,7 +100,6 @@ class Item extends Controller {
$item_deleted = false;
$item_hidden = false;
$item_unpublished = false;
- $item_delayed = false;
$item_pending_remove = false;
$item_blocked = false;
@@ -179,6 +177,7 @@ class Item extends Controller {
$categories = ((x($_REQUEST, 'category')) ? escape_tags($_REQUEST['category']) : '');
$webpage = ((x($_REQUEST, 'webpage')) ? intval($_REQUEST['webpage']) : 0);
$item_obscured = ((x($_REQUEST, 'obscured')) ? intval($_REQUEST['obscured']) : 0);
+ $item_delayed = ((x($_REQUEST, 'delayed')) ? intval($_REQUEST['delayed']) : 0);
$pagetitle = ((x($_REQUEST, 'pagetitle')) ? escape_tags($_REQUEST['pagetitle']) : '');
$layout_mid = ((x($_REQUEST, 'layout_mid')) ? escape_tags($_REQUEST['layout_mid']) : '');
$plink = ((x($_REQUEST, 'permalink')) ? escape_tags($_REQUEST['permalink']) : '');
@@ -208,7 +207,6 @@ class Item extends Controller {
$expires = NULL_DATE;
- $comments_closed = NULL_DATE;
$route = '';
$parent_item = null;
@@ -455,7 +453,7 @@ class Item extends Controller {
$title = escape_tags(trim($_REQUEST['title']));
$summary = escape_tags(trim($_REQUEST['summary']));
$body = trim($_REQUEST['body']);
- $item_flags = $orig_post['item_flags'];
+ $item_flags = $orig_post['item_flags'];
$item_origin = $orig_post['item_origin'];
$item_unseen = $orig_post['item_unseen'];
$item_starred = $orig_post['item_starred'];
@@ -469,7 +467,7 @@ class Item extends Controller {
$item_mentionsme = $orig_post['item_mentionsme'];
$item_nocomment = $orig_post['item_nocomment'];
$item_obscured = $orig_post['item_obscured'];
- $item_verified = $orig_post['item_verified'];
+ $item_verified = $orig_post['item_verified'];
$item_retained = $orig_post['item_retained'];
$item_rss = $orig_post['item_rss'];
$item_deleted = $orig_post['item_deleted'];
@@ -794,6 +792,7 @@ class Item extends Controller {
$item_origin = (($origin) ? 1 : 0);
$item_consensus = (($consensus) ? 1 : 0);
$item_nocomment = (($nocomment) ? 1 : 0);
+ $comments_closed = (($nocomment) ? $comments_closed : NULL_DATE);
// determine if this is a wall post
@@ -1246,8 +1245,6 @@ class Item extends Controller {
if ((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) {
- require_once('include/items.php');
-
$i = q("select * from item where id = %d limit 1",
intval(argv(2))
);
diff --git a/Zotlabs/Module/Owa.php b/Zotlabs/Module/Owa.php
index 85467d4f4..21082e166 100644
--- a/Zotlabs/Module/Owa.php
+++ b/Zotlabs/Module/Owa.php
@@ -18,96 +18,95 @@ use Zotlabs\Web\Controller;
class Owa extends Controller {
- function init() {
+ public function init(): void
+ {
$ret = [ 'success' => false ];
- if (array_key_exists('REDIRECT_REMOTE_USER',$_SERVER) && (! array_key_exists('HTTP_AUTHORIZATION',$_SERVER))) {
- $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['REDIRECT_REMOTE_USER'];
+ if (!$this->validateAuthorizationHeader()) {
+ $this->error('Missing or invalid authorization header.');
}
- if (array_key_exists('HTTP_AUTHORIZATION',$_SERVER) && substr(trim($_SERVER['HTTP_AUTHORIZATION']),0,9) === 'Signature') {
- $sigblock = HTTPSig::parse_sigheader($_SERVER['HTTP_AUTHORIZATION']);
- if ($sigblock) {
- $keyId = $sigblock['keyId'];
- $parsed = parse_url($keyId);
- if (str_starts_with($parsed['scheme'],'http')) {
- unset($parsed['fragment']);
- unset($parsed['query']);
- $keyId = unparse_url($parsed);
- }
- else {
- $keyId = str_replace('acct:', '', $keyId);
+ $sigblock = HTTPSig::parse_sigheader($_SERVER['HTTP_AUTHORIZATION']);
+ if ($sigblock) {
+ $keyId = $sigblock['keyId'];
+ $parsed = parse_url($keyId);
+ if (str_starts_with($parsed['scheme'],'http')) {
+ unset($parsed['fragment']);
+ unset($parsed['query']);
+ $keyId = unparse_url($parsed);
+ }
+ else {
+ $keyId = str_replace('acct:', '', $keyId);
+ }
+ if ($keyId) {
+ $r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
+ WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s')
+ AND hubloc_deleted = 0 AND xchan_pubkey != ''
+ ORDER BY hubloc_id DESC",
+ dbesc($keyId),
+ dbesc($keyId),
+ dbesc($keyId)
+ );
+ if (! $r) {
+ $found = discover_by_webbie($keyId);
+ logger('found = ' . print_r($found, true));
+ if ($found) {
+ $r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
+ WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s') AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC ",
+ dbesc($keyId),
+ dbesc($keyId),
+ dbesc($keyId)
+ );
+ }
}
- if ($keyId) {
- $r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
- WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s')
- AND hubloc_deleted = 0 AND xchan_pubkey != ''
- ORDER BY hubloc_id DESC",
- dbesc($keyId),
- dbesc($keyId),
- dbesc($keyId)
- );
- if (! $r) {
+
+ if ($r) {
+ foreach ($r as $hubloc) {
+ $verified = HTTPSig::verify(file_get_contents('php://input'), $hubloc['xchan_pubkey']);
+ if ($verified && $verified['header_signed'] && $verified['header_valid'] && ($verified['content_valid'] || (! $verified['content_signed']))) {
+ logger('OWA header: ' . print_r($verified,true),LOGGER_DATA);
+ logger('OWA success: ' . $hubloc['hubloc_id_url'],LOGGER_DATA);
+ $ret['success'] = true;
+ $token = random_string(32);
+ Verify::create('owt',0,$token,$hubloc['hubloc_id_url']);
+ $result = '';
+ openssl_public_encrypt($token,$result,$hubloc['xchan_pubkey']);
+ $ret['encrypted_token'] = base64url_encode($result);
+ break;
+ } else {
+ logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_id_url']);
+ }
+ }
+
+ if (!$ret['success']) {
+
+ // Possible a reinstall?
+ // In this case we probably already have an old hubloc
+ // but not the new one yet.
+
$found = discover_by_webbie($keyId);
- logger('found = ' . print_r($found, true));
+
if ($found) {
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
- WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s') AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC ",
- dbesc($keyId),
- dbesc($keyId),
+ WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s') AND hubloc_deleted = 0 ORDER BY hubloc_id DESC LIMIT 1",
+ dbesc(str_replace('acct:', '', $keyId)),
dbesc($keyId)
);
- }
- }
-
- if ($r) {
- foreach ($r as $hubloc) {
- $verified = HTTPSig::verify(file_get_contents('php://input'), $hubloc['xchan_pubkey']);
- if ($verified && $verified['header_signed'] && $verified['header_valid'] && ($verified['content_valid'] || (! $verified['content_signed']))) {
- logger('OWA header: ' . print_r($verified,true),LOGGER_DATA);
- logger('OWA success: ' . $hubloc['hubloc_id_url'],LOGGER_DATA);
- $ret['success'] = true;
- $token = random_string(32);
- Verify::create('owt',0,$token,$hubloc['hubloc_id_url']);
- $result = '';
- openssl_public_encrypt($token,$result,$hubloc['xchan_pubkey']);
- $ret['encrypted_token'] = base64url_encode($result);
- break;
- } else {
- logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_id_url']);
- }
- }
- if (!$ret['success']) {
-
- // Possible a reinstall?
- // In this case we probably already have an old hubloc
- // but not the new one yet.
-
- $found = discover_by_webbie($keyId);
-
- if ($found) {
- $r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
- WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s') AND hubloc_deleted = 0 ORDER BY hubloc_id DESC LIMIT 1",
- dbesc(str_replace('acct:', '', $keyId)),
- dbesc($keyId)
- );
-
- if ($r) {
- $verified = HTTPSig::verify(file_get_contents('php://input'), $r[0]['xchan_pubkey']);
- if ($verified && $verified['header_signed'] && $verified['header_valid'] && ($verified['content_valid'] || (! $verified['content_signed']))) {
- logger('OWA header: ' . print_r($verified,true), LOGGER_DATA);
- logger('OWA success: ' . $r[0]['hubloc_id_url'], LOGGER_DATA);
- $ret['success'] = true;
- $token = random_string(32);
- Verify::create('owt', 0, $token, $r[0]['hubloc_id_url']);
- $result = '';
- openssl_public_encrypt($token, $result, $r[0]['xchan_pubkey']);
- $ret['encrypted_token'] = base64url_encode($result);
- } else {
- logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_id_url']);
- }
+ if ($r) {
+ $verified = HTTPSig::verify(file_get_contents('php://input'), $r[0]['xchan_pubkey']);
+ if ($verified && $verified['header_signed'] && $verified['header_valid'] && ($verified['content_valid'] || (! $verified['content_signed']))) {
+ logger('OWA header: ' . print_r($verified,true), LOGGER_DATA);
+ logger('OWA success: ' . $r[0]['hubloc_id_url'], LOGGER_DATA);
+ $ret['success'] = true;
+ $token = random_string(32);
+ Verify::create('owt', 0, $token, $r[0]['hubloc_id_url']);
+ $result = '';
+ openssl_public_encrypt($token, $result, $r[0]['xchan_pubkey']);
+ $ret['encrypted_token'] = base64url_encode($result);
+ } else {
+ logger('OWA fail: ' . $hubloc['hubloc_id'] . ' ' . $hubloc['hubloc_id_url']);
}
}
}
@@ -118,4 +117,33 @@ class Owa extends Controller {
json_return_and_die($ret,'application/x-zot+json');
}
+
+ private function validateAuthorizationHeader(): bool
+ {
+ if (!empty($_SERVER['HTTP_AUTHORIZATION'])) {
+ $auth = trim($_SERVER['HTTP_AUTHORIZATION']);
+ } else if (!empty($_SERVER['REDIRECT_REMOTE_USER'])) {
+ $auth = trim($_SERVER['REDIRECT_REMOTE_USER']);
+ } else {
+ return false;
+ }
+
+ return strncmp($auth, 'Signature', 9) === 0;
+ }
+
+ /**
+ * Terminates the request, and return a json error response.
+ *
+ * @Note This function does not return!
+ *
+ * @param string $msg The error message for the response.
+ */
+ private function error(string $msg): void {
+ $ret = [
+ 'success' => false,
+ 'message' => $msg
+ ];
+
+ json_return_and_die($ret,'application/x-zot+json');
+ }
}
diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php
index 6d8edf4d8..234e73792 100644
--- a/Zotlabs/Module/Pubstream.php
+++ b/Zotlabs/Module/Pubstream.php
@@ -202,11 +202,9 @@ class Pubstream extends \Zotlabs\Web\Controller {
if($mid) {
$r = q("SELECT parent AS item_id FROM item
left join abook on item.author_xchan = abook.abook_xchan
- left join xchan on item.author_xchan = xchan.xchan_hash
WHERE item.$identifier = '%s' and item.item_private = 0
$uids $site_firehose_sql
$item_normal
- and xchan.xchan_censored = 0
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra $net_query2",
dbesc($mid)
@@ -216,11 +214,9 @@ class Pubstream extends \Zotlabs\Web\Controller {
// Fetch a page full of parent items for this page
$r = dbq("SELECT parent AS item_id FROM item
left join abook on ( item.author_xchan = abook.abook_xchan $abook_uids )
- left join xchan on item.author_xchan = xchan.xchan_hash
WHERE item.item_private = 0 $thread_top
$uids $site_firehose_sql
$item_normal
- and xchan.xchan_censored = 0
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra $net_query2
ORDER BY $ordering DESC $pager_sql "
@@ -231,10 +227,8 @@ class Pubstream extends \Zotlabs\Web\Controller {
if($mid) {
$r = q("SELECT parent AS item_id FROM item
left join abook on item.author_xchan = abook.abook_xchan
- left join xchan on item.author_xchan = xchan.xchan_hash
WHERE item.$identifier = '%s' and item.item_private = 0
$uids $site_firehose_sql $item_normal_update $simple_update
- and xchan.xchan_censored = 0
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra $net_query2",
dbesc($mid)
@@ -243,11 +237,9 @@ class Pubstream extends \Zotlabs\Web\Controller {
else {
$r = dbq("SELECT parent AS item_id FROM item
left join abook on item.author_xchan = abook.abook_xchan
- left join xchan on item.author_xchan = xchan.xchan_hash
WHERE item.item_private = 0 $thread_top
$uids $site_firehose_sql $item_normal_update
$simple_update
- and xchan.xchan_censored = 0
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra $net_query2"
);
diff --git a/Zotlabs/Module/Sse.php b/Zotlabs/Module/Sse.php
index fda2f2be4..673457db1 100644
--- a/Zotlabs/Module/Sse.php
+++ b/Zotlabs/Module/Sse.php
@@ -207,10 +207,9 @@ class Sse extends Controller {
if ($result) {
XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
- json_return_and_die($result);
}
- killme();
+ json_return_and_die($result);
}
diff --git a/Zotlabs/Module/Sse_bs.php b/Zotlabs/Module/Sse_bs.php
index 09c4ed614..5292abfaa 100644
--- a/Zotlabs/Module/Sse_bs.php
+++ b/Zotlabs/Module/Sse_bs.php
@@ -22,7 +22,6 @@ class Sse_bs extends Controller {
public static $xchans;
function init() {
-
self::$uid = local_channel();
self::$ob_hash = get_observer_hash();
self::$sse_id = false;
@@ -43,8 +42,9 @@ class Sse_bs extends Controller {
self::$offset = 0;
self::$xchans = '';
- if(isset($_REQUEST['sse_rmids']))
- self::mark_read($_REQUEST['sse_rmids']);
+ if (isset($_REQUEST['sse_rmids'])) {
+ self::mark_read(explode(',', $_REQUEST['sse_rmids']));
+ }
if(!empty($_REQUEST['nquery']) && $_REQUEST['nquery'] !== '%') {
$nquery = $_REQUEST['nquery'];
@@ -207,7 +207,7 @@ class Sse_bs extends Controller {
$item_normal
$sql_extra
$sql_extra2
- ORDER BY created DESC LIMIT $limit OFFSET $offset",
+ ORDER BY created DESC, received DESC LIMIT $limit OFFSET $offset",
intval(self::$uid),
dbescdate($_SESSION['sse_loadtime']),
dbesc(self::$ob_hash)
@@ -290,7 +290,7 @@ class Sse_bs extends Controller {
$item_normal
$sql_extra
$sql_extra2
- ORDER BY created DESC LIMIT $limit OFFSET $offset",
+ ORDER BY created DESC, received DESC LIMIT $limit OFFSET $offset",
intval(self::$uid),
dbescdate($_SESSION['sse_loadtime']),
dbesc(self::$ob_hash)
@@ -373,7 +373,7 @@ class Sse_bs extends Controller {
$item_normal
$sql_extra
$sql_extra2
- ORDER BY created DESC LIMIT $limit OFFSET $offset",
+ ORDER BY created DESC, received DESC LIMIT $limit OFFSET $offset",
intval(self::$uid),
dbescdate($_SESSION['sse_loadtime']),
dbesc(self::$ob_hash)
@@ -481,7 +481,7 @@ class Sse_bs extends Controller {
$sql_extra
$sql_extra2
$sql_extra3
- ORDER BY created DESC LIMIT $limit OFFSET $offset",
+ ORDER BY created DESC, received DESC LIMIT $limit OFFSET $offset",
dbescdate($_SESSION['sse_loadtime']),
dbesc(self::$ob_hash),
dbescdate($_SESSION['last_login_date'] ?? $_SESSION['static_loadtime'])
@@ -502,13 +502,15 @@ class Sse_bs extends Controller {
}
}
- $r = q("SELECT id FROM item
+ $r = q("SELECT id, body FROM item
WHERE true $uids
+ AND created <= '%s'
AND created > '%s'
$item_normal
$sql_extra
$sql_extra3
AND author_xchan != '%s' LIMIT 100",
+ dbescdate($_SESSION['sse_loadtime']),
dbescdate($_SESSION['last_login_date'] ?? $_SESSION['static_loadtime']),
dbesc(self::$ob_hash)
);
@@ -677,7 +679,7 @@ class Sse_bs extends Controller {
AND author_xchan != '%s'
AND item_unseen = 1
$item_normal
- ORDER BY created DESC",
+ ORDER BY created DESC, received DESC",
dbesc(ACTIVITY_POST),
intval(self::$uid),
dbesc(self::$ob_hash)
diff --git a/Zotlabs/Web/WebServer.php b/Zotlabs/Web/WebServer.php
index 19f14ee8a..d59effc88 100644
--- a/Zotlabs/Web/WebServer.php
+++ b/Zotlabs/Web/WebServer.php
@@ -61,7 +61,7 @@ class WebServer {
if (x($_GET,'zid') && $installed) {
\App::$query_string = strip_zids(\App::$query_string);
if(! local_channel()) {
- if (!isset($_SESSION['my_address']) || $_SESSION['my_address'] != $_GET['zid']) {
+ if (!isset($_SESSION['my_address'])) {
$_SESSION['my_address'] = Text::escape_tags($_GET['zid']);
$_SESSION['authenticated'] = 0;
}