aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG5
-rw-r--r--Zotlabs/Daemon/Addon.php1
-rw-r--r--Zotlabs/Daemon/Cache_embeds.php4
-rw-r--r--Zotlabs/Daemon/Cache_query.php4
-rw-r--r--Zotlabs/Daemon/Cli_suggest.php1
-rw-r--r--Zotlabs/Daemon/Convo.php31
-rw-r--r--Zotlabs/Daemon/Cron.php30
-rw-r--r--Zotlabs/Daemon/Cron_daily.php2
-rw-r--r--Zotlabs/Daemon/Cron_weekly.php11
-rw-r--r--Zotlabs/Daemon/Deliver.php2
-rw-r--r--Zotlabs/Daemon/Deliver_hooks.php6
-rw-r--r--Zotlabs/Daemon/Directory.php2
-rw-r--r--Zotlabs/Daemon/Expire.php2
-rw-r--r--Zotlabs/Daemon/Externals.php2
-rw-r--r--Zotlabs/Daemon/Importdoc.php2
-rw-r--r--Zotlabs/Daemon/Master.php12
-rw-r--r--Zotlabs/Daemon/Notifier.php2
-rw-r--r--Zotlabs/Daemon/Poller.php30
-rw-r--r--Zotlabs/Daemon/Queue.php2
-rw-r--r--Zotlabs/Daemon/Thumbnail.php2
-rw-r--r--Zotlabs/Lib/Activity.php8
-rw-r--r--Zotlabs/Lib/Libsync.php16
-rw-r--r--Zotlabs/Lib/Libzot.php6
-rw-r--r--Zotlabs/Lib/QueueWorker.php357
-rw-r--r--Zotlabs/Lib/ThreadItem.php8
-rw-r--r--Zotlabs/Module/Admin/Queueworker.php121
-rw-r--r--Zotlabs/Module/Admin/Site.php14
-rw-r--r--Zotlabs/Module/Cloud.php9
-rw-r--r--Zotlabs/Module/Import.php2
-rw-r--r--Zotlabs/Module/Item.php11
-rw-r--r--Zotlabs/Module/Pdledit.php37
-rw-r--r--Zotlabs/Module/Pdledit_gui.php51
-rw-r--r--Zotlabs/Module/Pubstream.php44
-rw-r--r--Zotlabs/Module/Settings/Account.php57
-rw-r--r--Zotlabs/Module/Sharedwithme.php51
-rw-r--r--Zotlabs/Module/Sse.php32
-rw-r--r--Zotlabs/Module/Sse_bs.php36
-rw-r--r--Zotlabs/Module/Vote.php6
-rw-r--r--Zotlabs/Update/_1254.php55
-rw-r--r--Zotlabs/Update/_1255.php29
-rw-r--r--Zotlabs/Web/SessionRedis.php11
-rw-r--r--Zotlabs/Widget/Admin.php1
-rw-r--r--Zotlabs/Widget/Categories.php13
-rw-r--r--Zotlabs/Widget/Channel_activities.php4
-rw-r--r--Zotlabs/Widget/Messages.php16
-rw-r--r--Zotlabs/Widget/Pubtagcloud.php17
-rw-r--r--boot.php37
-rw-r--r--include/attach.php18
-rw-r--r--include/auth.php3
-rw-r--r--include/event.php6
-rw-r--r--include/html2bbcode.php1
-rw-r--r--include/hubloc.php12
-rw-r--r--include/items.php44
-rw-r--r--include/network.php23
-rw-r--r--include/photos.php4
-rw-r--r--include/plugin.php19
-rw-r--r--include/taxonomy.php92
-rw-r--r--include/text.php9
-rw-r--r--install/schema_mysql.sql16
-rw-r--r--install/schema_postgres.sql15
-rw-r--r--view/css/bootstrap-red.css4
-rw-r--r--view/css/conversation.css7
-rw-r--r--view/fr/invite.formal.tpl2
-rw-r--r--view/js/mod_cloud.js3
-rw-r--r--view/theme/redbasic/css/style.css6
-rw-r--r--view/tpl/admin_site.tpl8
-rw-r--r--view/tpl/settings_account.tpl3
67 files changed, 1147 insertions, 350 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 9bdfaa8a0..be5a3bbce 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,8 @@
+Hubzilla 7.8.7 (2022-12-03)
+ - Fix regression when adding feed contacts
+ - Fix regression new channel calendar event not created
+
+
Hubzilla 7.8.6 (2022-11-14)
- Fix typo in boot.php
diff --git a/Zotlabs/Daemon/Addon.php b/Zotlabs/Daemon/Addon.php
index c6778750d..126e11cf6 100644
--- a/Zotlabs/Daemon/Addon.php
+++ b/Zotlabs/Daemon/Addon.php
@@ -7,6 +7,7 @@ class Addon {
static public function run($argc, $argv) {
call_hooks('daemon_addon', $argv);
+ return;
}
diff --git a/Zotlabs/Daemon/Cache_embeds.php b/Zotlabs/Daemon/Cache_embeds.php
index 9e5b8d2bb..d5adfcc59 100644
--- a/Zotlabs/Daemon/Cache_embeds.php
+++ b/Zotlabs/Daemon/Cache_embeds.php
@@ -19,8 +19,10 @@ class Cache_embeds {
$item = $c[0];
// bbcode conversion by default processes embeds that aren't already cached.
- // Ignore the returned html output.
+ // Ignore the returned html output.
bbcode($item['body']);
+
+ return;
}
}
diff --git a/Zotlabs/Daemon/Cache_query.php b/Zotlabs/Daemon/Cache_query.php
index 5f92ae6d0..cd9597e9a 100644
--- a/Zotlabs/Daemon/Cache_query.php
+++ b/Zotlabs/Daemon/Cache_query.php
@@ -24,7 +24,7 @@ class Cache_query {
array_shift($argv);
array_shift($argv);
-
+
$arr = json_decode(base64_decode($argv[0]), true);
$r = call_user_func_array('q', $arr);
@@ -32,5 +32,7 @@ class Cache_query {
Cache::set($key, serialize($r));
del_config('procid', $key);
+
+ return;
}
}
diff --git a/Zotlabs/Daemon/Cli_suggest.php b/Zotlabs/Daemon/Cli_suggest.php
index 5dced462d..028228cb0 100644
--- a/Zotlabs/Daemon/Cli_suggest.php
+++ b/Zotlabs/Daemon/Cli_suggest.php
@@ -9,6 +9,7 @@ class Cli_suggest {
static public function run($argc,$argv) {
update_suggestions();
+ return;
}
}
diff --git a/Zotlabs/Daemon/Convo.php b/Zotlabs/Daemon/Convo.php
index 940216b2c..d1a7e4f4d 100644
--- a/Zotlabs/Daemon/Convo.php
+++ b/Zotlabs/Daemon/Convo.php
@@ -30,6 +30,7 @@ class Convo {
intval($channel_id),
dbesc($contact_hash)
);
+
if (!$r) {
return;
}
@@ -40,19 +41,25 @@ class Convo {
$messages = $obj->get();
- if ($messages) {
- foreach ($messages as $message) {
- if (is_string($message)) {
- $message = Activity::fetch($message, $channel);
- }
- // set client flag because comments will probably just be objects and not full blown activities
- // and that lets us use implied_create
- $AS = new ActivityStreams($message);
- if ($AS->is_valid() && is_array($AS->obj)) {
- $item = Activity::decode_note($AS);
- Activity::store($channel, $contact['abook_xchan'], $AS, $item);
- }
+ if (!$messages) {
+ return;
+ }
+
+ foreach ($messages as $message) {
+ if (is_string($message)) {
+ $message = Activity::fetch($message, $channel);
+ }
+
+ // set client flag because comments will probably just be objects and not full blown activities
+ // and that lets us use implied_create
+ $AS = new ActivityStreams($message);
+ if ($AS->is_valid() && is_array($AS->obj)) {
+ $item = Activity::decode_note($AS);
+ Activity::store($channel, $contact['abook_xchan'], $AS, $item);
}
}
+
+ return;
+
}
}
diff --git a/Zotlabs/Daemon/Cron.php b/Zotlabs/Daemon/Cron.php
index 6629491de..640f06102 100644
--- a/Zotlabs/Daemon/Cron.php
+++ b/Zotlabs/Daemon/Cron.php
@@ -19,6 +19,7 @@ class Cron {
}
}
+/*
// Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
$lockfile = 'store/[data]/cron';
if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
@@ -30,6 +31,7 @@ class Cron {
// Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
$x = '';
file_put_contents($lockfile, $x);
+*/
logger('cron: start');
@@ -50,7 +52,7 @@ class Cron {
require_once('include/account.php');
remove_expired_registrations();
- $interval = get_config('system', 'delivery_interval', 3);
+ $interval = get_config('queueworker', 'queue_interval', 500000);
// expire any expired items
@@ -65,8 +67,10 @@ class Cron {
if ($rr['item_wall']) {
// The notifier isn't normally invoked unless item_drop is interactive.
Master::Summon(['Notifier', 'drop', $rr['id']]);
- if ($interval)
- @time_sleep_until(microtime(true) + (float)$interval);
+
+ if ($interval) {
+ usleep($interval);
+ }
}
}
}
@@ -96,8 +100,10 @@ class Cron {
if ($r) {
foreach ($r as $rr) {
Master::Summon(array('Directory', $rr['channel_id'], 'force'));
- if ($interval)
- @time_sleep_until(microtime(true) + (float)$interval);
+
+ if ($interval) {
+ usleep($interval);
+ }
}
}
@@ -151,8 +157,10 @@ class Cron {
);
}
Master::Summon(array('Notifier', 'wall-new', $rr['id']));
- if ($interval)
- @time_sleep_until(microtime(true) + (float)$interval);
+
+ if ($interval) {
+ usleep($interval);
+ }
}
}
}
@@ -203,10 +211,10 @@ class Cron {
}
- // pull in some public posts
+ // pull in some public posts if allowed
- $disable_discover_tab = get_config('system', 'disable_discover_tab') || get_config('system', 'disable_discover_tab') === false;
- if (!$disable_discover_tab)
+ $disable_externals = get_config('system', 'disable_discover_tab') || get_config('system', 'disable_discover_tab') === false || get_config('system', 'site_firehose');
+ if (!$disable_externals)
Master::Summon(['Externals']);
$restart = false;
@@ -228,7 +236,7 @@ class Cron {
set_config('system', 'lastcron', datetime_convert());
//All done - clear the lockfile
- @unlink($lockfile);
+ //@unlink($lockfile);
return;
}
diff --git a/Zotlabs/Daemon/Cron_daily.php b/Zotlabs/Daemon/Cron_daily.php
index 71d3bc9ef..6d62836c7 100644
--- a/Zotlabs/Daemon/Cron_daily.php
+++ b/Zotlabs/Daemon/Cron_daily.php
@@ -119,5 +119,7 @@ class Cron_daily {
/**
* End Cron Daily
*/
+
+ return;
}
}
diff --git a/Zotlabs/Daemon/Cron_weekly.php b/Zotlabs/Daemon/Cron_weekly.php
index 407aa40ef..75fb94700 100644
--- a/Zotlabs/Daemon/Cron_weekly.php
+++ b/Zotlabs/Daemon/Cron_weekly.php
@@ -22,12 +22,12 @@ class Cron_weekly {
mark_orphan_hubsxchans();
- // Find channels that were removed in the last three weeks, but
+ // Find channels that were removed in the last three weeks, but
// haven't been finally cleaned up. These should be older than 10
- // days to ensure that "purgeall" messages have gone out or bounced
- // or timed out.
+ // days to ensure that "purgeall" messages have gone out or bounced
+ // or timed out.
- $r = q("select channel_id from channel where channel_removed = 1 and
+ $r = q("select channel_id from channel where channel_removed = 1 and
channel_deleted > %s - INTERVAL %s and channel_deleted < %s - INTERVAL %s",
db_utcnow(), db_quoteinterval('21 DAY'),
db_utcnow(), db_quoteinterval('10 DAY')
@@ -59,5 +59,6 @@ class Cron_weekly {
* End Cron Weekly
*/
+ return;
}
-} \ No newline at end of file
+}
diff --git a/Zotlabs/Daemon/Deliver.php b/Zotlabs/Daemon/Deliver.php
index 400ef697b..2d80dc093 100644
--- a/Zotlabs/Daemon/Deliver.php
+++ b/Zotlabs/Daemon/Deliver.php
@@ -28,6 +28,8 @@ class Deliver {
}
+ return;
+
}
}
diff --git a/Zotlabs/Daemon/Deliver_hooks.php b/Zotlabs/Daemon/Deliver_hooks.php
index 4d3ce4e1d..1e478db1e 100644
--- a/Zotlabs/Daemon/Deliver_hooks.php
+++ b/Zotlabs/Daemon/Deliver_hooks.php
@@ -12,8 +12,12 @@ class Deliver_hooks {
$r = q("select * from item where id = '%d'",
intval($argv[1])
);
- if ($r)
+
+ if ($r) {
call_hooks('notifier_normal', $r[0]);
+ }
+
+ return;
}
}
diff --git a/Zotlabs/Daemon/Directory.php b/Zotlabs/Daemon/Directory.php
index 3996b8079..19adf8273 100644
--- a/Zotlabs/Daemon/Directory.php
+++ b/Zotlabs/Daemon/Directory.php
@@ -97,5 +97,7 @@ class Directory {
if ($pushall) {
Master::Summon(array('Notifier', 'refresh_all', $channel['channel_id']));
}
+
+ return;
}
}
diff --git a/Zotlabs/Daemon/Expire.php b/Zotlabs/Daemon/Expire.php
index 99fe68b6f..5d9f14b28 100644
--- a/Zotlabs/Daemon/Expire.php
+++ b/Zotlabs/Daemon/Expire.php
@@ -103,5 +103,7 @@ class Expire {
}
del_config('procid', 'expire');
+
+ return;
}
}
diff --git a/Zotlabs/Daemon/Externals.php b/Zotlabs/Daemon/Externals.php
index 91fa09044..2c7c7c172 100644
--- a/Zotlabs/Daemon/Externals.php
+++ b/Zotlabs/Daemon/Externals.php
@@ -143,7 +143,7 @@ class Externals {
$AS = new ActivityStreams($message);
if ($AS->is_valid() && is_array($AS->obj)) {
$item = Activity::decode_note($AS);
- Activity::store($importer, $contact['abook_xchan'], $AS, $item);
+ Activity::store($importer, $contact['hubloc_hash'], $AS, $item);
$total++;
}
}
diff --git a/Zotlabs/Daemon/Importdoc.php b/Zotlabs/Daemon/Importdoc.php
index 9e818e2b3..c5a81e50c 100644
--- a/Zotlabs/Daemon/Importdoc.php
+++ b/Zotlabs/Daemon/Importdoc.php
@@ -11,6 +11,8 @@ class Importdoc {
self::update_docs_dir('doc/*');
+ return;
+
}
static public function update_docs_dir($s) {
diff --git a/Zotlabs/Daemon/Master.php b/Zotlabs/Daemon/Master.php
index 6fa656be5..c9ed91aaa 100644
--- a/Zotlabs/Daemon/Master.php
+++ b/Zotlabs/Daemon/Master.php
@@ -2,6 +2,8 @@
namespace Zotlabs\Daemon;
+use Zotlabs\Lib\QueueWorker;
+
if (array_search(__file__, get_included_files()) === 0) {
require_once('include/cli_startup.php');
array_shift($argv);
@@ -9,6 +11,7 @@ if (array_search(__file__, get_included_files()) === 0) {
if ($argc)
Master::Release($argc, $argv);
+
return;
}
@@ -16,6 +19,10 @@ if (array_search(__file__, get_included_files()) === 0) {
class Master {
static public function Summon($arr) {
+
+ QueueWorker::Summon($arr);
+ return;
+/*
$hookinfo = [
'argv' => $arr
];
@@ -32,11 +39,15 @@ class Master {
$phpbin = get_config('system', 'phpbin', 'php');
proc_run($phpbin, 'Zotlabs/Daemon/Master.php', $arr);
+*/
}
static public function Release($argc, $argv) {
cli_startup();
+ QueueWorker::Release($argv);
+ return;
+/*
$hookinfo = [
'argv' => $argv
];
@@ -54,5 +65,6 @@ class Master {
logger('Master: release: ' . json_encode($argv), LOGGER_ALL, LOG_DEBUG);
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
$cls::run($argc, $argv);
+*/
}
}
diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php
index bfccb4099..f51dfab28 100644
--- a/Zotlabs/Daemon/Notifier.php
+++ b/Zotlabs/Daemon/Notifier.php
@@ -509,6 +509,7 @@ class Notifier {
// public posts won't make it to the local public stream unless there's a recipient on this site.
// This code block sees if it's a public post and localhost is missing, and if so adds an entry for the local sys channel to the $hubs list
+ /* sys channel is now added in collect recipients
if (!self::$private) {
$found_localhost = false;
if ($hubs) {
@@ -529,6 +530,7 @@ class Notifier {
}
}
}
+ */
if (!$hubs) {
logger('notifier: no hubs', LOGGER_NORMAL, LOG_NOTICE);
diff --git a/Zotlabs/Daemon/Poller.php b/Zotlabs/Daemon/Poller.php
index 63c498f17..0fdc3da16 100644
--- a/Zotlabs/Daemon/Poller.php
+++ b/Zotlabs/Daemon/Poller.php
@@ -17,9 +17,12 @@ class Poller {
}
}
- $interval = intval(get_config('system', 'poll_interval'));
- if (!$interval)
+ $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';
@@ -32,6 +35,7 @@ class Poller {
// Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
$x = '';
file_put_contents($lockfile, $x);
+*/
logger('poller: start');
@@ -103,8 +107,10 @@ class Poller {
if ($t < $x) {
Master::Summon(['Onepoll', $contact['abook_id']]);
- if ($interval)
- @time_sleep_until(microtime(true) + (float)$interval);
+
+ if ($interval) {
+ usleep($interval);
+ }
}
continue;
@@ -167,9 +173,10 @@ class Poller {
continue;
Master::Summon(['Onepoll', $contact['abook_id']]);
- if ($interval)
- @time_sleep_until(microtime(true) + (float)$interval);
+ if ($interval) {
+ usleep($interval);
+ }
}
}
@@ -190,9 +197,12 @@ class Poller {
if ($rr['ud_last'] > NULL_DATE)
if ($rr['ud_last'] > datetime_convert('UTC', 'UTC', 'now - 1 day'))
continue;
+
Master::Summon(['Onedirsync', $rr['ud_id']]);
- if ($interval)
- @time_sleep_until(microtime(true) + (float)$interval);
+
+ if ($interval) {
+ usleep($interval);
+ }
}
}
}
@@ -200,9 +210,9 @@ 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 41aaf45ed..3eb7d9d23 100644
--- a/Zotlabs/Daemon/Queue.php
+++ b/Zotlabs/Daemon/Queue.php
@@ -79,5 +79,7 @@ class Queue {
foreach ($r as $rv) {
LibQueue::deliver($rv);
}
+
+ return;
}
}
diff --git a/Zotlabs/Daemon/Thumbnail.php b/Zotlabs/Daemon/Thumbnail.php
index 3688e8ae5..fa9570658 100644
--- a/Zotlabs/Daemon/Thumbnail.php
+++ b/Zotlabs/Daemon/Thumbnail.php
@@ -73,5 +73,7 @@ class Thumbnail {
|| (filectime(dbunescbin($attach['content']) . 'thumb') < (time() - 60)))) {
$default_controller->Thumb($attach, $preview_style, $preview_width, $preview_height);
}
+
+ return;
}
}
diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
index 9dbb15c28..8f4e0444c 100644
--- a/Zotlabs/Lib/Activity.php
+++ b/Zotlabs/Lib/Activity.php
@@ -672,6 +672,7 @@ class Activity {
}
}
}
+
return $ret;
}
@@ -2456,7 +2457,7 @@ class Activity {
$s['attach'] = $a;
}
- $a = self::decode_iconfig($act->obj);
+ $a = self::decode_iconfig($act->data);
if ($a) {
$s['iconfig'] = $a;
}
@@ -2786,8 +2787,9 @@ class Activity {
set_iconfig($s, 'diaspora', 'fields', $diaspora_rawmsg, 1);
}
- set_iconfig($s, 'activitypub', 'recips', $act->raw_recips);
-
+ if ($act->raw_recips) {
+ set_iconfig($s, 'activitypub', 'recips', $act->raw_recips);
+ }
$hookinfo = [
'act' => $act,
diff --git a/Zotlabs/Lib/Libsync.php b/Zotlabs/Lib/Libsync.php
index fd9886f71..f844c63b5 100644
--- a/Zotlabs/Lib/Libsync.php
+++ b/Zotlabs/Lib/Libsync.php
@@ -135,8 +135,7 @@ class Libsync {
$info['collection_members'] = $r;
}
- $interval = ((get_config('system', 'delivery_interval') !== false)
- ? intval(get_config('system', 'delivery_interval')) : 2);
+ $interval = get_config('queueworker', 'queue_interval', 500000);
logger('Packet: ' . print_r($info, true), LOGGER_DATA, LOG_DEBUG);
@@ -155,19 +154,26 @@ class Libsync {
]);
+ /*
$x = q("select count(outq_hash) as total from outq where outq_delivered = 0");
+
if (intval($x[0]['total']) > intval(get_config('system', 'force_queue_threshold', 3000))) {
logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO);
Queue::update($hash);
continue;
}
-
+ */
Master::Summon(['Deliver', $hash]);
+
+ /*
$total = $total - 1;
+ */
+
+ if ($interval) {
+ usleep($interval);
+ }
- if ($interval && $total)
- @time_sleep_until(microtime(true) + (float)$interval);
}
}
diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php
index b0d33e055..c635fdb17 100644
--- a/Zotlabs/Lib/Libzot.php
+++ b/Zotlabs/Lib/Libzot.php
@@ -291,6 +291,12 @@ class Libzot {
}
$m = parse_url($url);
+
+ if (!$m) {
+ logger('zot_refresh: could not parse url');
+ return false;
+ }
+
$site_url = unparse_url([ 'scheme' => $m['scheme'], 'host' => $m['host'] ]);
$s = q("select site_dead from site where site_url = '%s' limit 1",
diff --git a/Zotlabs/Lib/QueueWorker.php b/Zotlabs/Lib/QueueWorker.php
new file mode 100644
index 000000000..fd2ebd7e1
--- /dev/null
+++ b/Zotlabs/Lib/QueueWorker.php
@@ -0,0 +1,357 @@
+<?php
+
+namespace Zotlabs\Lib;
+
+use Ramsey\Uuid\Uuid;
+use Ramsey\Uuid\Exception\UnableToBuildUuidException;
+
+class QueueWorker {
+
+ public static $queueworker = null;
+ public static $maxworkers = 0;
+ public static $workermaxage = 0;
+ public static $workersleep = 100;
+ public static $default_priorities = [
+ 'Notifier' => 10,
+ 'Deliver' => 10,
+ 'Cache_query' => 10,
+ 'Content_importer' => 1,
+ 'File_importer' => 1,
+ 'Channel_purge' => 1,
+ 'Directory' => 1
+ ];
+
+ // Exceptions for processtimeout ($workermaxage) value.
+ // Currently the value is overriden with 3600 seconds (1h).
+ public static $long_running_cmd = [
+ 'Queue'
+ ];
+
+ private static function qstart() {
+ q('START TRANSACTION');
+ }
+
+ private static function qcommit() {
+ q("COMMIT");
+ }
+
+ private static function qrollback() {
+ q("ROLLBACK");
+ }
+
+ public static function Summon($argv) {
+
+ if ($argv[0] !== 'Queueworker') {
+
+ $priority = 0; // @TODO allow reprioritization
+
+ if (isset(self::$default_priorities[$argv[0]])) {
+ $priority = self::$default_priorities[$argv[0]];
+ }
+
+ $workinfo = ['argc' => count($argv), 'argv' => $argv];
+ $workinfo_json = json_encode($workinfo);
+ $uuid = self::getUuid($workinfo_json);
+
+ $r = q("SELECT * FROM workerq WHERE workerq_uuid = '%s'",
+ dbesc($uuid)
+ );
+ if ($r) {
+ logger("Summon: Ignoring duplicate workerq task", LOGGER_DEBUG);
+ logger(print_r($workinfo, true));
+ return;
+ }
+
+ self::qstart();
+ $r = q("INSERT INTO workerq (workerq_priority, workerq_data, workerq_uuid, workerq_cmd) VALUES (%d, '%s', '%s', '%s')",
+ intval($priority),
+ $workinfo_json,
+ dbesc($uuid),
+ dbesc($argv[0])
+ );
+ if (!$r) {
+ self::qrollback();
+ logger("INSERT FAILED", LOGGER_DEBUG);
+ return;
+ }
+ self::qcommit();
+ logger('INSERTED: ' . $workinfo_json, LOGGER_DEBUG);
+ }
+
+ $workers = self::GetWorkerCount();
+ if ($workers < self::$maxworkers) {
+ logger($workers . '/' . self::$maxworkers . ' workers active', LOGGER_DEBUG);
+ $phpbin = get_config('system', 'phpbin', 'php');
+ proc_run($phpbin, 'Zotlabs/Daemon/Master.php', ['Queueworker']);
+ }
+ }
+
+ public static function Release($argv) {
+
+ if ($argv[0] !== 'Queueworker') {
+
+ $priority = 0; // @TODO allow reprioritization
+ if (isset(self::$default_priorities[$argv[0]])) {
+ $priority = self::$default_priorities[$argv[0]];
+ }
+
+ $workinfo = ['argc' => count($argv), 'argv' => $argv];
+ $workinfo_json = json_encode($workinfo);
+ $uuid = self::getUuid($workinfo_json);
+
+ $r = q("SELECT * FROM workerq WHERE workerq_uuid = '%s'",
+ dbesc($uuid)
+ );
+ if ($r) {
+ logger("Release: Duplicate task - do not insert.", LOGGER_DEBUG);
+ logger(print_r($workinfo, true));
+ return;
+ }
+
+ self::qstart();
+ $r = q("INSERT INTO workerq (workerq_priority, workerq_data, workerq_uuid, workerq_cmd) VALUES (%d, '%s', '%s', '%s')",
+ intval($priority),
+ $workinfo_json,
+ dbesc($uuid),
+ dbesc($argv[0])
+ );
+ if (!$r) {
+ self::qrollback();
+ logger("Insert failed: " . $workinfo_json, LOGGER_DEBUG);
+ return;
+ }
+ self::qcommit();
+ logger('INSERTED: ' . $workinfo_json, LOGGER_DEBUG);
+ }
+
+ self::Process();
+ }
+
+ public static function GetWorkerCount() {
+ if (self::$maxworkers == 0) {
+ self::$maxworkers = get_config('queueworker', 'max_queueworkers', 4);
+ self::$maxworkers = self::$maxworkers > 3 ? self::$maxworkers : 4;
+ }
+ if (self::$workermaxage == 0) {
+ self::$workermaxage = get_config('queueworker', 'max_queueworker_age');
+ self::$workermaxage = self::$workermaxage > 120 ? self::$workermaxage : 300;
+ }
+
+ q("update workerq set workerq_reservationid = null where workerq_reservationid is not null and workerq_processtimeout < %s",
+ db_utcnow()
+ );
+
+ //usleep(self::$workersleep);
+
+ $workers = dbq("select count(distinct workerq_reservationid) as total from workerq where workerq_reservationid is not null");
+ logger("WORKERCOUNT: " . $workers[0]['total'], LOGGER_DEBUG);
+
+ return intval($workers[0]['total']);
+ }
+
+ public static function GetWorkerID() {
+ if (self::$queueworker) {
+ return self::$queueworker;
+ }
+
+ $wid = uniqid('', true);
+
+ usleep(mt_rand(300000, 1000000)); //Sleep .3 - 1 seconds before creating a new worker.
+
+ $workers = self::GetWorkerCount();
+
+ if ($workers >= self::$maxworkers) {
+ logger("Too many active workers ($workers) max = " . self::$maxworkers, LOGGER_DEBUG);
+ return false;
+ }
+
+ self::$queueworker = $wid;
+
+ return $wid;
+ }
+
+ private static function getWorkId() {
+ self::GetWorkerCount();
+
+ self::qstart();
+
+ // This is probably the better solution but is not supported by mariadb < 10.6 which is still used a lot.
+ // $work = dbq("SELECT workerq_id FROM workerq WHERE workerq_reservationid IS NULL ORDER BY workerq_priority DESC, workerq_id ASC LIMIT 1 FOR UPDATE SKIP LOCKED;");
+
+ $work = dbq("SELECT workerq_id, workerq_cmd FROM workerq WHERE workerq_reservationid IS NULL ORDER BY workerq_priority DESC, workerq_id ASC LIMIT 1 FOR UPDATE;");
+
+ if (!$work) {
+ self::qcommit();
+ return false;
+ }
+
+ $id = $work[0]['workerq_id'];
+ $cmd = $work[0]['workerq_cmd'];
+ $age = self::$workermaxage;
+
+ if (in_array($cmd, self::$long_running_cmd)) {
+ $age = 3600; // 1h TODO: make this configurable
+ }
+
+ $work = q("UPDATE workerq SET workerq_reservationid = '%s', workerq_processtimeout = %s + INTERVAL %s WHERE workerq_id = %d",
+ self::$queueworker,
+ db_utcnow(),
+ db_quoteinterval($age . " SECOND"),
+ intval($id)
+ );
+
+ if (!$work) {
+ self::qrollback();
+ logger("Could not update workerq.", LOGGER_DEBUG);
+ return false;
+ }
+
+ logger("GOTWORK: " . json_encode($work), LOGGER_DEBUG);
+ self::qcommit();
+
+ return $id;
+ }
+
+ public static function Process() {
+ $sleep = intval(get_config('queueworker', 'queue_worker_sleep', 100));
+ $auto_queue_worker_sleep = get_config('queueworker', 'auto_queue_worker_sleep', 0);
+
+ if (!self::GetWorkerID()) {
+ if ($auto_queue_worker_sleep) {
+ set_config('queueworker', 'queue_worker_sleep', $sleep + 100);
+ }
+
+ logger('Unable to get worker ID. Exiting.', LOGGER_DEBUG);
+ killme();
+ }
+
+ if ($auto_queue_worker_sleep && $sleep > 100) {
+ $next_sleep = $sleep - 100;
+ set_config('queueworker', 'queue_worker_sleep', (($next_sleep < 100) ? 100 : $next_sleep));
+ }
+
+ $jobs = 0;
+ $workid = self::getWorkId();
+ $load_average_sleep = false;
+ self::$workersleep = $sleep;
+ self::$workersleep = ((intval(self::$workersleep) > 100) ? intval(self::$workersleep) : 100);
+
+ if (function_exists('sys_getloadavg') && get_config('queueworker', 'load_average_sleep')) {
+ // very experimental!
+ $load_average_sleep = true;
+ }
+
+ while ($workid) {
+
+ if ($load_average_sleep) {
+ $load_average = sys_getloadavg();
+ self::$workersleep = intval($load_average[0]) * 10000;
+
+ if (!self::$workersleep) {
+ self::$workersleep = 100;
+ }
+ }
+
+ logger('queue_worker_sleep: ' . self::$workersleep, LOGGER_DEBUG);
+
+ usleep(self::$workersleep);
+
+ $workitem = dbq("SELECT * FROM workerq WHERE workerq_id = $workid");
+
+ if ($workitem) {
+ // At least SOME work to do.... in case there's more, let's ramp up workers.
+ $workers = self::GetWorkerCount();
+
+ if ($workers < self::$maxworkers) {
+ logger($workers . '/' . self::$maxworkers . ' workers active', LOGGER_DEBUG);
+ $phpbin = get_config('system', 'phpbin', 'php');
+ proc_run($phpbin, 'Zotlabs/Daemon/Master.php', ['Queueworker']);
+ }
+
+ $jobs++;
+
+ logger("Workinfo: " . $workitem[0]['workerq_data'], LOGGER_DEBUG);
+
+ $workinfo = json_decode($workitem[0]['workerq_data'], true);
+ $argv = $workinfo['argv'];
+
+ $cls = '\\Zotlabs\\Daemon\\' . $argv[0];
+ $argv = flatten_array_recursive($argv);
+ $argc = count($argv);
+ $rnd = random_string();
+
+ logger('PROCESSING: ' . $rnd . ' ' . print_r($argv[0], true));
+
+ $cls::run($argc, $argv);
+
+ logger('COMPLETED: ' . $rnd);
+
+ // @FIXME: Right now we assume that if we get a return, everything is OK.
+ // At some point we may want to test whether the run returns true/false
+ // and requeue the work to be tried again if needed. But we probably want
+ // to implement some sort of "retry interval" first.
+
+ dbq("delete from workerq where workerq_id = $workid");
+ }
+ else {
+ logger("NO WORKITEM!", LOGGER_DEBUG);
+ }
+ $workid = self::getWorkId();
+ }
+ logger('Master: Worker Thread: queue items processed:' . $jobs, LOGGER_DEBUG);
+ }
+
+ public static function ClearQueue() {
+ $work = q("select * from workerq");
+ while ($work) {
+ foreach ($work as $workitem) {
+ $workinfo = json_decode($workitem['v'], true);
+ $argc = $workinfo['argc'];
+ $argv = $workinfo['argv'];
+
+ logger('Master: process: ' . print_r($argv, true), LOGGER_ALL, LOG_DEBUG);
+
+ if (!isset($argv[0])) {
+ q("delete from workerq where workerq_id = %d",
+ $work[0]['workerq_id']
+ );
+ continue;
+ }
+
+ $cls = '\\Zotlabs\\Daemon\\' . $argv[0];
+ $cls::run($argc, $argv);
+
+ q("delete from workerq where workerq_id = %d",
+ $work[0]['workerq_id']
+ );
+
+ //Give the server .3 seconds to catch its breath between tasks.
+ //This will hopefully keep it from crashing to it's knees entirely
+ //if the last task ended up initiating other parallel processes
+ //(eg. polling remotes)
+ usleep(300000);
+ }
+
+ //Make sure nothing new came in
+ $work = q("select * from workerq");
+ }
+ }
+
+ /**
+ * @brief Generate a name-based v5 UUID with custom namespace
+ *
+ * @param string $data
+ * @return string $uuid
+ */
+ private static function getUuid(string $data) {
+ $namespace = '3a112e42-f147-4ccf-a78b-f6841339ea2a';
+ try {
+ $uuid = Uuid::uuid5($namespace, $data)->toString();
+ } catch (UnableToBuildUuidException $e) {
+ logger('UUID generation failed');
+ return '';
+ }
+ return $uuid;
+ }
+
+}
diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php
index e86e2cac1..d1b386c42 100644
--- a/Zotlabs/Lib/ThreadItem.php
+++ b/Zotlabs/Lib/ThreadItem.php
@@ -137,13 +137,7 @@ class ThreadItem {
$shareable = false;
}
- $privacy_warning = false;
- if(intval($item['item_private']) && ($item['owner']['xchan_network'] === 'activitypub')) {
- $recips = get_iconfig($item['parent'], 'activitypub', 'recips');
-
- if(! is_array($recips['to']) || ! in_array($observer['xchan_url'], $recips['to']))
- $privacy_warning = true;
- }
+ $privacy_warning = ($item['owner']['xchan_network'] === 'activitypub' && intval($item['item_private']) === 1);
if ($lock) {
if (($item['mid'] == $item['parent_mid']) && isset($item['term']) && count(get_terms_oftype($item['term'], TERM_FORUM))) {
diff --git a/Zotlabs/Module/Admin/Queueworker.php b/Zotlabs/Module/Admin/Queueworker.php
new file mode 100644
index 000000000..45a09bf04
--- /dev/null
+++ b/Zotlabs/Module/Admin/Queueworker.php
@@ -0,0 +1,121 @@
+<?php
+
+namespace Zotlabs\Module\Admin;
+
+use App;
+use Zotlabs\Web\Controller;
+
+class Queueworker extends Controller {
+
+ function init() {
+
+ }
+
+ function post() {
+
+ check_form_security_token('form_security_token', 'queueworker');
+
+ $maxqueueworkers = intval($_POST['queueworker_maxworkers']);
+ $maxqueueworkers = ($maxqueueworkers > 3) ? $maxqueueworkers : 4;
+ set_config('queueworker', 'max_queueworkers', $maxqueueworkers);
+
+ $maxworkerage = intval($_POST['queueworker_max_age']);
+ $maxworkerage = ($maxworkerage >= 120) ? $maxworkerage : 300;
+ set_config('queueworker', 'queueworker_max_age', $maxworkerage);
+
+ $queueworkersleep = intval($_POST['queue_worker_sleep']);
+ $queueworkersleep = ($queueworkersleep > 100) ? $queueworkersleep : 100;
+ set_config('queueworker', 'queue_worker_sleep', $queueworkersleep);
+
+ $auto_queue_worker_sleep = intval($_POST['auto_queue_worker_sleep']);
+ set_config('queueworker', 'auto_queue_worker_sleep', $auto_queue_worker_sleep);
+
+ goaway(z_root() . '/admin/queueworker');
+ }
+
+ function get() {
+
+ $content = "<H1>Queue Status</H1>\n";
+
+ $r = q('select count(*) as total from workerq');
+
+ $content .= "<H4>There are " . $r[0]['total'] . " queue items to be processed.</H4>";
+
+ $r = dbq("select count(distinct workerq_reservationid) as qworkers from workerq where workerq_reservationid is not null");
+
+ $content .= "<H4>Active workers: " . $r[0]['qworkers'] . "</H4>";
+
+ $r = dbq("select workerq_cmd, count(*) as total from workerq where true group by workerq_cmd");
+
+ if ($r) {
+ $content .= "<H4>Work items</H4>";
+ foreach($r as $rr) {
+ $content .= $rr['workerq_cmd'] . ': ' . $rr['total'] . '<br>';
+ }
+ }
+
+ $maxqueueworkers = get_config('queueworker', 'max_queueworkers', 4);
+ $maxqueueworkers = ($maxqueueworkers > 3) ? $maxqueueworkers : 4;
+
+ $sc = '';
+
+ $sc .= replace_macros(get_markup_template('field_input.tpl'), [
+ '$field' => [
+ 'queueworker_maxworkers',
+ t('Max queueworker threads'),
+ $maxqueueworkers,
+ t('Minimum 4, default 4')
+ ]
+ ]);
+
+ $workermaxage = get_config('queueworker', 'queueworker_max_age');
+ $workermaxage = ($workermaxage >= 120) ? $workermaxage : 300;
+
+ $sc .= replace_macros(get_markup_template('field_input.tpl'), [
+ '$field' => [
+ 'queueworker_max_age',
+ t('Assume workers dead after'),
+ $workermaxage,
+ t('Minimum 120, default 300 seconds')
+ ]
+ ]);
+
+ $queueworkersleep = get_config('queueworker', 'queue_worker_sleep');
+ $queueworkersleep = ($queueworkersleep > 100) ? $queueworkersleep : 100;
+
+ $auto_queue_worker_sleep = get_config('queueworker', 'auto_queue_worker_sleep', 0);
+
+ $sc .= replace_macros(get_markup_template('field_input.tpl'), [
+ '$field' => [
+ 'queue_worker_sleep',
+ t('Pause before starting next task'),
+ $queueworkersleep,
+ t('Minimum 100, default 100 microseconds'),
+ '',
+ (($auto_queue_worker_sleep) ? 'disabled' : '')
+ ]
+ ]);
+
+ $sc .= replace_macros(get_markup_template('field_checkbox.tpl'), [
+ '$field' => [
+ 'auto_queue_worker_sleep',
+ t('Automatically adjust pause before starting next task'),
+ $auto_queue_worker_sleep,
+ ]
+ ]);
+
+ $tpl = get_markup_template('settings_addon.tpl');
+ $content .= replace_macros($tpl, [
+ '$action_url' => 'admin/queueworker',
+ '$form_security_token' => get_form_security_token('queueworker'),
+ '$title' => t('Queueworker Settings'),
+ '$content' => $sc,
+ '$baseurl' => z_root(),
+ '$submit' => t('Save')
+ ]
+ );
+
+ return $content;
+
+ }
+}
diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php
index 85f81e344..42cf064c9 100644
--- a/Zotlabs/Module/Admin/Site.php
+++ b/Zotlabs/Module/Admin/Site.php
@@ -100,7 +100,7 @@ class Site {
$reg_expire = (preg_match('/^[a-z]{1,1}$/', $regexpireu) ? $regexpiren . $regexpireu : '');
$imagick_path = ((x($_POST,'imagick_path')) ? trim($_POST['imagick_path']) : '');
- $force_queue = ((intval($_POST['force_queue']) > 0) ? intval($_POST['force_queue']) : 3000);
+ //$force_queue = ((intval($_POST['force_queue']) > 0) ? intval($_POST['force_queue']) : 3000);
$pub_incl = escape_tags(trim($_POST['pub_incl']));
$pub_excl = escape_tags(trim($_POST['pub_excl']));
@@ -205,7 +205,7 @@ class Site {
set_config('system','disable_discover_tab', $disable_discover_tab);
set_config('system','site_firehose', $site_firehose);
set_config('system','open_pubstream', $open_pubstream);
- set_config('system','force_queue_threshold', $force_queue);
+ //set_config('system','force_queue_threshold', $force_queue);
if ($global_directory == '') {
del_config('system', 'directory_submit_url');
} else {
@@ -508,10 +508,10 @@ class Site {
'$frontpage' => array('frontpage', t("Site homepage to show visitors (default: login box)"), get_config('system','frontpage'), t("example: 'pubstream' to show public stream, 'page/sys/home' to show a system webpage called 'home' or 'include:home.html' to include a file.")),
'$mirror_frontpage' => array('mirror_frontpage', t("Preserve site homepage URL"), get_config('system','mirror_frontpage'), t('Present the site homepage in a frame at the original location instead of redirecting')),
'$allowed_sites' => array('allowed_sites', t("Allowed friend domains"), get_config('system','allowed_sites'), t("Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains")),
- '$force_publish' => array('publish_all', t("Force publish"), get_config('system','publish_all'), t("Check to force all profiles on this site to be listed in the site directory.")),
- '$disable_discover_tab' => array('disable_discover_tab', t('Import Public Streams'), $discover_tab, t('Import and allow access to public content pulled from other sites. Warning: this content is unmoderated.')),
- '$site_firehose' => array('site_firehose', t('Site only Public Streams'), get_config('system','site_firehose'), t('Allow access to public content originating only from this site if Imported Public Streams are disabled.')),
- '$open_pubstream' => array('open_pubstream', t('Allow anybody on the internet to access the Public streams'), get_config('system','open_pubstream',1), t('Disable to require authentication before viewing. Warning: this content is unmoderated.')),
+ '$force_publish' => array('publish_all', t("Force publish"), get_config('system','publish_all'), t("Check to force all profiles on this site to be listed in the site directory")),
+ '$disable_discover_tab' => array('disable_discover_tab', t('Enable public stream'), $discover_tab, t('Enable the public stream. Warning: this content is unmoderated')),
+ '$site_firehose' => array('site_firehose', t('Site only public stream'), get_config('system','site_firehose'), t('Restrict the public stream to content originating at this site')),
+ '$open_pubstream' => array('open_pubstream', t('Allow anybody on the internet to access the public streams'), get_config('system','open_pubstream',1), t('Disable to require authentication before viewing')),
'$incl' => array('pub_incl',t('Only import Public stream posts with this text'), get_config('system','pubstream_incl'),t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')),
'$excl' => array('pub_excl',t('Do not import Public stream posts with this text'), get_config('system','pubstream_excl'),t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')),
@@ -532,7 +532,7 @@ class Site {
'$timeout' => array('timeout', t("Network timeout"), (x(get_config('system','curl_timeout'))?get_config('system','curl_timeout'):60), t("Value is in seconds. Set to 0 for unlimited (not recommended).")),
'$delivery_interval' => array('delivery_interval', t("Delivery interval"), (x(get_config('system','delivery_interval'))?get_config('system','delivery_interval'):2), t("Delay background delivery processes by this many seconds to reduce system load. Recommend: 4-5 for shared hosts, 2-3 for virtual private servers. 0-1 for large dedicated servers.")),
'$delivery_batch_count' => array('delivery_batch_count', t('Deliveries per process'),(x(get_config('system','delivery_batch_count'))?get_config('system','delivery_batch_count'):1), t("Number of deliveries to attempt in a single operating system process. Adjust if necessary to tune system performance. Recommend: 1-5.")),
- '$force_queue' => array('force_queue', t("Queue Threshold"), get_config('system','force_queue_threshold',3000), t("Always defer immediate delivery if queue contains more than this number of entries.")),
+ //'$force_queue' => array('force_queue', t("Queue Threshold"), get_config('system','force_queue_threshold',3000), t("Always defer immediate delivery if queue contains more than this number of entries.")),
'$poll_interval' => array('poll_interval', t("Poll interval"), (x(get_config('system','poll_interval'))?get_config('system','poll_interval'):2), t("Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval.")),
'$imagick_path' => array('imagick_path', t("Path to ImageMagick convert program"), get_config('system','imagick_convert_path'), t("If set, use this program to generate photo thumbnails for huge images ( > 4000 pixels in either dimension), otherwise memory exhaustion may occur. Example: /usr/bin/convert")),
'$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")),
diff --git a/Zotlabs/Module/Cloud.php b/Zotlabs/Module/Cloud.php
index 4cc7595a1..05109247a 100644
--- a/Zotlabs/Module/Cloud.php
+++ b/Zotlabs/Module/Cloud.php
@@ -100,7 +100,6 @@ class Cloud extends Controller {
// over-ride the default XML output on thrown exceptions
-
$server->on('exception', [ $this, 'DAVException' ]);
// All we need to do now, is to fire up the server
@@ -117,21 +116,19 @@ class Cloud extends Controller {
function DAVException($err) {
if($err instanceof \Sabre\DAV\Exception\NotFound) {
- notice( t('Not found') . EOL);
+ \App::$page['content'] = '<h2>404 Not found</h2>';
}
elseif($err instanceof \Sabre\DAV\Exception\Forbidden) {
- notice( t('Permission denied') . EOL);
+ \App::$page['content'] = '<h2>403 Forbidden</h2>';
}
elseif($err instanceof \Sabre\DAV\Exception\NotImplemented) {
- // notice( t('Please refresh page') . EOL);
goaway(z_root() . '/' . \App::$query_string);
}
else {
- notice( t('Unknown error') . EOL);
+ \App::$page['content'] = '<h2>Unknown error</h2>';
}
construct_page();
-
killme();
}
diff --git a/Zotlabs/Module/Import.php b/Zotlabs/Module/Import.php
index ec47e370b..c8a9ac5ed 100644
--- a/Zotlabs/Module/Import.php
+++ b/Zotlabs/Module/Import.php
@@ -536,7 +536,7 @@ class Import extends Controller {
$since = datetime_convert(date_default_timezone_get(), date_default_timezone_get(), '0001-01-01 00:00');
$until = datetime_convert(date_default_timezone_get(), date_default_timezone_get(), 'now + 1 day');
- $poll_interval = get_config('system', 'poll_interval', 3);
+ //$poll_interval = get_config('system', 'poll_interval', 3);
$page = 0;
Master::Summon(['Content_importer', sprintf('%d', $page), $since, $until, $channel['channel_address'], urlencode($hz_server)]);
diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php
index 8e6106e79..27fc62ee6 100644
--- a/Zotlabs/Module/Item.php
+++ b/Zotlabs/Module/Item.php
@@ -1518,8 +1518,9 @@ class Item extends Controller {
if (preg_match_all('/\[answer\](.*?)\[\/answer\]/ism', $body, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
- $ptr[] = ['name' => $match[1], 'type' => 'Note', 'replies' => ['type' => 'Collection', 'totalItems' => 0]];
- $body = str_replace('[answer]' . $match[1] . '[/answer]', EMPTY_STR, $body);
+ $answer = escape_tags(trim($match[1]));
+ $ptr[] = ['name' => $answer, 'type' => 'Note', 'replies' => ['type' => 'Collection', 'totalItems' => 0]];
+ $body = str_replace('[answer]' . $answer . '[/answer]', EMPTY_STR, $body);
}
}
@@ -1573,8 +1574,10 @@ class Item extends Controller {
$obj['content'] = bbcode($question);
foreach ($answers as $answer) {
- if (trim($answer))
- $ptr[] = ['name' => escape_tags($answer), 'type' => 'Note', 'replies' => ['type' => 'Collection', 'totalItems' => 0]];
+ $answer = escape_tags(trim($answer));
+ if ($answer) {
+ $ptr[] = ['name' => $answer, 'type' => 'Note', 'replies' => ['type' => 'Collection', 'totalItems' => 0]];
+ }
}
if ($multiple) {
diff --git a/Zotlabs/Module/Pdledit.php b/Zotlabs/Module/Pdledit.php
index 3b94c9611..e0bbc31d0 100644
--- a/Zotlabs/Module/Pdledit.php
+++ b/Zotlabs/Module/Pdledit.php
@@ -78,6 +78,23 @@ class Pdledit extends Controller {
}
}
+ // addons
+ $o .= '<h2>Addons</h2>';
+
+ $addons = plugins_installed_list();
+
+ foreach ($addons as $addon) {
+
+ $path = 'addon/' . $addon . '/Mod_' . ucfirst($addon) . '.php';
+
+ if (!file_exists($path))
+ continue;
+
+ $o .= '<a href="pdledit/' . $addon . '" >' . $addon . '</a>' . ((in_array($addon, $edited)) ? ' ' . t('(modified)') . ' <a href="pdledit/' . $addon . '/reset" >' . t('Reset') . '</a>': '' ) . '<br />';
+
+ }
+
+
$o .= '</div>';
// list module pdl files
@@ -85,11 +102,25 @@ class Pdledit extends Controller {
}
$t = get_pconfig(local_channel(),'system',$module);
- $s = file_get_contents(theme_include($module));
- if(! $t) {
+ $s = '';
+
+ if(!$t) {
+ $sys_path = theme_include($module);
+
+ if ($sys_path) {
+ $s = file_get_contents($sys_path);
+ }
+ else {
+ $addon_path = 'addon/' . argv(1) . '/' . $module;
+ if (file_exists($addon_path)) {
+ $s = file_get_contents($addon_path);
+ }
+ }
+
$t = $s;
}
- if(! $t) {
+
+ if(!$t) {
notice( t('Layout not found.') . EOL);
return '';
}
diff --git a/Zotlabs/Module/Pdledit_gui.php b/Zotlabs/Module/Pdledit_gui.php
index b550b92d3..dadb3296e 100644
--- a/Zotlabs/Module/Pdledit_gui.php
+++ b/Zotlabs/Module/Pdledit_gui.php
@@ -220,6 +220,7 @@ class Pdledit_gui extends Controller {
function get_modules() {
$ret = '';
+ $arr = [];
$files = glob('Zotlabs/Module/*.php');
if($files) {
@@ -232,23 +233,54 @@ class Pdledit_gui extends Controller {
$x = theme_include('mod_' . $name . '.pdl');
if($x) {
- $ret .= '<div class="mb-2"><a href="pdledit_gui/' . $name . '">' . $name . '</a></div>';
+ $arr[] = $name;
}
}
}
+ $addons = plugins_installed_list();
+ if ($addons) {
+ foreach ($addons as $name) {
+ $path = 'addon/' . $name . '/mod_' . $name . '.pdl';
+ if (file_exists($path)) {
+ $arr[] = $name;
+ }
+ }
+ }
+
+ sort($arr);
+
+ foreach ($arr as $name) {
+ $ret .= '<div class="mb-2"><a href="pdledit_gui/' . $name . '">' . $name . '</a></div>';
+ }
+
return $ret;
+
}
function get_widgets($module) {
$ret = [];
+
$checkpaths = [
'Zotlabs/Widget/*.php'
];
+ $addons = plugins_installed_list();
+
+ if ($addons) {
+ foreach ($addons as $name) {
+ $path = 'addon/' . $name . '/Widget';
+
+ if (is_dir($path)) {
+ $checkpaths[] = $path . '/*.php';
+ }
+ }
+ }
+
foreach ($checkpaths as $path) {
$files = glob($path);
+
if($files) {
foreach($files as $f) {
$name = lcfirst(basename($f, '.php'));
@@ -272,6 +304,8 @@ class Pdledit_gui extends Controller {
}
}
+ usort($ret, fn($a, $b) => $a['name'] <=> $b['name']);
+
return $ret;
}
@@ -536,12 +570,21 @@ class Pdledit_gui extends Controller {
'modified' => true
];
- $pdl_path = 'mod_' . $module . '.pdl';
+ $pdl = 'mod_' . $module . '.pdl';
+ $pdl_path = '';
- $ret['pdl'] = get_pconfig(local_channel(), 'system', $pdl_path);
+ $ret['pdl'] = get_pconfig(local_channel(), 'system', $pdl);
if(!$ret['pdl']) {
- $pdl_path = theme_include($pdl_path);
+ $pdl_path = theme_include($pdl);
+
+ if (!$pdl_path) {
+ $addon_path = 'addon/' . $module . '/' . $pdl;
+ if (file_exists($addon_path)) {
+ $pdl_path = $addon_path;
+ }
+ }
+
if ($pdl_path) {
$ret['pdl'] = file_get_contents($pdl_path);
$ret['modified'] = false;
diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php
index 47da3c13a..7b8d75727 100644
--- a/Zotlabs/Module/Pubstream.php
+++ b/Zotlabs/Module/Pubstream.php
@@ -158,16 +158,15 @@ class Pubstream extends \Zotlabs\Web\Controller {
require_once('include/security.php');
$sys = get_sys_channel();
+ $uids = " and item.uid = " . intval($sys['channel_id']) . " ";
$abook_uids = " and abook.abook_channel = " . intval($sys['channel_id']) . " ";
- $sql_extra = '';
+ $sql_extra = item_permissions_sql($sys['channel_id']);
+ $sql_extra_order = '';
+ $site_firehose_sql = '';
+ $thread_top = " and item.item_thread_top = 1 ";
if($site_firehose) {
- $uids = " and item.uid in ( " . stream_perms_api_uids(PERMS_PUBLIC) . " ) and item_private = 0 and item_wall = 1 ";
- }
- else {
- $uids = " and item.uid = " . intval($sys['channel_id']) . " ";
- $sql_extra .= item_permissions_sql($sys['channel_id']);
- \App::$data['firehose'] = intval($sys['channel_id']);
+ $site_firehose_sql = " and owner_xchan in (select channel_hash from channel where channel_system = 0 and channel_removed = 0) ";
}
if(get_config('system','public_list_mode'))
@@ -178,6 +177,8 @@ class Pubstream extends \Zotlabs\Web\Controller {
if(x($hashtags)) {
$sql_extra .= protect_sprintf(term_query('item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
+ $sql_extra_order = " ORDER BY item.created DESC ";
+ $thread_top = '';
}
$net_query = (($net) ? " left join xchan on xchan_hash = author_xchan " : '');
@@ -199,7 +200,9 @@ class Pubstream extends \Zotlabs\Web\Controller {
$r = q("SELECT parent AS item_id FROM item
left join abook on item.author_xchan = abook.abook_xchan
$net_query
- WHERE mid = '%s' $uids $item_normal
+ WHERE item.mid = '%s' and item.item_private = 0
+ $uids $site_firehose_sql
+ $item_normal
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra $net_query2",
dbesc($mid)
@@ -207,10 +210,12 @@ class Pubstream extends \Zotlabs\Web\Controller {
}
else {
// Fetch a page full of parent items for this page
- $r = dbq("SELECT item.id AS item_id FROM item
+ $r = dbq("SELECT parent AS item_id FROM item
left join abook on ( item.author_xchan = abook.abook_xchan $abook_uids )
$net_query
- WHERE true $uids and item.item_thread_top = 1 $item_normal
+ WHERE item.item_private = 0 $thread_top
+ $uids $site_firehose_sql
+ $item_normal
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra $net_query2
ORDER BY $ordering DESC $pager_sql "
@@ -222,7 +227,8 @@ class Pubstream extends \Zotlabs\Web\Controller {
$r = q("SELECT parent AS item_id FROM item
left join abook on item.author_xchan = abook.abook_xchan
$net_query
- WHERE mid = '%s' $uids $item_normal_update $simple_update
+ WHERE item.mid = '%s' and item.item_private = 0
+ $uids $site_firehose_sql $item_normal_update $simple_update
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra $net_query2",
dbesc($mid)
@@ -232,7 +238,8 @@ class Pubstream extends \Zotlabs\Web\Controller {
$r = dbq("SELECT parent AS item_id FROM item
left join abook on item.author_xchan = abook.abook_xchan
$net_query
- WHERE true $uids $item_normal_update
+ WHERE item.item_private = 0 $thread_top
+ $uids $site_firehose_sql $item_normal_update
$simple_update
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra $net_query2"
@@ -250,15 +257,22 @@ class Pubstream extends \Zotlabs\Web\Controller {
$items = dbq("SELECT item.*, item.id AS item_id FROM item
WHERE true $uids $item_normal
AND item.parent IN ( $parents_str )
- $sql_extra"
+ $sql_extra $sql_extra_order"
);
+
+
// use effective_uid param of xchan_query to help sort out comment permission
// for sys_channel owned items.
- xchan_query($items,true,(($sys) ? local_channel() : 0));
+ xchan_query($items, true, local_channel());
$items = fetch_post_tags($items,true);
- $items = conv_sort($items,$ordering);
+
+ if (!$hashtags) {
+ $items = conv_sort($items, $ordering);
+ }
+
+
}
}
diff --git a/Zotlabs/Module/Settings/Account.php b/Zotlabs/Module/Settings/Account.php
index 97cc9389a..5e1fb176e 100644
--- a/Zotlabs/Module/Settings/Account.php
+++ b/Zotlabs/Module/Settings/Account.php
@@ -6,11 +6,11 @@ class Account {
function post() {
check_form_security_token_redirectOnErr('/settings/account', 'settings_account');
-
+
call_hooks('account_settings_post', $_POST);
-
+
$errs = array();
-
+
$email = ((x($_POST,'email')) ? trim(notags($_POST['email'])) : '');
$account = \App::get_account();
@@ -34,38 +34,38 @@ class Account {
}
}
}
-
+
if($errs) {
foreach($errs as $err)
notice($err . EOL);
$errs = array();
}
-
-
+
+
if((x($_POST,'npassword')) || (x($_POST,'confirm'))) {
-
+
$origpass = trim($_POST['origpass']);
-
+
require_once('include/auth.php');
if(! account_verify_password($email,$origpass)) {
$errs[] = t('Password verification failed.');
}
-
+
$newpass = trim($_POST['npassword']);
$confirm = trim($_POST['confirm']);
-
+
if($newpass != $confirm ) {
$errs[] = t('Passwords do not match. Password unchanged.');
}
-
+
if((! x($newpass)) || (! x($confirm))) {
$errs[] = t('Empty passwords are not allowed. Password unchanged.');
}
-
+
if(! $errs) {
$salt = random_string(32);
$password_encoded = hash('whirlpool', $salt . $newpass);
- $r = q("update account set account_salt = '%s', account_password = '%s', account_password_changed = '%s'
+ $r = q("update account set account_salt = '%s', account_password = '%s', account_password_changed = '%s'
where account_id = %d",
dbesc($salt),
dbesc($password_encoded),
@@ -78,36 +78,37 @@ class Account {
$errs[] = t('Password update failed. Please try again.');
}
}
-
-
+
+
if($errs) {
foreach($errs as $err)
notice($err . EOL);
}
goaway(z_root() . '/settings/account' );
}
-
-
+
+
function get() {
$account_settings = "";
-
+
call_hooks('account_settings', $account_settings);
-
+
$email = \App::$account['account_email'];
- $attremail = (!strpos($email, '@')) ? 'disabled="disabled"' : '';
+ $attremail = ((!strpos($email, '@')) ? 'disabled="disabled"' : '');
$tpl = get_markup_template("settings_account.tpl");
$o .= replace_macros($tpl, array(
'$form_security_token' => get_form_security_token("settings_account"),
- '$title' => t('Account Settings'),
- '$origpass' => array('origpass', t('Current Password'), ' ',''),
- '$password1'=> array('npassword', t('Enter New Password'), '', ''),
- '$password2'=> array('confirm', t('Confirm New Password'), '', t('Leave password fields blank unless changing')),
- '$submit' => t('Submit'),
- '$email' => array('email', t('DId2 or Email Address:'), $email, '', '', $attremail),
- '$removeme' => t('Remove Account'),
- '$removeaccount' => t('Remove this account including all its channels'),
+ '$title' => t('Account Settings'),
+ '$origpass' => array('origpass', t('Current Password'), ' ',''),
+ '$password1' => array('npassword', t('Enter New Password'), '', ''),
+ '$password2' => array('confirm', t('Confirm New Password'), '', t('Leave password fields blank unless changing')),
+ '$submit' => t('Submit'),
+ '$email' => array('email', t('DId2 or Email Address:'), $email, '', '', $attremail),
+ '$email_hidden' => (($attremail) ? $email : ''),
+ '$removeme' => t('Remove Account'),
+ '$removeaccount' => t('Remove this account including all its channels'),
'$account_settings' => $account_settings
));
return $o;
diff --git a/Zotlabs/Module/Sharedwithme.php b/Zotlabs/Module/Sharedwithme.php
index 4211a3af8..c294079d4 100644
--- a/Zotlabs/Module/Sharedwithme.php
+++ b/Zotlabs/Module/Sharedwithme.php
@@ -19,13 +19,13 @@ class Sharedwithme extends Controller {
notice( t('Permission denied.') . EOL);
return;
}
-
+
$channel = \App::get_channel();
-
+
$is_owner = (local_channel() && (local_channel() == $channel['channel_id']));
$item_normal = item_normal();
-
+
//drop single file - localuser
if((argc() > 2) && (argv(2) === 'drop')) {
@@ -36,7 +36,7 @@ class Sharedwithme extends Controller {
goaway(z_root() . '/sharedwithme');
}
-
+
//drop all files - localuser
if((argc() > 1) && (argv(1) === 'dropall')) {
@@ -62,33 +62,34 @@ class Sharedwithme extends Controller {
dbesc($channel['channel_hash'])
);
+ $r = fetch_post_tags($r, true);
+
$items = [];
$ids = [];
if($r) {
-
+
foreach($r as $rr) {
- $object = json_decode($rr['obj'],true);
- $meta = self::get_meta($object);
+ $meta = get_iconfig($rr, 'attach', 'meta');
$item = [];
$item['id'] = $rr['id'];
$item['objfiletype'] = $meta['type'];
$item['objfiletypeclass'] = getIconFromType($meta['type']);
$item['objurl'] = $meta['path'] . '?f=&zid=' . $channel['xchan_addr'];
- $item['objfilename'] = $object['name'];
+ $item['objfilename'] = $meta['name'];
$item['objfilesize'] = userReadableSize($meta['size']);
$item['objedited'] = $meta['edited'];
$item['unseen'] = $rr['item_unseen'];
-
+
$items[] = $item;
-
+
if($item['unseen']) {
$ids[] = $rr['id'];
}
-
+
}
-
+
}
$ids = implode(',', $ids);
@@ -98,9 +99,9 @@ class Sharedwithme extends Controller {
intval(local_channel())
);
}
-
+
$o = '';
-
+
$o .= replace_macros(get_markup_template('sharedwithme.tpl'), array(
'$header' => t('Files: shared with me'),
'$name' => t('Name'),
@@ -111,27 +112,9 @@ class Sharedwithme extends Controller {
'$drop' => t('Remove this file'),
'$items' => $items
));
-
- return $o;
-
- }
-
- function get_meta($object) {
-
- $ret = [];
-
- if(! is_array($object['attachment']))
- return;
- foreach($object['attachment'] as $a) {
- if($a['name'] === 'zot.attach.meta') {
- $ret = $a['value'];
- break;
- }
- }
-
- return $ret;
+ return $o;
}
-
+
}
diff --git a/Zotlabs/Module/Sse.php b/Zotlabs/Module/Sse.php
index f87a19821..8b46dcafd 100644
--- a/Zotlabs/Module/Sse.php
+++ b/Zotlabs/Module/Sse.php
@@ -50,7 +50,7 @@ class Sse extends Controller {
self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify');
}
- $sleep_seconds = 3;
+ $sleep = 1000000; // microseconds
self::$sse_enabled = get_config('system', 'sse_enabled', 0);
@@ -63,17 +63,24 @@ class Sse extends Controller {
header("Connection: keep-alive");
header("X-Accel-Buffering: no");
- while(true) {
+ $i = 0;
- if(! self::$sse_id) {
+ while(true) {
- // Update chat presence indication
+ // reset counter for updating chatpresence about every minute
+ if (($i * $sleep)/60 > 1000000) {
+ $i = 0;
+ }
+ if(!self::$sse_id && $i === 0) {
+ // Update chat presence indication about once per minute
$r = q("select cp_id, cp_room from chatpresence where cp_xchan = '%s' and cp_client = '%s' and cp_room = 0 limit 1",
dbesc(self::$ob_hash),
dbesc($_SERVER['REMOTE_ADDR'])
);
+
$basic_presence = false;
+
if($r) {
$basic_presence = true;
q("update chatpresence set cp_last = '%s' where cp_id = %d",
@@ -81,7 +88,8 @@ class Sse extends Controller {
intval($r[0]['cp_id'])
);
}
- if(! $basic_presence) {
+
+ if(!$basic_presence) {
q("insert into chatpresence ( cp_xchan, cp_last, cp_status, cp_client)
values( '%s', '%s', '%s', '%s' ) ",
dbesc(self::$ob_hash),
@@ -94,9 +102,14 @@ class Sse extends Controller {
XConfig::Load(self::$ob_hash);
- $result = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
+ $result = [];
$lock = XConfig::Get(self::$ob_hash, 'sse', 'lock');
+ if (!$lock) {
+ $result = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
+ }
+
+
// We do not have the local_channel in the addon.
// Reset pubs here if the app is not installed.
if (self::$uid && (!(self::$vnotify & VNOTIFY_PUBS) || !Apps::system_app_installed(self::$uid, 'Public Stream'))) {
@@ -105,7 +118,7 @@ class Sse extends Controller {
}
}
- if($result && !$lock) {
+ if($result) {
echo "event: notifications\n";
echo 'data: ' . json_encode($result);
echo "\n\n";
@@ -121,6 +134,7 @@ class Sse extends Controller {
if(ob_get_length() > 0)
ob_end_flush();
+
flush();
if(connection_status() != CONNECTION_NORMAL || connection_aborted()) {
@@ -129,7 +143,9 @@ class Sse extends Controller {
break;
}
- sleep($sleep_seconds);
+ $i++;
+
+ usleep($sleep);
}
diff --git a/Zotlabs/Module/Sse_bs.php b/Zotlabs/Module/Sse_bs.php
index 4aabcafcb..052870cc9 100644
--- a/Zotlabs/Module/Sse_bs.php
+++ b/Zotlabs/Module/Sse_bs.php
@@ -173,6 +173,9 @@ class Sse_bs extends Controller {
$item_normal = item_normal();
+ // FEP-5624 filter approvals for comments
+ $approvals = " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject') ";
+
if ($notifications) {
$items = q("SELECT * FROM item
WHERE uid = %d
@@ -181,6 +184,7 @@ class Sse_bs extends Controller {
AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image')
AND author_xchan != '%s'
$item_normal
+ $approvals
$sql_extra
$sql_extra2
ORDER BY created DESC LIMIT $limit OFFSET $offset",
@@ -210,6 +214,7 @@ class Sse_bs extends Controller {
AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image')
AND author_xchan != '%s'
$item_normal
+ $approvals
$sql_extra LIMIT 100",
intval(self::$uid),
dbesc(self::$ob_hash)
@@ -253,6 +258,9 @@ class Sse_bs extends Controller {
$item_normal = item_normal();
+ // FEP-5624 filter approvals for comments
+ $approvals = " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject') ";
+
if ($notifications) {
$items = q("SELECT * FROM item
WHERE uid = %d
@@ -261,6 +269,7 @@ class Sse_bs extends Controller {
AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image')
AND author_xchan != '%s'
$item_normal
+ $approvals
$sql_extra
$sql_extra2
ORDER BY created DESC LIMIT $limit OFFSET $offset",
@@ -288,6 +297,7 @@ class Sse_bs extends Controller {
$r = q("SELECT id FROM item
WHERE uid = %d and item_unseen = 1 AND item_private = 2
$item_normal
+ $approvals
$sql_extra
AND author_xchan != '%s' LIMIT 100",
intval(self::$uid),
@@ -333,6 +343,9 @@ class Sse_bs extends Controller {
$item_normal = item_normal();
+ // FEP-5624 filter approvals for comments
+ $approvals = " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject') ";
+
if ($notifications) {
$items = q("SELECT * FROM item
WHERE uid = %d
@@ -341,6 +354,7 @@ class Sse_bs extends Controller {
AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image')
AND author_xchan != '%s'
$item_normal
+ $approvals
$sql_extra
$sql_extra2
ORDER BY created DESC LIMIT $limit OFFSET $offset",
@@ -368,6 +382,7 @@ class Sse_bs extends Controller {
$r = q("SELECT id FROM item
WHERE uid = %d and item_unseen = 1 AND item_wall = 1 AND item_private IN (0, 1)
$item_normal
+ $approvals
$sql_extra
AND author_xchan != '%s' LIMIT 100",
intval(self::$uid),
@@ -421,21 +436,30 @@ class Sse_bs extends Controller {
if(self::$xchans)
$sql_extra2 = " AND CASE WHEN verb = '" . ACTIVITY_SHARE . "' THEN owner_xchan ELSE author_xchan END IN (" . self::$xchans . ") ";
+ $uids = " AND uid IN ( " . $sys['channel_id'] . " ) ";
+
+ $site_firehose = get_config('system', 'site_firehose', 0);
+ if($site_firehose) {
+ $uids = " AND uid IN ( " . stream_perms_api_uids(PERMS_PUBLIC) . " ) AND item_private = 0 AND item_wall = 1 ";
+ }
+
$item_normal = item_normal();
+ // FEP-5624 filter approvals for comments
+ $approvals = " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject') ";
+
if ($notifications) {
$items = q("SELECT * FROM item
- WHERE uid = %d
+ WHERE true $uids
AND created <= '%s'
- AND item_unseen = 1
AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image')
AND author_xchan != '%s'
AND created > '%s'
$item_normal
+ $approvals
$sql_extra
$sql_extra2
ORDER BY created DESC LIMIT $limit OFFSET $offset",
- intval($sys['channel_id']),
dbescdate($_SESSION['sse_loadtime']),
dbesc(self::$ob_hash),
dbescdate($_SESSION['static_loadtime'])
@@ -454,17 +478,15 @@ class Sse_bs extends Controller {
else {
$result['pubs']['offset'] = -1;
}
-
-
}
$r = q("SELECT id FROM item
- WHERE uid = %d AND item_unseen = 1
+ WHERE true $uids
AND created > '%s'
$item_normal
+ $approvals
$sql_extra
AND author_xchan != '%s' LIMIT 100",
- intval($sys['channel_id']),
dbescdate($_SESSION['static_loadtime']),
dbesc(self::$ob_hash)
);
diff --git a/Zotlabs/Module/Vote.php b/Zotlabs/Module/Vote.php
index 4f909d33d..870fd760c 100644
--- a/Zotlabs/Module/Vote.php
+++ b/Zotlabs/Module/Vote.php
@@ -45,9 +45,7 @@ class Vote extends Controller {
if ($obj['oneOf']) {
foreach($obj['oneOf'] as $selection) {
- // logger('selection: ' . $selection);
- // logger('response: ' . $response);
- if($selection['name'] && $selection['name'] === $response) {
+ if($selection['name'] && htmlspecialchars_decode($selection['name']) === $response) {
$valid = true;
}
}
@@ -56,7 +54,7 @@ class Vote extends Controller {
$choices = [];
if ($obj['anyOf']) {
foreach ($obj['anyOf'] as $selection) {
- $choices[] = $selection['name'];
+ $choices[] = htmlspecialchars_decode($selection['name']);
}
foreach ($response as $res) {
if (! in_array($res,$choices)) {
diff --git a/Zotlabs/Update/_1254.php b/Zotlabs/Update/_1254.php
new file mode 100644
index 000000000..f316fe65b
--- /dev/null
+++ b/Zotlabs/Update/_1254.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1254 {
+
+ function run() {
+
+ dbq("START TRANSACTION");
+
+ if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
+ $r1 = dbq("CREATE TABLE IF NOT EXISTS workerq (
+ workerq_id bigserial NOT NULL,
+ workerq_priority smallint,
+ workerq_reservationid varchar(25) DEFAULT NULL,
+ workerq_processtimeout timestamp NOT NULL DEFAULT '0001-01-01 00:00:00',
+ workerq_data text,
+ workerq_uuid UUID NOT NULL,
+ PRIMARY KEY (workerq_id))"
+ );
+
+ $r2 = dbq("CREATE INDEX idx_workerq_priority ON workerq (workerq_priority)");
+ $r3 = dbq("CREATE INDEX idx_workerq_reservationid ON workerq (workerq_reservationid)");
+ $r4 = dbq("CREATE INDEX idx_workerq_processtimeout ON workerq (workerq_processtimeout)");
+ $r5 = dbq("CREATE INDEX idx_workerq_uuid ON workerq (workerq_uuid)");
+
+ $r = ($r1 && $r2 && $r3 && $r4 && $r5);
+ }
+ else {
+ $r = dbq("CREATE TABLE IF NOT EXISTS workerq (
+ workerq_id BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ workerq_priority smallint,
+ workerq_reservationid varchar(25) DEFAULT NULL,
+ workerq_processtimeout datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
+ workerq_data text,
+ workerq_uuid char(36) NOT NULL DEFAULT '',
+ KEY workerq_priority (workerq_priority),
+ KEY workerq_reservationid (workerq_reservationid),
+ KEY workerq_processtimeout (workerq_uuid),
+ KEY workerq_uuid (workerq_processtimeout)
+ ) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4"
+ );
+ }
+
+ if($r) {
+ dbq("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ q("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Update/_1255.php b/Zotlabs/Update/_1255.php
new file mode 100644
index 000000000..4f1da1a4a
--- /dev/null
+++ b/Zotlabs/Update/_1255.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Zotlabs\Update;
+
+class _1255 {
+
+ function run() {
+
+ dbq("START TRANSACTION");
+
+ if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
+ $r = q("ALTER TABLE workerq add workerq_cmd text NOT NULL DEFAULT ''");
+ }
+
+ if(ACTIVE_DBTYPE == DBTYPE_MYSQL) {
+ $r = q("ALTER TABLE workerq add workerq_cmd varchar(191) NOT NULL DEFAULT ''");
+ }
+
+ if($r) {
+ dbq("COMMIT");
+ return UPDATE_SUCCESS;
+ }
+
+ q("ROLLBACK");
+ return UPDATE_FAILED;
+
+ }
+
+}
diff --git a/Zotlabs/Web/SessionRedis.php b/Zotlabs/Web/SessionRedis.php
index 66eb7a02d..f32e6a4f4 100644
--- a/Zotlabs/Web/SessionRedis.php
+++ b/Zotlabs/Web/SessionRedis.php
@@ -42,7 +42,7 @@ class SessionRedis implements \SessionHandlerInterface {
}
}
-
+ #[\ReturnTypeWillChange]
function open($s, $n) {
return true;
@@ -53,6 +53,7 @@ class SessionRedis implements \SessionHandlerInterface {
// some which call read explicitly and some that do not. So we call it explicitly
// just after sid regeneration to force a record to exist.
+ #[\ReturnTypeWillChange]
function read($id) {
if ($id) {
@@ -67,7 +68,7 @@ class SessionRedis implements \SessionHandlerInterface {
return '';
}
-
+ #[\ReturnTypeWillChange]
function write($id, $data) {
// Pretend everything is hunky-dory, even though it isn't.
@@ -100,13 +101,13 @@ class SessionRedis implements \SessionHandlerInterface {
return true;
}
-
+ #[\ReturnTypeWillChange]
function close() {
return true;
}
-
+ #[\ReturnTypeWillChange]
function destroy ($id) {
$this->redis->del($id);
@@ -114,7 +115,7 @@ class SessionRedis implements \SessionHandlerInterface {
return true;
}
-
+ #[\ReturnTypeWillChange]
function gc($expire) {
return true;
diff --git a/Zotlabs/Widget/Admin.php b/Zotlabs/Widget/Admin.php
index 0a7a6925f..aa88de36a 100644
--- a/Zotlabs/Widget/Admin.php
+++ b/Zotlabs/Widget/Admin.php
@@ -32,6 +32,7 @@ class Admin {
'addons' => array(z_root() . '/admin/addons/', t('Addons'), 'addons'),
'themes' => array(z_root() . '/admin/themes/', t('Themes'), 'themes'),
'queue' => array(z_root() . '/admin/queue', t('Inspect queue'), 'queue'),
+ 'queueworker' => array(z_root() . '/admin/queueworker', t('Queueworker'), 'queueworker'),
'profs' => array(z_root() . '/admin/profs', t('Profile Fields'), 'profs'),
'dbsync' => array(z_root() . '/admin/dbsync/', t('DB updates'), 'dbsync')
];
diff --git a/Zotlabs/Widget/Categories.php b/Zotlabs/Widget/Categories.php
index b31856e48..7e6a3c6f7 100644
--- a/Zotlabs/Widget/Categories.php
+++ b/Zotlabs/Widget/Categories.php
@@ -3,7 +3,7 @@
/**
* * Name: Categories
* * Description: Display a menu with links to categories
- * * Requires: channel, articles, cards, cloud
+ * * Requires: channel, cloud
*/
namespace Zotlabs\Widget;
@@ -24,15 +24,16 @@ class Categories {
}
$cat = ((x($_REQUEST, 'cat')) ? htmlspecialchars($_REQUEST['cat'], ENT_COMPAT, 'UTF-8') : '');
- $srchurl = App::$query_string;
- $srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is', '', $srchurl), '&');
- $srchurl = str_replace(['?f=','&f=', '/?'], ['', '', ''], $srchurl);
+
+ // Discard queries from the current URL, as the template expects a base
+ // URL without any queries.
+ $base = substr(App::$query_string, 0, strcspn(App::$query_string, '?'));
if($files) {
- return filecategories_widget($srchurl, $cat);
+ return filecategories_widget($base, $cat);
}
- return categories_widget($srchurl, $cat);
+ return categories_widget($base, $cat);
}
}
diff --git a/Zotlabs/Widget/Channel_activities.php b/Zotlabs/Widget/Channel_activities.php
index 9acde591d..06080f8c8 100644
--- a/Zotlabs/Widget/Channel_activities.php
+++ b/Zotlabs/Widget/Channel_activities.php
@@ -26,7 +26,7 @@ class Channel_activities {
self::$channel = App::get_channel();
$o = '<div id="channel-activities" class="d-none overflow-hidden">';
- $o .= '<h2 class="mb-4">Welcome ' . self::$channel['channel_name'] . '!</h2>';
+ $o .= '<h2 class="mb-4">' . t('Welcome') . ' ' . self::$channel['channel_name'] . '!</h2>';
//$o .= 'Last login date: ' . get_pconfig(self::$uid, 'system', 'stored_login_date') . ' from ' . get_pconfig(self::$uid, 'system', 'stored_login_addr');
self::get_photos_activity();
@@ -43,7 +43,7 @@ class Channel_activities {
call_hooks('channel_activities_widget', $hookdata);
if (!$hookdata['activities']) {
- $o .= '<h3>No recent activity to display</h3>';
+ $o .= '<h3>' . t('No recent activities') . '</h3>';
$o .= '</div>';
return $o;
}
diff --git a/Zotlabs/Widget/Messages.php b/Zotlabs/Widget/Messages.php
index 0f57a8d85..8c413e16e 100644
--- a/Zotlabs/Widget/Messages.php
+++ b/Zotlabs/Widget/Messages.php
@@ -58,7 +58,8 @@ class Messages {
}
$channel = App::get_channel();
- $item_normal = str_replace('item.', 'i.', item_normal());
+ $item_normal_i = str_replace('item.', 'i.', item_normal());
+ $item_normal_c = str_replace('item.', 'c.', item_normal());
$entries = [];
$limit = 30;
$dummy_order_sql = '';
@@ -68,10 +69,12 @@ class Messages {
$vnotify_sql = '';
if (!($vnotify & VNOTIFY_LIKE)) {
- $vnotify_sql = " AND c.verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
+ $vnotify_sql_c = " AND c.verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
+ $vnotify_sql_i = " AND i.verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
}
elseif (!feature_enabled(local_channel(), 'dislike')) {
- $vnotify_sql = " AND c.verb NOT IN ('" . dbesc(ACTIVITY_DISLIKE) . "') ";
+ $vnotify_sql_c = " AND c.verb NOT IN ('" . dbesc(ACTIVITY_DISLIKE) . "') ";
+ $vnotify_sql_i = " AND i.verb NOT IN ('" . dbesc(ACTIVITY_DISLIKE) . "') ";
}
switch($type) {
@@ -88,13 +91,16 @@ class Messages {
$type_sql = ' AND i.item_private IN (0, 1) ';
}
+ // FEP-5624 filter approvals for comments
+ $approvals_c = " AND c.verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject') ";
+
$items = q("SELECT *,
- (SELECT count(*) FROM item c WHERE c.uid = %d AND c.parent = i.parent AND c.item_unseen = 1 AND c.item_thread_top = 0 $vnotify_sql) AS unseen_count
+ (SELECT count(*) FROM item c WHERE c.uid = %d AND c.parent = i.parent AND c.item_unseen = 1 AND c.item_thread_top = 0 $item_normal_c $approvals_c $vnotify_sql_c) AS unseen_count
FROM item i WHERE i.uid = %d
AND i.created <= '%s'
$type_sql
AND i.item_thread_top = 1
- $item_normal
+ $item_normal_i
ORDER BY i.created DESC $dummy_order_sql
LIMIT $limit OFFSET $offset",
intval(local_channel()),
diff --git a/Zotlabs/Widget/Pubtagcloud.php b/Zotlabs/Widget/Pubtagcloud.php
index db7ea02e7..90bf5eb97 100644
--- a/Zotlabs/Widget/Pubtagcloud.php
+++ b/Zotlabs/Widget/Pubtagcloud.php
@@ -22,24 +22,19 @@ class Pubtagcloud {
}
}
- $site_firehose = ((intval(get_config('system','site_firehose',0))) ? true : false);
- $net_firehose = ((get_config('system','disable_discover_tab',1)) ? false : true);
+ $net_firehose = ((get_config('system','disable_discover_tab',1)) ? false : true);
- if(! ($site_firehose || $net_firehose)) {
- return EMPTY_STR;
- }
+ if(!$net_firehose) {
+ return '';
+ }
- if($net_firehose) {
- $site_firehose = false;
- }
+ $site_firehose = ((intval(get_config('system','site_firehose',0))) ? true : false);
$safemode = get_xconfig(get_observer_hash(),'directory','safemode',1);
-
-
$limit = ((array_key_exists('limit', $arr)) ? intval($arr['limit']) : 75);
- return pubtagblock($net_firehose,$site_firehose, $limit, $trending, $safemode);
+ return pubtagblock($net_firehose, $site_firehose, $limit, $trending, $safemode);
return '';
}
diff --git a/boot.php b/boot.php
index 31f00a206..c2d9223a9 100644
--- a/boot.php
+++ b/boot.php
@@ -60,10 +60,10 @@ require_once('include/bbcode.php');
require_once('include/items.php');
define('PLATFORM_NAME', 'hubzilla');
-define('STD_VERSION', '7.9.9');
+define('STD_VERSION', '7.9.17');
define('ZOT_REVISION', '6.0');
-define('DB_UPDATE_VERSION', 1253);
+define('DB_UPDATE_VERSION', 1255);
define('PROJECT_BASE', __DIR__);
@@ -2045,24 +2045,8 @@ function proc_run() {
if (!$arr['run_cmd'])
return;
- if (count($args) && $args[0] === 'php')
+ if (count($args) && $args[0] === 'php') {
$args[0] = ((x(App::$config, 'system')) && (x(App::$config['system'], 'php_path')) && (strlen(App::$config['system']['php_path'])) ? App::$config['system']['php_path'] : 'php');
-
-
- // redirect proc_run statements of legacy daemon processes to the newer Daemon Master object class
- // We will keep this interface until everybody has transitioned. (2016-05-20)
-
- if (strstr($args[1], 'include/')) {
- // convert 'include/foo.php' to 'Foo'
- $orig = substr(ucfirst(substr($args[1], 8)), 0, -4);
- logger('proc_run_redirect: ' . $orig);
- if (file_exists('Zotlabs/Daemon/' . $orig . '.php')) {
- array_shift($args); // daemons are all run by php, pop it off the top of the array
- $args[0] = $orig; // replace with the new daemon name
- logger('Redirecting old proc_run interface: ' . print_r($args, true), LOGGER_DEBUG, LOG_DEBUG);
- Master::Summon($args); // summon the daemon
- return;
- }
}
$args = array_map('escapeshellarg', $args);
@@ -2284,6 +2268,7 @@ function load_pdl() {
'module' => App::$module,
'layout' => ''
];
+
/**
* @hooks load_pdl
* Called when we load a PDL file or description.
@@ -2297,20 +2282,26 @@ function load_pdl() {
$u = App::$comanche->get_channel_id();
$s = '';
- if ($u)
+ if ($u) {
$s = get_pconfig($u, 'system', $n);
- if (!$s)
+ }
+
+ if (!$s) {
$s = $layout;
+ }
- if ((!$s) && (($p = theme_include($n)) != ''))
+ if ((!$s) && (($p = theme_include($n)) != '')) {
$s = @file_get_contents($p);
- elseif (file_exists('addon/' . App::$module . '/' . $n))
+ }
+ elseif ((!$s) && file_exists('addon/' . App::$module . '/' . $n)) {
$s = @file_get_contents('addon/' . App::$module . '/' . $n);
+ }
$arr = [
'module' => App::$module,
'layout' => $s
];
+
call_hooks('alter_pdl', $arr);
$s = $arr['layout'];
diff --git a/include/attach.php b/include/attach.php
index fd418103d..fc146d008 100644
--- a/include/attach.php
+++ b/include/attach.php
@@ -2105,8 +2105,22 @@ function attach_store_item($channel, $observer, $file) {
$arr['verb'] = ACTIVITY_CREATE;
$arr['obj_type'] = $type;
$arr['title'] = $file['filename'];
- $body_str = sprintf(t('%s shared a %s with you'), '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]', '[zrl=' . $path . ']' . t('file') . '[/zrl]');
- $arr['body'] = $body_str;
+
+ if ($type === 'Image') {
+ $arr['body'] = '[zrl=' . $path . '][zmg=' . $path . ']' . $file['display_path'] . '[/zmg][/zrl]';
+ }
+ else {
+ $arr['attach'][] = [
+ 'href' => z_root() . '/attach/' . $resource_id,
+ 'length' => $file['filesize'],
+ 'type' => $file['filetype'],
+ 'title' => urlencode($file['filename']),
+ 'revision' => $file['revision']
+ ];
+ }
+
+ $body_str = sprintf((($type === 'Image') ? t('%s shared an %s with you') : t('%s shared a %s with you')), '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]', '[zrl=' . $path . ']' . (($type === 'Image') ? t('image') : t('file')) . '[/zrl]');
+ $arr['body'] .= $body_str;
$meta = [
'name' => $file['filename'],
diff --git a/include/auth.php b/include/auth.php
index 4f4d26a6c..125aedffd 100644
--- a/include/auth.php
+++ b/include/auth.php
@@ -94,7 +94,7 @@ function account_verify_password($login, $pass) {
$where = " where account_email = '" . dbesc($login) . "' ";
}
- $a = q("select * from account $where");
+ $a = dbq("select * from account $where");
if(! $a) {
return null;
}
@@ -112,6 +112,7 @@ function account_verify_password($login, $pass) {
}
if($channel) {
+
// Try the authentication plugin again since weve determined we are using the channel login instead of account login
$addon_auth = [
'username' => $account['account_email'],
diff --git a/include/event.php b/include/event.php
index 7c81d6934..b27504296 100644
--- a/include/event.php
+++ b/include/event.php
@@ -502,7 +502,6 @@ function ev_compare($a, $b) {
function event_store_event($arr) {
-
$arr['created'] = $arr['created'] ?? datetime_convert();
$arr['edited'] = $arr['edited'] ?? datetime_convert();
$arr['etype'] = $arr['etype'] ?? 'event';
@@ -533,7 +532,7 @@ function event_store_event($arr) {
$existing_event = null;
- if(isset($arr['event_hash'])) {
+ if(isset($arr['event_hash']) && $arr['event_hash']) {
$r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
dbesc($arr['event_hash']),
intval($arr['uid'])
@@ -543,7 +542,7 @@ function event_store_event($arr) {
}
}
- if(isset($arr['id'])) {
+ if(isset($arr['id']) && $arr['id']) {
$r = q("SELECT * FROM event WHERE id = %d AND uid = %d LIMIT 1",
intval($arr['id']),
intval($arr['uid'])
@@ -647,7 +646,6 @@ function event_store_event($arr) {
$hash = random_string(48);
}
}
-
$r = q("INSERT INTO event ( uid,aid,event_xchan,event_hash,created,edited,dtstart,dtend,summary,description,location,etype,
adjust,nofinish, event_status, event_status_date, event_percent, event_repeat, event_sequence, event_priority, event_vdata, allow_cid,allow_gid,deny_cid,deny_gid)
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', %d, '%s', %d, %d, '%s', '%s', '%s', '%s', '%s' ) ",
diff --git a/include/html2bbcode.php b/include/html2bbcode.php
index 0aa067371..c928b91b1 100644
--- a/include/html2bbcode.php
+++ b/include/html2bbcode.php
@@ -171,6 +171,7 @@ function html2bbcode($message)
node2bbcode($doc, 'i', array(), '[i]', '[/i]');
node2bbcode($doc, 'u', array(), '[u]', '[/u]');
node2bbcode($doc, 's', array(), '[s]', '[/s]');
+ node2bbcode($doc, 'mark', array(), '[mark]', '[/mark]');
node2bbcode($doc, 'big', array(), "[size=large]", "[/size]");
node2bbcode($doc, 'small', array(), "[size=small]", "[/size]");
diff --git a/include/hubloc.php b/include/hubloc.php
index bf5d8f120..0236e4ae7 100644
--- a/include/hubloc.php
+++ b/include/hubloc.php
@@ -79,9 +79,10 @@ function prune_hub_reinstalls() {
$r = q("select site_url from site where site_type = %d",
intval(SITE_TYPE_ZOT)
);
+
if($r) {
foreach($r as $rr) {
- $x = q("select count(*) as t, hubloc_sitekey, max(hubloc_connected) as c from hubloc where hubloc_url = '%s' group by hubloc_sitekey order by c",
+ $x = q("select count(*) as t, hubloc_sitekey, max(hubloc_connected) as c from hubloc where hubloc_url = '%s' and hubloc_network = 'zot6' group by hubloc_sitekey order by c",
dbesc($rr['site_url'])
);
@@ -155,8 +156,7 @@ function remove_obsolete_hublocs() {
logger('remove_obsolete_hublocs: removing ' . count($r) . ' hublocs.');
- $interval = ((get_config('system', 'delivery_interval') !== false)
- ? intval(get_config('system', 'delivery_interval')) : 2 );
+ $interval = get_config('queueworker', 'queue_interval', 500000);
foreach($r as $rr) {
q("update hubloc set hubloc_deleted = 1 where hubloc_id = %d",
@@ -168,8 +168,10 @@ function remove_obsolete_hublocs() {
);
if($x) {
Master::Summon(array('Notifier', 'refresh_all', $x[0]['channel_id']));
- if($interval)
- @time_sleep_until(microtime(true) + (float) $interval);
+
+ if($interval) {
+ usleep($interval);
+ }
}
}
}
diff --git a/include/items.php b/include/items.php
index 752251a7e..891f16b7f 100644
--- a/include/items.php
+++ b/include/items.php
@@ -97,7 +97,6 @@ function collect_recipients($item, &$private_envelope,$include_groups = true) {
$private_envelope = false;
require_once('include/channel.php');
- //$sys = get_sys_channel();
if(array_key_exists('public_policy',$item) && $item['public_policy'] !== 'self') {
@@ -114,7 +113,7 @@ function collect_recipients($item, &$private_envelope,$include_groups = true) {
$r = $hookinfo['recipients'];
} else {
$r = q("select abook_xchan, xchan_network from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and abook_pending = 0 and abook_archived = 0 ",
- intval($item['uid'])
+ intval($item['uid'])
);
}
@@ -141,18 +140,19 @@ function collect_recipients($item, &$private_envelope,$include_groups = true) {
}
}
}
-// we probably want to check that discovery channel delivery is allowed before uncommenting this.
-// if($policy === 'pub')
-// $recipients[] = $sys['xchan_hash'];
}
- // Forward to thread listeners, *unless* there is even a remote hint that the item
- // might have some privacy attached. This could be (for instance) an ActivityPub DM
+ // Forward to thread listeners and pubstream (sys channel), *unless* there is even
+ // a remote hint that the item might have some privacy attached.
+ // This could be (for instance) an ActivityPub DM
// in the middle of a public thread. Unless we can guarantee beyond all doubt that
// this is public, don't allow it to go to thread listeners.
if(! intval($item['item_private'])) {
+ $sys = get_sys_channel();
+ $recipients[] = $sys['xchan_hash'];
+
$r = ThreadListener::fetch_by_target($item['parent_mid']);
if($r) {
foreach($r as $rv) {
@@ -4124,21 +4124,24 @@ function posted_dates($uid,$wall) {
*/
function fetch_post_tags($items, $link = false) {
- $tag_finder = array();
- if($items) {
- foreach($items as $item) {
- if(is_array($item)) {
- if(array_key_exists('item_id',$item)) {
- if(! in_array($item['item_id'],$tag_finder))
- $tag_finder[] = $item['item_id'];
- }
- else {
- if(! in_array($item['id'],$tag_finder))
- $tag_finder[] = $item['id'];
- }
+ if (!is_array($items) || !$items) {
+ return $items;
+ }
+
+ $tag_finder = [];
+ foreach($items as $item) {
+ if(is_array($item)) {
+ if(array_key_exists('item_id',$item)) {
+ if(! in_array($item['item_id'],$tag_finder))
+ $tag_finder[] = $item['item_id'];
+ }
+ else {
+ if(! in_array($item['id'],$tag_finder))
+ $tag_finder[] = $item['id'];
}
}
}
+
$tag_finder_str = implode(', ', $tag_finder);
if(strlen($tag_finder_str)) {
@@ -4599,10 +4602,11 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$items = array();
}
+ /** @FIXME finish mark unseen sql
if ($parents_str && (isset($arr['mark_seen']) && $arr['mark_seen'])) {
$update_unseen = ' AND parent IN ( ' . dbesc($parents_str) . ' )';
- /** @FIXME finish mark unseen sql */
}
+ */
}
return $items;
diff --git a/include/network.php b/include/network.php
index 36859bc2f..f0642d8f7 100644
--- a/include/network.php
+++ b/include/network.php
@@ -1467,7 +1467,7 @@ function do_delivery($deliveries, $force = false) {
if(! (is_array($deliveries) && count($deliveries)))
return;
-
+ /*
$x = q("select count(outq_hash) as total from outq where outq_delivered = 0");
if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',3000)) && (! $force)) {
logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO);
@@ -1476,10 +1476,10 @@ function do_delivery($deliveries, $force = false) {
}
return;
}
+ */
- $interval = ((get_config('system','delivery_interval') !== false)
- ? intval(get_config('system','delivery_interval')) : 2 );
+ $interval = get_config('queueworker', 'queue_interval', 500000);
$deliveries_per_process = intval(get_config('system','delivery_batch_count'));
@@ -1487,7 +1487,7 @@ function do_delivery($deliveries, $force = false) {
$deliveries_per_process = 1;
- $deliver = array();
+ $deliver = [];
foreach($deliveries as $d) {
if(! $d)
@@ -1496,17 +1496,20 @@ function do_delivery($deliveries, $force = false) {
$deliver[] = $d;
if(count($deliver) >= $deliveries_per_process) {
- Zotlabs\Daemon\Master::Summon(array('Deliver',$deliver));
- $deliver = array();
- if($interval)
- @time_sleep_until(microtime(true) + (float) $interval);
+ Zotlabs\Daemon\Master::Summon(['Deliver', $deliver]);
+ $deliver = [];
+
+ if($interval) {
+ usleep($interval);
+ }
}
}
// catch any stragglers
- if($deliver)
- Zotlabs\Daemon\Master::Summon(array('Deliver',$deliver));
+ if($deliver) {
+ Zotlabs\Daemon\Master::Summon(['Deliver', $deliver]);
+ }
}
diff --git a/include/photos.php b/include/photos.php
index de9cc6b13..6e00ffbf0 100644
--- a/include/photos.php
+++ b/include/photos.php
@@ -64,7 +64,7 @@ function photo_upload($channel, $observer, $args) {
}
$ac = $acl->get();
-
+hz_syslog(print_r($ac,true));
$width = $height = 0;
if ($args['getimagesize']) {
@@ -405,7 +405,7 @@ function photo_upload($channel, $observer, $args) {
}
}
- $attribution = (($visitor) ? $visitor['xchan_url'] : $channel['xchan_url']);
+ $attribution = (($visitor) ? $visitor : $channel['xchan_url']);
//// Create item object
$object = [
diff --git a/include/plugin.php b/include/plugin.php
index ff5014c8b..ae73a847c 100644
--- a/include/plugin.php
+++ b/include/plugin.php
@@ -189,7 +189,7 @@ function plugin_is_installed($name) {
function reload_plugins() {
$plugins = get_config('system', 'addon');
if(strlen($plugins)) {
- $r = q("SELECT * FROM addon WHERE installed = 1");
+ $r = dbq("SELECT * FROM addon WHERE installed = 1");
if(count($r))
$installed = $r;
else
@@ -243,7 +243,7 @@ function reload_plugins() {
function plugins_installed_list() {
- $r = q("select * from addon where installed = 1 order by aname asc");
+ $r = dbq("select * from addon where installed = 1 order by aname asc");
return(($r) ? ids_to_array($r,'aname') : []);
}
@@ -313,7 +313,7 @@ function plugins_sync() {
*/
function visible_plugin_list() {
- $r = q("select * from addon where hidden = 0 order by aname asc");
+ $r = dbq("select * from addon where hidden = 0 order by aname asc");
$x = (($r) ? ids_to_array($r,'aname') : array());
$y = [];
if($x) {
@@ -392,7 +392,7 @@ function load_hooks() {
App::$hooks = [];
- $r = q("SELECT * FROM hook WHERE true ORDER BY priority DESC");
+ $r = dbq("SELECT * FROM hook WHERE true ORDER BY priority DESC");
if($r) {
foreach($r as $rv) {
@@ -613,6 +613,17 @@ function get_widget_info($widget){
"addon/$widget.php"
];
+ $addons = plugins_installed_list();
+
+ if ($addons) {
+ foreach ($addons as $name) {
+ $path = 'addon/' . $name . '/Widget/' . $ucwidget . '.php';
+ if (is_file($path)) {
+ $checkpaths[] = $path ;
+ }
+ }
+ }
+
$widget_found = false;
foreach ($checkpaths as $path) {
diff --git a/include/taxonomy.php b/include/taxonomy.php
index 1eded055a..671f96c2e 100644
--- a/include/taxonomy.php
+++ b/include/taxonomy.php
@@ -322,7 +322,7 @@ function pubtagblock($net,$site,$limit,$recent = 0,$safemode = 1, $type = TERM_H
if($r) {
$o = '<div class="tagblock widget"><h3>' . (($recent) ? t('Trending') : t('Tags')) . '</h3><div class="tags" align="center">';
foreach($r as $rr) {
- $o .= '<span class="tag'.$rr[2].'">#</span><a href="'.$link .'/' . '?f=&tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
+ $o .= '<span class="tag'.$rr[2].'">#</span><a href="'.$link . '?tag=' . urlencode($rr[0]).'" class="tag'.$rr[2].'">'.$rr[0].'</a> ' . "\r\n";
}
$o .= '</div></div>';
}
@@ -335,53 +335,55 @@ function pub_tagadelic($net, $site, $limit, $recent, $safemode, $type) {
$item_normal = item_normal();
$count = intval($limit);
- $sql_extra = "";
- if($site)
- $uids = " and item.uid in ( " . stream_perms_api_uids(PERMS_PUBLIC) . " ) and item_private = 0 and item_wall = 1 ";
- else {
- $sys = get_sys_channel();
- $uids = " and item.uid = " . intval($sys['channel_id']) . " ";
- $sql_extra = " and item_private = 0 ";
- }
-
- if($recent)
- $sql_extra .= " and item.created > NOW() - INTERVAL " . db_quoteinterval(intval($recent) . ' DAY') . " ";
-
-
- if($safemode) {
- $unsafetags = get_config('system','unsafepubtags', [ 'boobs', 'bot', 'rss', 'girl','girls', 'nsfw', 'sexy', 'nude' ]);
- if($unsafetags) {
- $sql_extra .= " and not term.term in ( " . stringify_array($unsafetags,true) . ") ";
- }
- }
-
- $key = __FUNCTION__ . "-" . md5($site . $recent . $safemode . $limit . $type);
-
- $content = Cache::get($key, '5 MINUTE');
- if(! $content) {
-
- $content = Cache::get($key, '1 MONTH');
- $arr = [
- "SELECT term, count(term) AS total FROM term LEFT JOIN item ON term.oid = item.id
- WHERE term.ttype = %d
- AND otype = %d
- AND item_type = %d
- $sql_extra $uids $item_normal
- GROUP BY term ORDER BY total DESC %s",
- intval($type),
- intval(TERM_OBJ_POST),
- intval(ITEM_TYPE_POST),
- (intval($count) ? "LIMIT $count" : '')
- ];
-
- \Zotlabs\Daemon\Master::Summon([ 'Cache_query', $key, base64_encode(json_encode($arr)) ]);
+ $sys = get_sys_channel();
+ $uids = " and item.uid = " . intval($sys['channel_id']) . " ";
+ $sql_extra = item_permissions_sql($sys['channel_id']);
+
+ $site_firehose_sql = '';
+
+ if ($site) {
+ $site_firehose_sql = " and owner_xchan in (select channel_hash from channel where channel_system = 0 and channel_removed = 0) ";
+ }
+
+ if($recent) {
+ $sql_extra .= " and item.created > NOW() - INTERVAL " . db_quoteinterval(intval($recent) . ' DAY') . " ";
+ }
+
+ if($safemode) {
+ $unsafetags = get_config('system','unsafepubtags', [ 'boobs', 'bot', 'rss', 'girl','girls', 'nsfw', 'sexy', 'nude' ]);
+ if($unsafetags) {
+ $sql_extra .= " and not term.term in ( " . stringify_array($unsafetags,true) . ") ";
}
+ }
+
+ $key = __FUNCTION__ . "-" . md5($site . $recent . $safemode . $limit . $type);
- $r = unserialize($content);
- if(! $r)
- return [];
+ $content = Cache::get($key, '5 MINUTE');
+ if(! $content) {
- return Zotlabs\Text\Tagadelic::calc($r);
+ $content = Cache::get($key, '1 MONTH');
+ $arr = [
+ "SELECT term, count(term) AS total FROM term LEFT JOIN item ON term.oid = item.id
+ WHERE term.ttype = %d
+ AND otype = %d
+ AND item_type = %d
+ AND item_private = 0
+ $uids $item_normal $site_firehose_sql $sql_extra
+ GROUP BY term ORDER BY total DESC %s",
+ intval($type),
+ intval(TERM_OBJ_POST),
+ intval(ITEM_TYPE_POST),
+ (intval($count) ? "LIMIT $count" : '')
+ ];
+
+ \Zotlabs\Daemon\Master::Summon([ 'Cache_query', $key, base64_encode(json_encode($arr)) ]);
+ }
+
+ $r = unserialize($content);
+ if(! $r)
+ return [];
+
+ return Zotlabs\Text\Tagadelic::calc($r);
}
diff --git a/include/text.php b/include/text.php
index af6ad7ea2..35ce465d6 100644
--- a/include/text.php
+++ b/include/text.php
@@ -303,6 +303,7 @@ function purify_html($s, $allow_position = false) {
$def->addElement('footer', 'Block', 'Flow', 'Common');
//Inline
$def->addElement('button', 'Inline', 'Inline', 'Common');
+ $def->addElement('mark', 'Inline', 'Inline', 'Common');
if($allow_position) {
@@ -2969,7 +2970,7 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true)
$newname = substr($name,1);
$newname = substr($newname,0,-1);
- $r = q("SELECT * FROM xchan WHERE ( xchan_addr = '%s' OR xchan_url = '%s' ) AND xchan_deleted = 0",
+ $r = q("SELECT * FROM xchan LEFT JOIN hubloc ON hubloc_hash = xchan_hash WHERE ( xchan_addr = '%s' OR xchan_url = '%s' ) AND xchan_deleted = 0 AND NOT xchan_network IN ('rss', 'anon', 'unknown') ORDER BY hubloc_id DESC",
dbesc($newname),
dbesc($newname)
);
@@ -2995,7 +2996,7 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true)
// select someone from this user's contacts by name
$r = q("SELECT * FROM abook LEFT JOIN xchan ON abook_xchan = xchan_hash
- WHERE xchan_name = '%s' AND abook_channel = %d AND xchan_deleted = 0",
+ WHERE xchan_name = '%s' AND abook_channel = %d AND xchan_deleted = 0 AND NOT xchan_network IN ('rss', 'anon', 'unknown')",
dbesc($newname),
intval($profile_uid)
);
@@ -3004,7 +3005,7 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true)
if((! $r) && strpos($newname,'@')) {
$r = q("SELECT * FROM xchan LEFT JOIN hubloc ON xchan_hash = hubloc_hash
- WHERE hubloc_addr = '%s' AND xchan_deleted = 0 ",
+ WHERE hubloc_addr = '%s' AND xchan_deleted = 0 AND NOT xchan_network IN ('rss', 'anon', 'unknown') ORDER BY hubloc_id DESC",
dbesc($newname)
);
}
@@ -3016,7 +3017,7 @@ function handle_tag(&$body, &$str_tags, $profile_uid, $tag, $in_network = true)
$newname = str_replace('%','',$newname);
$r = q("SELECT * FROM abook LEFT JOIN xchan ON abook_xchan = xchan_hash
- WHERE xchan_addr LIKE ('%s') AND abook_channel = %d AND xchan_deleted = 0",
+ WHERE xchan_addr LIKE ('%s') AND abook_channel = %d AND xchan_deleted = 0 AND NOT xchan_network IN ('rss', 'anon', 'unknown')",
dbesc(((strpos($newname,'@')) ? $newname : $newname . '@%')),
intval($profile_uid)
);
diff --git a/install/schema_mysql.sql b/install/schema_mysql.sql
index 80ae20d7b..0f407960d 100644
--- a/install/schema_mysql.sql
+++ b/install/schema_mysql.sql
@@ -1232,7 +1232,7 @@ CREATE TABLE IF NOT EXISTS `verify` (
CREATE TABLE IF NOT EXISTS `vote` (
`vote_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
- `vote_guid` varchar(191) NOT NULL,
+ `vote_guid` varchar(191) NOT NULL,
`vote_poll` int(11) NOT NULL DEFAULT 0 ,
`vote_element` int(11) NOT NULL DEFAULT 0 ,
`vote_result` text NOT NULL,
@@ -1616,3 +1616,17 @@ CREATE TABLE if not exists oauth_jwt (
subject VARCHAR(80),
public_key VARCHAR(2000) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE IF NOT EXISTS workerq (
+ workerq_id BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ workerq_priority smallint,
+ workerq_reservationid varchar(25) DEFAULT NULL,
+ workerq_processtimeout datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
+ workerq_data text,
+ workerq_uuid char(36) NOT NULL DEFAULT '',
+ workerq_cmd varchar(191) NOT NULL DEFAULT '',
+ KEY workerq_priority (workerq_priority),
+ KEY workerq_reservationid (workerq_reservationid),
+ KEY workerq_processtimeout (workerq_uuid),
+ KEY workerq_uuid (workerq_processtimeout)
+) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4
diff --git a/install/schema_postgres.sql b/install/schema_postgres.sql
index 96d0cc33c..5a97ebca1 100644
--- a/install/schema_postgres.sql
+++ b/install/schema_postgres.sql
@@ -1652,4 +1652,17 @@ CREATE TABLE oauth_jwt (
public_key VARCHAR(2000) NOT NULL
);
-
+CREATE TABLE IF NOT EXISTS workerq (
+ workerq_id bigserial NOT NULL,
+ workerq_priority smallint,
+ workerq_reservationid varchar(25) DEFAULT NULL,
+ workerq_processtimeout timestamp NOT NULL DEFAULT '0001-01-01 00:00:00',
+ workerq_data text,
+ workerq_uuid UUID NOT NULL,
+ workerq_cmd text NOT NULL DEFAULT '',
+ PRIMARY KEY (workerq_id)
+)
+CREATE INDEX idx_workerq_priority ON workerq (workerq_priority);
+CREATE INDEX idx_workerq_reservationid ON workerq (workerq_reservationid);
+CREATE INDEX idx_workerq_processtimeout ON workerq (workerq_processtimeout);
+CREATE INDEX idx_workerq_uuid ON workerq (workerq_uuid);
diff --git a/view/css/bootstrap-red.css b/view/css/bootstrap-red.css
index b0bd4fd75..f1296d7b2 100644
--- a/view/css/bootstrap-red.css
+++ b/view/css/bootstrap-red.css
@@ -65,7 +65,3 @@ label {
a {
text-decoration: none !important;
}
-
-.mark {
- background-color: yellow;
-}
diff --git a/view/css/conversation.css b/view/css/conversation.css
index 97d7857cc..d6a99f853 100644
--- a/view/css/conversation.css
+++ b/view/css/conversation.css
@@ -94,7 +94,6 @@
/* conversation */
-
/* conv_item */
.wall-item-head-new {
@@ -220,12 +219,6 @@ a.wall-item-name-link {
border-left: 0.2rem solid #007bff;
}
-.item-highlight .wall-item-head,
-.item-highlight .wall-item-content,
-.item-highlight .wall-item-tools {
- padding-left: 0.3rem;
-}
-
/* comment_item */
diff --git a/view/fr/invite.formal.tpl b/view/fr/invite.formal.tpl
index 404059af6..5d4d34caa 100644
--- a/view/fr/invite.formal.tpl
+++ b/view/fr/invite.formal.tpl
@@ -1,6 +1,6 @@
{{* tpl FR formel, pour inviter de manière plus polie des personnes comme des membres d'entreprise ou des partenaires professionnels *}}.
-Veuillez rejoindre le réseau social {{$nom du projet}}. Ce message contient les données essentielles pour la première connexion.
+Veuillez rejoindre le réseau social {{$projectname}}. Ce message contient les données essentielles pour la première connexion.
Le site est à rejoindre se trouve ici :
{{$invite_whereami}}
diff --git a/view/js/mod_cloud.js b/view/js/mod_cloud.js
index 7f9cb4fd1..e0f59beab 100644
--- a/view/js/mod_cloud.js
+++ b/view/js/mod_cloud.js
@@ -411,6 +411,9 @@ function UploadInit() {
var filedrag = $(".cloud-index.attach-drop");
var reload = false;
+ if (!$('#invisible-cloud-file-upload').length)
+ return;
+
$('#invisible-cloud-file-upload').fileupload({
url: 'file_upload',
dataType: 'json',
diff --git a/view/theme/redbasic/css/style.css b/view/theme/redbasic/css/style.css
index 20309b709..9069500d9 100644
--- a/view/theme/redbasic/css/style.css
+++ b/view/theme/redbasic/css/style.css
@@ -13,6 +13,7 @@
--bs-link-color: $link_colour;
--bs-link-hover-color: $link_hover_colour;
--bs-body-bg: $bgcolour;
+ --bs-highlight-bg: yellow;
}
.nav-tabs {
@@ -1790,11 +1791,6 @@ dl.bb-dl > dd > li {
opacity: 1;
}
-/* default highlighted text if not specified by schema: */
-span.default-highlight {
- background-color: yellow;
-}
-
.bootstrap-tagsinput {
width: 100%;
}
diff --git a/view/tpl/admin_site.tpl b/view/tpl/admin_site.tpl
index fa942baff..bad68361b 100644
--- a/view/tpl/admin_site.tpl
+++ b/view/tpl/admin_site.tpl
@@ -20,7 +20,7 @@
{{include file="field_input.tpl" field=$frontpage}}
{{include file="field_checkbox.tpl" field=$mirror_frontpage}}
{{include file="field_checkbox.tpl" field=$login_on_homepage}}
- {{include file="field_checkbox.tpl" field=$enable_context_help}}
+ {{** include file="field_checkbox.tpl" field=$enable_context_help **}}
{{if $directory_server}}
{{include file="field_select.tpl" field=$directory_server}}
{{/if}}
@@ -72,10 +72,10 @@
{{include file="field_input.tpl" field=$proxy}}
{{include file="field_input.tpl" field=$proxyuser}}
{{include file="field_input.tpl" field=$timeout}}
- {{include file="field_input.tpl" field=$delivery_interval}}
+ {{**include file="field_input.tpl" field=$delivery_interval**}}
{{include file="field_input.tpl" field=$delivery_batch_count}}
- {{include file="field_input.tpl" field=$force_queue}}
- {{include file="field_input.tpl" field=$poll_interval}}
+ {{**include file="field_input.tpl" field=$force_queue**}}
+ {{**include file="field_input.tpl" field=$poll_interval**}}
{{include file="field_input.tpl" field=$maxloadavg}}
{{include file="field_input.tpl" field=$default_expire_days}}
{{include file="field_input.tpl" field=$active_expire_days}}
diff --git a/view/tpl/settings_account.tpl b/view/tpl/settings_account.tpl
index c81f1abbb..2b942d694 100644
--- a/view/tpl/settings_account.tpl
+++ b/view/tpl/settings_account.tpl
@@ -8,6 +8,9 @@
<input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
<div class="section-content-tools-wrapper">
{{include file="field_input.tpl" field=$email}}
+ {{if $email_hidden}}
+ <input type='hidden' name='email' value='{{$email_hidden}}'>
+ {{/if}}
{{include file="field_password.tpl" field=$origpass}}
{{include file="field_password.tpl" field=$password1}}
{{include file="field_password.tpl" field=$password2}}