aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs
diff options
context:
space:
mode:
Diffstat (limited to 'Zotlabs')
-rw-r--r--Zotlabs/Daemon/Cron.php3
-rw-r--r--Zotlabs/Lib/Activity.php34
-rw-r--r--Zotlabs/Lib/DB_Upgrade.php31
-rw-r--r--Zotlabs/Lib/Libzot.php31
-rw-r--r--Zotlabs/Lib/PermissionDescription.php14
-rw-r--r--Zotlabs/Lib/ThreadItem.php28
-rw-r--r--Zotlabs/Lib/Traits/HelpHelperTrait.php47
-rw-r--r--Zotlabs/Module/Admin/Addons.php281
-rw-r--r--Zotlabs/Module/Appman.php28
-rw-r--r--Zotlabs/Module/Filer.php63
-rw-r--r--Zotlabs/Module/Help.php18
-rw-r--r--Zotlabs/Module/Hq.php1
-rw-r--r--Zotlabs/Module/Item.php9
-rw-r--r--Zotlabs/Module/Like.php5
-rw-r--r--Zotlabs/Module/Lockview.php2
-rw-r--r--Zotlabs/Module/Magic.php8
-rw-r--r--Zotlabs/Module/Notes.php30
-rw-r--r--Zotlabs/Module/Pubsites.php8
-rw-r--r--Zotlabs/Module/Settings/Conversation.php19
-rw-r--r--Zotlabs/Module/Sse.php63
-rw-r--r--Zotlabs/Storage/GitRepo.php159
-rw-r--r--Zotlabs/Web/WebServer.php4
-rw-r--r--Zotlabs/Widget/Activity_filter.php12
-rw-r--r--Zotlabs/Widget/Channel_activities.php8
-rw-r--r--Zotlabs/Widget/Helpindex.php4
-rw-r--r--Zotlabs/Widget/Hq_controls.php4
-rw-r--r--Zotlabs/Widget/Messages.php67
-rw-r--r--Zotlabs/Widget/Notes.php9
-rw-r--r--Zotlabs/Widget/Notifications.php14
-rw-r--r--Zotlabs/Widget/Permcats.php2
-rw-r--r--Zotlabs/Widget/Privacygroups.php2
-rw-r--r--Zotlabs/Widget/Rating.php6
-rw-r--r--Zotlabs/Widget/Tokens.php2
33 files changed, 349 insertions, 667 deletions
diff --git a/Zotlabs/Daemon/Cron.php b/Zotlabs/Daemon/Cron.php
index d2c863572..3f5ce28eb 100644
--- a/Zotlabs/Daemon/Cron.php
+++ b/Zotlabs/Daemon/Cron.php
@@ -178,9 +178,6 @@ class Cron {
}
}
- require_once('include/attach.php');
- attach_upgrade();
-
// once daily run birthday_updates and then expire in background
// FIXME: add birthday updates, both locally and for xprof for use
diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
index ae43a43b5..90d7af8e8 100644
--- a/Zotlabs/Lib/Activity.php
+++ b/Zotlabs/Lib/Activity.php
@@ -2116,6 +2116,13 @@ class Activity {
$s['expires'] = datetime_convert('UTC', 'UTC', $act->obj['expires']);
}
+ if ($act->objprop('location')) {
+ $s['location'] = ((isset($act->objprop('location')['name'])) ? html2plain(purify_html($act->objprop('location')['name'])) : '');
+ if (isset($act->objprop('location')['latitude'], $act->objprop('location')['longitude'])) {
+ $s['coord'] = floatval($act->objprop('location')['latitude']) . ' ' . floatval($act->objprop('location')['longitude']);
+ }
+ }
+
if (in_array($act->type, ['Invite', 'Create']) && $act->objprop('type') === 'Event') {
$s['mid'] = $s['parent_mid'] = $act->id;
}
@@ -3047,13 +3054,6 @@ class Activity {
}
$a = new ActivityStreams($n);
- if ($a->type === 'Announce' && is_array($a->obj)
- && array_key_exists('object', $a->obj) && array_key_exists('actor', $a->obj)) {
- // This is a relayed/forwarded Activity (as opposed to a shared/boosted object)
- // Reparse the encapsulated Activity and use that instead
- logger('relayed activity', LOGGER_DEBUG);
- $a = new ActivityStreams($a->obj);
- }
logger($a->debug(), LOGGER_DATA);
@@ -3062,6 +3062,24 @@ class Activity {
break;
}
+ if (in_array($a->type, ['Add', 'Remove'])
+ && is_array($a->obj)
+ && array_key_exists('object', $a->obj)
+ && array_key_exists('actor', $a->obj)
+ && !empty($a->tgt)) {
+
+ logger('unsupported collection operation', LOGGER_DEBUG);
+ return;
+ }
+
+ if ($a->type === 'Announce' && is_array($a->obj)
+ && array_key_exists('object', $a->obj) && array_key_exists('actor', $a->obj)) {
+ // This is a relayed/forwarded Activity (as opposed to a shared/boosted object)
+ // Reparse the encapsulated Activity and use that instead
+ logger('relayed activity', LOGGER_DEBUG);
+ $a = new ActivityStreams($a->obj);
+ }
+
$item = Activity::decode_note($a);
if (!$item) {
@@ -3464,7 +3482,7 @@ class Activity {
$ret[$collection] = $actor_record[$collection];
}
}
- if (array_path_exists('endpoints/sharedInbox', $actor_record) && $actor_record['endpoints']['sharedInbox']) {
+ if (!empty($actor_record['endpoints']['sharedInbox'])) {
$ret['sharedInbox'] = $actor_record['endpoints']['sharedInbox'];
}
diff --git a/Zotlabs/Lib/DB_Upgrade.php b/Zotlabs/Lib/DB_Upgrade.php
index 981c354a4..e11c2eb10 100644
--- a/Zotlabs/Lib/DB_Upgrade.php
+++ b/Zotlabs/Lib/DB_Upgrade.php
@@ -1,18 +1,35 @@
<?php
+/**
+ * A class to handle database schema upgrades.
+ *
+ * SPDX-FileCopyrightText: 2024 Hubzilla Community
+ * SPDX-FileContributor: Harald Eilertsen
+ *
+ * SPDX-License-Identifier: MIT
+ */
namespace Zotlabs\Lib;
use Zotlabs\Lib\Config;
+/**
+ * Upgrade the database schema if necessary.
+ *
+ * Compares the currently active database schema version with the version
+ * required for this version of Hubzilla, and performs the upgrade if needed.
+ *
+ * If the difference consists of more than one revision of the schema, each of
+ * the intermediate upgrades are performed in turn.
+ */
class DB_Upgrade {
- public $config_name = '';
- public $func_prefix = '';
-
- function __construct($db_revision) {
-
- $this->config_name = 'db_version';
- $this->func_prefix = '_';
+ /**
+ * Check the installed and required schema versions and perform the upgrade
+ * if necessary.
+ *
+ * @param int $db_version The required DB schema version.
+ */
+ public static function run(int $db_revision): void {
$build = Config::Get('system', 'db_version', 0);
if(! intval($build))
diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php
index bc944c97c..05134f433 100644
--- a/Zotlabs/Lib/Libzot.php
+++ b/Zotlabs/Lib/Libzot.php
@@ -1148,6 +1148,17 @@ class Libzot {
logger('Activity rejected: ' . print_r($data, true));
return;
}
+
+ if (in_array($AS->type, ['Add', 'Remove'])
+ && is_array($AS->obj)
+ && array_key_exists('object', $AS->obj)
+ && array_key_exists('actor', $AS->obj)
+ && !empty($AS->tgt)) {
+
+ logger('unsupported collection operation', LOGGER_DEBUG);
+ return;
+ }
+
if (is_array($AS->obj)) {
$item = Activity::decode_note($AS);
if (!$item) {
@@ -1158,6 +1169,7 @@ class Libzot {
else {
$item = [];
}
+
logger($AS->debug(), LOGGER_DATA);
}
@@ -2006,7 +2018,13 @@ class Libzot {
foreach ($items as $activity) {
$AS = new ActivityStreams($activity);
- if ($AS->is_valid() && $AS->type === 'Announce' && is_array($AS->obj)
+
+ if (!$AS->is_valid()) {
+ logger('Fetched activity rejected: ' . print_r($activity, true));
+ continue;
+ }
+
+ if ($AS->type === 'Announce' && is_array($AS->obj)
&& array_key_exists('object', $AS->obj) && array_key_exists('actor', $AS->obj)) {
// This is a relayed/forwarded Activity (as opposed to a shared/boosted object)
// Reparse the encapsulated Activity and use that instead
@@ -2014,9 +2032,14 @@ class Libzot {
$AS = new ActivityStreams($AS->obj);
}
- if (!$AS->is_valid()) {
- logger('Fetched activity rejected: ' . print_r($activity, true));
- continue;
+ if (in_array($AS->type, ['Add', 'Remove'])
+ && is_array($AS->obj)
+ && array_key_exists('object', $AS->obj)
+ && array_key_exists('actor', $AS->obj)
+ && !empty($AS->tgt)) {
+
+ logger('unsupported collection operation', LOGGER_DEBUG);
+ return;
}
// logger($AS->debug());
diff --git a/Zotlabs/Lib/PermissionDescription.php b/Zotlabs/Lib/PermissionDescription.php
index 51d5f890d..13df60b60 100644
--- a/Zotlabs/Lib/PermissionDescription.php
+++ b/Zotlabs/Lib/PermissionDescription.php
@@ -117,7 +117,7 @@ class PermissionDescription {
}
/**
- * Returns an icon css class name if an appropriate one is available, e.g. "fa-globe" for Public,
+ * Returns an icon css class name if an appropriate one is available, e.g. "bi-globe" for Public,
* otherwise returns empty string.
*
* @return string icon css class name (often FontAwesome)
@@ -125,12 +125,12 @@ class PermissionDescription {
public function get_permission_icon() {
switch($this->channel_perm) {
- case 0:/* only me */ return 'fa-eye-slash';
- case PERMS_PUBLIC: return 'fa-globe';
- case PERMS_NETWORK: return 'fa-share-alt-square'; // fa-share-alt-square is very similiar to the hubzilla logo, but we should create our own logo class to use
- case PERMS_SITE: return 'fa-sitemap';
- case PERMS_CONTACTS: return 'fa-group';
- case PERMS_SPECIFIC: return 'fa-list';
+ case 0:/* only me */ return 'bi-eye-slash';
+ case PERMS_PUBLIC: return 'bi-globe';
+ case PERMS_NETWORK: return 'bi-share'; // bi-share is very similiar to the hubzilla logo, but we should create our own logo class to use
+ case PERMS_SITE: return 'bi-geo';
+ case PERMS_CONTACTS: return 'bi-people';
+ case PERMS_SPECIFIC: return 'bi-list-ul';
case PERMS_AUTHED: return '';
case PERMS_PENDING: return '';
default: return '';
diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php
index 1082bf642..d21d85105 100644
--- a/Zotlabs/Lib/ThreadItem.php
+++ b/Zotlabs/Lib/ThreadItem.php
@@ -93,7 +93,7 @@ class ThreadItem {
$buttons = '';
$dropping = false;
$star = false;
- $isstarred = "unstarred fa-star-o";
+ $isstarred = "unstarred bi-star";
$is_comment = false;
$is_item = false;
$osparkle = '';
@@ -123,13 +123,13 @@ class ThreadItem {
$locktype = 0;
}
- $shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && (intval($item['item_private']) === 0)) ? true : false);
+ $shareable = ((local_channel() && $conv->get_profile_owner() == local_channel()) && (intval($item['item_private']) === 0));
// allow an exemption for sharing stuff from your private feeds
if($item['author']['xchan_network'] === 'rss')
$shareable = true;
- $repeatable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && (intval($item['item_private']) === 0) && (in_array($item['author']['xchan_network'], ['zot6', 'activitypub']))) ? true : false);
+ $repeatable = ((local_channel() && $conv->get_profile_owner() == local_channel()) && intval($item['item_private']) === 0 && in_array($item['author']['xchan_network'], ['zot6', 'activitypub']));
// @fixme
// Have recently added code to properly handle polls in group reshares by redirecting all of the poll responses to the group.
@@ -187,7 +187,7 @@ class ThreadItem {
$drop = [ 'dropping' => true, 'delete' => t('Admin Delete') ];
}
- $filer = ((($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) ? t("Save to Folder") : false);
+ $filer = (((local_channel() && $conv->get_profile_owner() === local_channel()) || (local_channel() && App::$module === 'pubstream')) ? t("Save to Folder") : false);
$profile_avatar = $item['author']['xchan_photo_s'];
$profile_link = chanlink_hash($item['author_xchan']);
@@ -204,9 +204,11 @@ class ThreadItem {
$response_verbs[] = 'dislike';
}
- $response_verbs[] = 'announce';
+ if ($repeatable) {
+ $response_verbs[] = 'announce';
+ }
- if(in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
+ if (in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
$response_verbs[] = 'attendyes';
$response_verbs[] = 'attendno';
$response_verbs[] = 'attendmaybe';
@@ -216,18 +218,18 @@ class ThreadItem {
}
}
- if($item['obj_type'] === 'Question') {
+ if ($item['obj_type'] === 'Question') {
$response_verbs[] = 'answer';
}
- if(! feature_enabled($conv->get_profile_owner(),'dislike'))
+ if (!feature_enabled($conv->get_profile_owner(),'dislike')) {
unset($conv_responses['dislike']);
+ }
$responses = get_responses($conv_responses,$response_verbs,$this,$item);
$my_responses = [];
foreach($response_verbs as $v) {
-
$my_responses[$v] = ((isset($conv_responses[$v][$item['mid'] . '-m'])) ? 1 : 0);
}
@@ -327,11 +329,13 @@ class ThreadItem {
$like = [];
$dislike = [];
$reply_to = [];
+ $reactions_allowed = false;
if($this->is_commentable() && $observer) {
$like = array( t("I like this \x28toggle\x29"), t("like"));
$dislike = array( t("I don't like this \x28toggle\x29"), t("dislike"));
- $reply_to = array( t("Reply on this comment"), t("reply"), t("Reply to"));
+ $reply_to = array( t("Reply to this comment"), t("reply"), t("Reply to"));
+ $reactions_allowed = true;
}
$share = [];
@@ -539,6 +543,8 @@ class ThreadItem {
'moderate_approve' => t('Approve'),
'moderate_delete' => t('Delete'),
'rtl' => in_array($item['lang'], rtl_languages()),
+ 'reactions_allowed' => $reactions_allowed,
+ 'reaction_str' => [t('Add yours'), t('Remove yours')]
);
$arr = array('item' => $item, 'output' => $tmp_item);
@@ -567,7 +573,7 @@ class ThreadItem {
if(($nb_children > $visible_comments) || ($thread_level > 1)) {
$result['children'][0]['comment_firstcollapsed'] = true;
$result['children'][0]['num_comments'] = $comment_count_txt['label'];
- $result['children'][0]['hide_text'] = sprintf( t('%s show all'), '<i class="fa fa-chevron-down"></i>');
+ $result['children'][0]['hide_text'] = t('show all');
if($thread_level > 1) {
$result['children'][$nb_children - 1]['comment_lastcollapsed'] = true;
}
diff --git a/Zotlabs/Lib/Traits/HelpHelperTrait.php b/Zotlabs/Lib/Traits/HelpHelperTrait.php
index b7711bbd5..63b0eb22e 100644
--- a/Zotlabs/Lib/Traits/HelpHelperTrait.php
+++ b/Zotlabs/Lib/Traits/HelpHelperTrait.php
@@ -15,6 +15,15 @@ trait HelpHelperTrait {
private string $file_type = '';
/**
+ * Associative array containing the detected language.
+ */
+ private array $lang = [
+ 'language' => 'en', //! Detected language, 2-letter ISO 639-1 code ("en")
+ 'from_url' => false, //! true if language from URL overrides browser default
+ 'missing' => false, //! true if topic not found in detected language
+ ];
+
+ /**
* Determines help language.
*
* If the language was specified in the URL, override the language preference
@@ -28,17 +37,15 @@ trait HelpHelperTrait {
$languages = $language_repository->getList();
if(array_key_exists(argv(1), $languages)) {
- $lang = argv(1);
- $from_url = true;
+ $this->lang['language'] = argv(1);
+ $this->lang['from_url'] = true;
} else {
- $lang = \App::$language;
- if(! isset($lang))
- $lang = 'en';
+ if(isset(\App::$language)) {
+ $this->lang['language'] = \App::$language;
+ }
- $from_url = false;
+ $this->lang['from_url'] = false;
}
-
- $this->lang = array('language' => $lang, 'from_url' => $from_url);
}
/**
@@ -53,10 +60,10 @@ trait HelpHelperTrait {
// Use local variable until we can use trait constants.
$valid_file_ext = ['md', 'bb', 'html'];
- $base_path = "doc/{$lang}/${base_path}";
+ $base_path_with_lang = "doc/{$lang}/${base_path}";
foreach ($valid_file_ext as $ext) {
- $path = "{$base_path}.{$ext}";
+ $path = "{$base_path_with_lang}.{$ext}";
if (file_exists($path)) {
$this->file_name = $path;
$this->file_type = $ext;
@@ -64,5 +71,25 @@ trait HelpHelperTrait {
break;
}
}
+
+ if (empty($this->file_name) && $lang !== 'en') {
+ $this->lang['missing'] = true;
+ $this->find_help_file($base_path, 'en');
+ }
+ }
+
+ public function missing_translation(): bool {
+ return !!$this->lang['missing'];
+ }
+
+ public function missing_translation_message(): string {
+ $prefered_language_name = get_language_name(
+ $this->lang['language'],
+ $this->lang['language']
+ );
+
+ return bbcode(
+ t("This page is not yet available in {$prefered_language_name}. See [observer.baseurl]/help/developer/developer_guide#Translations for information about how to help.")
+ );
}
}
diff --git a/Zotlabs/Module/Admin/Addons.php b/Zotlabs/Module/Admin/Addons.php
index b7cfb651c..681eed750 100644
--- a/Zotlabs/Module/Admin/Addons.php
+++ b/Zotlabs/Module/Admin/Addons.php
@@ -4,7 +4,6 @@ namespace Zotlabs\Module\Admin;
use App;
use \Zotlabs\Lib\Config;
-use \Zotlabs\Storage\GitRepo;
use \Michelf\MarkdownExtra;
class Addons {
@@ -24,227 +23,6 @@ class Addons {
goaway(z_root() . '/admin/addons/' . argv(2) );
}
- elseif(argc() > 2) {
- switch(argv(2)) {
- case 'updaterepo':
- if (array_key_exists('repoName', $_REQUEST)) {
- $repoName = $_REQUEST['repoName'];
- }
- else {
- json_return_and_die(array('message' => 'No repo name provided.', 'success' => false));
- }
- $extendDir = 'store/[data]/git/sys/extend';
- $addonDir = $extendDir . '/addon';
- if (!file_exists($extendDir)) {
- if (!mkdir($extendDir, 0770, true)) {
- logger('Error creating extend folder: ' . $extendDir);
- json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
- }
- else {
- if (!symlink(realpath('extend/addon'), $addonDir)) {
- logger('Error creating symlink to addon folder: ' . $addonDir);
- json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
- }
- }
- }
- $repoDir = 'store/[data]/git/sys/extend/addon/' . $repoName;
- if (!is_dir($repoDir)) {
- logger('Repo directory does not exist: ' . $repoDir);
- json_return_and_die(array('message' => 'Invalid addon repo.', 'success' => false));
- }
- if (!is_writable($repoDir)) {
- logger('Repo directory not writable to web server: ' . $repoDir);
- json_return_and_die(array('message' => 'Repo directory not writable to web server.', 'success' => false));
- }
- $git = new GitRepo('sys', null, false, $repoName, $repoDir);
- try {
- if ($git->pull()) {
- $files = array_diff(scandir($repoDir), array('.', '..'));
- foreach ($files as $file) {
- if (is_dir($repoDir . '/' . $file) && $file !== '.git') {
- $source = '../extend/addon/' . $repoName . '/' . $file;
- $target = realpath('addon/') . '/' . $file;
- unlink($target);
- if (!symlink($source, $target)) {
- logger('Error linking addons to /addon');
- json_return_and_die(array('message' => 'Error linking addons to /addon', 'success' => false));
- }
- }
- }
- json_return_and_die(array('message' => 'Repo updated.', 'success' => true));
- } else {
- json_return_and_die(array('message' => 'Error updating addon repo.', 'success' => false));
- }
- } catch (\PHPGit\Exception\GitException $e) {
- json_return_and_die(array('message' => 'Error updating addon repo.', 'success' => false));
- }
- break;
- case 'removerepo':
- if (array_key_exists('repoName', $_REQUEST)) {
- $repoName = $_REQUEST['repoName'];
- } else {
- json_return_and_die(array('message' => 'No repo name provided.', 'success' => false));
- }
- $extendDir = 'store/[data]/git/sys/extend';
- $addonDir = $extendDir . '/addon';
- if (!file_exists($extendDir)) {
- if (!mkdir($extendDir, 0770, true)) {
- logger('Error creating extend folder: ' . $extendDir);
- json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
- } else {
- if (!symlink(realpath('extend/addon'), $addonDir)) {
- logger('Error creating symlink to addon folder: ' . $addonDir);
- json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
- }
- }
- }
- $repoDir = 'store/[data]/git/sys/extend/addon/' . $repoName;
- if (!is_dir($repoDir)) {
- logger('Repo directory does not exist: ' . $repoDir);
- json_return_and_die(array('message' => 'Invalid addon repo.', 'success' => false));
- }
- if (!is_writable($repoDir)) {
- logger('Repo directory not writable to web server: ' . $repoDir);
- json_return_and_die(array('message' => 'Repo directory not writable to web server.', 'success' => false));
- }
- /// @TODO remove directory and unlink /addon/files
- if (rrmdir($repoDir)) {
- json_return_and_die(array('message' => 'Repo deleted.', 'success' => true));
- } else {
- json_return_and_die(array('message' => 'Error deleting addon repo.', 'success' => false));
- }
- break;
- case 'installrepo':
- if (array_key_exists('repoURL', $_REQUEST)) {
- require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies
- $repoURL = $_REQUEST['repoURL'];
- $extendDir = 'store/[data]/git/sys/extend';
- $addonDir = $extendDir . '/addon';
- if (!file_exists($extendDir)) {
- if (!mkdir($extendDir, 0770, true)) {
- logger('Error creating extend folder: ' . $extendDir);
- json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
- } else {
- if (!symlink(realpath('extend/addon'), $addonDir)) {
- logger('Error creating symlink to addon folder: ' . $addonDir);
- json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
- }
- }
- }
- if (!is_writable($extendDir)) {
- logger('Directory not writable to web server: ' . $extendDir);
- json_return_and_die(array('message' => 'Directory not writable to web server.', 'success' => false));
- }
- $repoName = null;
- if (array_key_exists('repoName', $_REQUEST) && $_REQUEST['repoName'] !== '') {
- $repoName = $_REQUEST['repoName'];
- } else {
- $repoName = GitRepo::getRepoNameFromURL($repoURL);
- }
- if (!$repoName) {
- logger('Invalid git repo');
- json_return_and_die(array('message' => 'Invalid git repo', 'success' => false));
- }
- $repoDir = $addonDir . '/' . $repoName;
- $tempRepoBaseDir = 'store/[data]/git/sys/temp/';
- $tempAddonDir = $tempRepoBaseDir . $repoName;
-
- if (!is_writable($addonDir) || !is_writable($tempAddonDir)) {
- logger('Temp repo directory or /extend/addon not writable to web server: ' . $tempAddonDir);
- json_return_and_die(array('message' => 'Temp repo directory not writable to web server.', 'success' => false));
- }
- rename($tempAddonDir, $repoDir);
-
- if (!is_writable(realpath('addon/'))) {
- logger('/addon directory not writable to web server: ' . $tempAddonDir);
- json_return_and_die(array('message' => '/addon directory not writable to web server.', 'success' => false));
- }
- $files = array_diff(scandir($repoDir), array('.', '..'));
- foreach ($files as $file) {
- if (is_dir($repoDir . '/' . $file) && $file !== '.git') {
- $source = '../extend/addon/' . $repoName . '/' . $file;
- $target = realpath('addon/') . '/' . $file;
- unlink($target);
- if (!symlink($source, $target)) {
- logger('Error linking addons to /addon');
- json_return_and_die(array('message' => 'Error linking addons to /addon', 'success' => false));
- }
- }
- }
- $git = new GitRepo('sys', $repoURL, false, $repoName, $repoDir);
- $repo = $git->probeRepo();
- json_return_and_die(array('repo' => $repo, 'message' => '', 'success' => true));
- }
- break;
- case 'addrepo':
- if (array_key_exists('repoURL', $_REQUEST)) {
- require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies
- $repoURL = $_REQUEST['repoURL'];
- $extendDir = 'store/[data]/git/sys/extend';
- $addonDir = $extendDir . '/addon';
- $tempAddonDir = realpath('store/[data]') . '/git/sys/temp';
- if (!file_exists($extendDir)) {
- if (!mkdir($extendDir, 0770, true)) {
- logger('Error creating extend folder: ' . $extendDir);
- json_return_and_die(array('message' => 'Error creating extend folder: ' . $extendDir, 'success' => false));
- } else {
- if (!symlink(realpath('extend/addon'), $addonDir)) {
- logger('Error creating symlink to addon folder: ' . $addonDir);
- json_return_and_die(array('message' => 'Error creating symlink to addon folder: ' . $addonDir, 'success' => false));
- }
- }
- }
- if (!is_dir($tempAddonDir)) {
- if (!mkdir($tempAddonDir, 0770, true)) {
- logger('Error creating temp plugin repo folder: ' . $tempAddonDir);
- json_return_and_die(array('message' => 'Error creating temp plugin repo folder: ' . $tempAddonDir, 'success' => false));
- }
- }
- $repoName = null;
- if (array_key_exists('repoName', $_REQUEST) && $_REQUEST['repoName'] !== '') {
- $repoName = $_REQUEST['repoName'];
- } else {
- $repoName = GitRepo::getRepoNameFromURL($repoURL);
- }
- if (!$repoName) {
- logger('Invalid git repo');
- json_return_and_die(array('message' => 'Invalid git repo: ' . $repoName, 'success' => false));
- }
- $repoDir = $tempAddonDir . '/' . $repoName;
- if (!is_writable($tempAddonDir)) {
- logger('Temporary directory for new addon repo is not writable to web server: ' . $tempAddonDir);
- json_return_and_die(array('message' => 'Temporary directory for new addon repo is not writable to web server.', 'success' => false));
- }
- // clone the repo if new automatically
- $git = new GitRepo('sys', $repoURL, true, $repoName, $repoDir);
-
- $remotes = $git->git->remote();
- $fetchURL = $remotes['origin']['fetch'];
- if ($fetchURL !== $git->url) {
- if (rrmdir($repoDir)) {
- $git = new GitRepo('sys', $repoURL, true, $repoName, $repoDir);
- } else {
- json_return_and_die(array('message' => 'Error deleting existing addon repo.', 'success' => false));
- }
- }
- $repo = $git->probeRepo();
- $repo['readme'] = $repo['manifest'] = null;
- foreach ($git->git->tree('master') as $object) {
- if ($object['type'] == 'blob' && (strtolower($object['file']) === 'readme.md' || strtolower($object['file']) === 'readme')) {
- $repo['readme'] = MarkdownExtra::defaultTransform($git->git->cat->blob($object['hash']));
- } else if ($object['type'] == 'blob' && strtolower($object['file']) === 'manifest.json') {
- $repo['manifest'] = $git->git->cat->blob($object['hash']);
- }
- }
- json_return_and_die(array('repo' => $repo, 'message' => '', 'success' => true));
- } else {
- json_return_and_die(array('message' => 'No repo URL provided', 'success' => false));
- }
- break;
- default:
- break;
- }
- }
}
/**
@@ -408,37 +186,6 @@ class Addons {
usort($plugins,'self::plugin_sort');
- $allowManageRepos = false;
- if(is_writable('extend/addon') && is_writable('store/[data]')) {
- $allowManageRepos = true;
- }
-
- $admin_plugins_add_repo_form= replace_macros(
- get_markup_template('admin_plugins_addrepo.tpl'), array(
- '$post' => 'admin/addons/addrepo',
- '$desc' => t('Enter the public git repository URL of the addon repo.'),
- '$repoURL' => array('repoURL', t('Addon repo git URL'), '', ''),
- '$repoName' => array('repoName', t('Custom repo name'), '', '', t('(optional)')),
- '$submit' => t('Download Addon Repo')
- )
- );
- $newRepoModalID = random_string(3);
- $newRepoModal = replace_macros(
- get_markup_template('generic_modal.tpl'), array(
- '$id' => $newRepoModalID,
- '$title' => t('Install new repo'),
- '$ok' => t('Install'),
- '$cancel' => t('Cancel')
- )
- );
-
- $reponames = $this->listAddonRepos();
- $addonrepos = [];
- foreach($reponames as $repo) {
- $addonrepos[] = array('name' => $repo, 'description' => '');
- /// @TODO Parse repo info to provide more information about repos
- }
-
$t = get_markup_template('admin_plugins.tpl');
return replace_macros($t, array(
'$title' => t('Administration'),
@@ -449,37 +196,9 @@ class Addons {
'$plugins' => $plugins,
'$disabled' => t('Disabled - version incompatibility'),
'$form_security_token' => get_form_security_token('admin_addons'),
- '$allowManageRepos' => $allowManageRepos,
- '$managerepos' => t('Manage Repos'),
- '$installedtitle' => t('Installed Addon Repositories'),
- '$addnewrepotitle' => t('Install a New Addon Repository'),
- '$expandform' => false,
- '$form' => $admin_plugins_add_repo_form,
- '$newRepoModal' => $newRepoModal,
- '$newRepoModalID' => $newRepoModalID,
- '$addonrepos' => $addonrepos,
- '$repoUpdateButton' => t('Update'),
- '$repoBranchButton' => t('Switch branch'),
- '$repoRemoveButton' => t('Remove')
));
}
- function listAddonRepos() {
- $addonrepos = [];
- $addonDir = 'extend/addon/';
- if(is_dir($addonDir)) {
- if ($handle = opendir($addonDir)) {
- while (false !== ($entry = readdir($handle))) {
- if ($entry != "." && $entry != "..") {
- $addonrepos[] = $entry;
- }
- }
- closedir($handle);
- }
- }
- return $addonrepos;
- }
-
static public function plugin_sort($a,$b) {
return(strcmp(strtolower($a[2]['name']),strtolower($b[2]['name'])));
}
diff --git a/Zotlabs/Module/Appman.php b/Zotlabs/Module/Appman.php
index 5f72d771b..8a842feda 100644
--- a/Zotlabs/Module/Appman.php
+++ b/Zotlabs/Module/Appman.php
@@ -16,21 +16,21 @@ class Appman extends \Zotlabs\Web\Controller {
if(isset($_POST['url']) && $_POST['url']) {
$arr = array(
'uid' => intval($_REQUEST['uid']),
- 'url' => escape_tags($_REQUEST['url']),
- 'guid' => escape_tags($_REQUEST['guid']),
- 'author' => escape_tags($_REQUEST['author']),
- 'addr' => escape_tags($_REQUEST['addr']),
- 'name' => escape_tags($_REQUEST['name']),
- 'desc' => escape_tags($_REQUEST['desc']),
- 'photo' => escape_tags($_REQUEST['photo']),
- 'version' => escape_tags($_REQUEST['version']),
- 'price' => escape_tags($_REQUEST['price']),
- 'page' => escape_tags($_REQUEST['page']),
- 'requires' => escape_tags($_REQUEST['requires']),
+ 'url' => escape_tags($_REQUEST['url'] ?? ''),
+ 'guid' => escape_tags($_REQUEST['guid'] ?? ''),
+ 'author' => escape_tags($_REQUEST['author'] ?? ''),
+ 'addr' => escape_tags($_REQUEST['addr'] ?? ''),
+ 'name' => escape_tags($_REQUEST['name'] ?? ''),
+ 'desc' => escape_tags($_REQUEST['desc'] ?? ''),
+ 'photo' => escape_tags($_REQUEST['photo'] ?? ''),
+ 'version' => escape_tags($_REQUEST['version'] ?? ''),
+ 'price' => escape_tags($_REQUEST['price'] ?? ''),
+ 'page' => escape_tags($_REQUEST['page'] ?? ''),
+ 'requires' => escape_tags($_REQUEST['requires'] ?? ''),
'system' => intval($_REQUEST['system']),
- 'plugin' => escape_tags($_REQUEST['plugin']),
- 'sig' => escape_tags($_REQUEST['sig']),
- 'categories' => escape_tags($_REQUEST['categories'])
+ 'plugin' => escape_tags($_REQUEST['plugin'] ?? ''),
+ 'sig' => escape_tags($_REQUEST['sig'] ?? ''),
+ 'categories' => escape_tags($_REQUEST['categories'] ?? '')
);
$_REQUEST['appid'] = Apps::app_install(local_channel(),$arr);
diff --git a/Zotlabs/Module/Filer.php b/Zotlabs/Module/Filer.php
index c2747e6c2..bf472eb67 100644
--- a/Zotlabs/Module/Filer.php
+++ b/Zotlabs/Module/Filer.php
@@ -1,43 +1,54 @@
<?php
namespace Zotlabs\Module;
-require_once('include/security.php');
-require_once('include/bbcode.php');
-require_once('include/items.php');
-
-
+use App;
class Filer extends \Zotlabs\Web\Controller {
function get() {
-
- if(! local_channel()) {
+
+ if(!local_channel()) {
killme();
}
-
- $term = unxmlify(trim($_GET['term']));
- $item_id = ((\App::$argc > 1) ? intval(\App::$argv[1]) : 0);
-
+
+ $term = unxmlify(trim($_GET['term'] ?? ''));
+ $item_id = ((App::$argc > 1) ? intval(App::$argv[1]) : 0);
+
logger('filer: tag ' . $term . ' item ' . $item_id);
-
+
if($item_id && strlen($term)){
+
+ $sys = get_sys_channel();
+
+ $r = q("SELECT * FROM item WHERE (uid = %d OR uid = %d) AND id = %d
+ and item_type in (0,6,7) and item_deleted = 0 and item_unpublished = 0
+ and item_delayed = 0 and item_pending_remove = 0 and item_blocked = 0 LIMIT 1",
+ intval(local_channel()),
+ intval($sys['channel_id']),
+ intval($item_id)
+ );
+
+ if ($r && $r[0]['uid'] === $sys['channel_id']) {
+ $r = [copy_of_pubitem(App::get_channel(), $r[0]['mid'])];
+ }
+
+ if(!$r) {
+ killme();
+ }
+
+ $item_id = $r[0]['id'];
+
// file item
store_item_tag(local_channel(),$item_id,TERM_OBJ_POST,TERM_FILE,$term,'');
-
+
// protect the entire conversation from periodic expiration
-
- $r = q("select parent from item where id = %d and uid = %d limit 1",
- intval($item_id),
+
+ q("update item set item_retained = 1, changed = '%s' where id = %d and uid = %d",
+ dbesc(datetime_convert()),
+ intval($r[0]['parent']),
intval(local_channel())
);
- if($r) {
- $x = q("update item set item_retained = 1, changed = '%s' where id = %d and uid = %d",
- dbesc(datetime_convert()),
- intval($r[0]['parent']),
- intval(local_channel())
- );
- }
- }
+ }
else {
$filetags = array();
$r = q("select distinct(term) from term where uid = %d and ttype = %d order by term asc",
@@ -55,10 +66,10 @@ class Filer extends \Zotlabs\Web\Controller {
'$title' => t('Save to Folder'),
'$cancel' => t('Cancel')
));
-
+
echo $o;
}
killme();
}
-
+
}
diff --git a/Zotlabs/Module/Help.php b/Zotlabs/Module/Help.php
index fd5cacee6..fc0ef2708 100644
--- a/Zotlabs/Module/Help.php
+++ b/Zotlabs/Module/Help.php
@@ -6,6 +6,7 @@ use Michelf\MarkdownExtra;
/**
* You can create local site resources in doc/Site.md and either link to doc/Home.md for the standard resources
* or use our include mechanism to include it on your local page.
+ *
*@code
* #include doc/Home.md;
*@endcode
@@ -19,14 +20,6 @@ class Help extends \Zotlabs\Web\Controller {
private string $heading_slug = '';
/**
- * Associative array containing the detected language.
- */
- public array $lang = [
- 'language' => 'en', //! Detected language, 2-letter ISO 639-1 code ("en")
- 'from_url' => false, //! true if language from URL overrides browser default
- ];
-
- /**
* Pre-check before processing request.
*
* Determine language requested, and ensure that a topic was requested.
@@ -36,8 +29,8 @@ class Help extends \Zotlabs\Web\Controller {
public function init() {
$this->determine_help_language();
- if (argc() === 1) {
- goaway("/help/{$this->lang['language']}/about/about");
+ if (empty($_REQUEST['search']) && argc() === 1) {
+ goaway("/help/about/about");
killme();
}
}
@@ -69,6 +62,7 @@ class Help extends \Zotlabs\Web\Controller {
$o .= '</div>';
$o .= '<div class="section-content-wrapper">';
+ require_once('include/help.php');
$r = search_doc_files($_REQUEST['search']);
if($r) {
$o .= '<ul class="help-searchlist">';
@@ -160,6 +154,10 @@ class Help extends \Zotlabs\Web\Controller {
array_shift($args);
}
+ if (empty($args)) {
+ goaway("/help/about/about");
+ }
+
// Keep the first remaining arg as the heading slug
$this->heading_slug = $args[0];
diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php
index c8e6efe38..51caa179c 100644
--- a/Zotlabs/Module/Hq.php
+++ b/Zotlabs/Module/Hq.php
@@ -230,6 +230,7 @@ class Hq extends \Zotlabs\Web\Controller {
$options['offset'] = $_REQUEST['offset'] ?? 0;
$options['type'] = $_REQUEST['type'] ?? '';
$options['author'] = ((isset($_REQUEST['author'])) ? urldecode($_REQUEST['author']) : '');
+ $options['file'] = ((isset($_REQUEST['file'])) ? urldecode($_REQUEST['file']) : '');
$ret = Messages::get_messages_page($options);
diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php
index 3d13655d2..d96cfd822 100644
--- a/Zotlabs/Module/Item.php
+++ b/Zotlabs/Module/Item.php
@@ -837,8 +837,10 @@ class Item extends Controller {
if ($results) {
- // Set permissions based on tag replacements
- set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $private, $parent_item);
+ // Set permissions based on tag replacements only if not editing an existing post
+ if (!$orig_post) {
+ set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $private, $parent_item);
+ }
foreach ($results as $result) {
$success = $result['success'];
@@ -1058,7 +1060,7 @@ class Item extends Controller {
$obj['id'] = $mid;
$obj['diaspora:guid'] = $uuid;
$obj['attributedTo'] = channel_url($channel);
- $obj['published'] = $created;
+ $obj['published'] = datetime_convert('UTC', 'UTC', $created, ATOM_TIME);
$obj['name'] = $title;
$datarray['obj'] = $obj;
@@ -1429,7 +1431,6 @@ class Item extends Controller {
require_once('include/items.php');
-
$i = q("select id, uid, item_origin, author_xchan, owner_xchan, source_xchan, item_type from item where id = %d limit 1",
intval(argv(2))
);
diff --git a/Zotlabs/Module/Like.php b/Zotlabs/Module/Like.php
index 4460900a8..d493742e7 100644
--- a/Zotlabs/Module/Like.php
+++ b/Zotlabs/Module/Like.php
@@ -569,6 +569,11 @@ class Like extends Controller {
call_hooks('post_local_end', $arr);
+ if ($is_rsvp && in_array($verb, ['attendyes', 'attendmaybe'])) {
+ event_addtocal($item_id, local_channel());
+ }
+
+
$r = q("select * from item where id = %d",
intval($post_id)
);
diff --git a/Zotlabs/Module/Lockview.php b/Zotlabs/Module/Lockview.php
index f3ae07f74..4b708a1aa 100644
--- a/Zotlabs/Module/Lockview.php
+++ b/Zotlabs/Module/Lockview.php
@@ -227,7 +227,7 @@ class Lockview extends Controller {
$allowed_xchans = array_unique($allowed_xchans);
foreach ($atokens as $atoken) {
if (in_array($atoken['xchan_hash'], $allowed_xchans)) {
- $guest_access_list[] = '<div class="dropdown-item d-flex justify-content-between cursor-pointer" title="' . sprintf(t('Click to copy link to this ressource for guest %s to clipboard'), $atoken['xchan_name']) . '" data-token="' . $url . '?zat=' . $atoken['atoken_token'] . '" onclick="navigator.clipboard.writeText(this.dataset.token); toast(\'' . t('Link copied') . '\', \'info\');"><span>' . $atoken['xchan_name'] . '</span><i class="fa fa-copy p-1"></i></div>';
+ $guest_access_list[] = '<div class="dropdown-item d-flex justify-content-between cursor-pointer" title="' . sprintf(t('Click to copy link to this ressource for guest %s to clipboard'), $atoken['xchan_name']) . '" data-token="' . $url . '?zat=' . $atoken['atoken_token'] . '" onclick="navigator.clipboard.writeText(this.dataset.token); toast(\'' . t('Link copied') . '\', \'info\');"><span>' . $atoken['xchan_name'] . '</span><i class="bi bi-copy p-1"></i></div>';
}
}
}
diff --git a/Zotlabs/Module/Magic.php b/Zotlabs/Module/Magic.php
index 8259f7d39..deda4255d 100644
--- a/Zotlabs/Module/Magic.php
+++ b/Zotlabs/Module/Magic.php
@@ -40,7 +40,11 @@ class Magic extends Controller {
goaway($dest);
}
- $basepath = $parsed['scheme'] . '://' . $parsed['host'] . (isset($parsed['port']) ? ':' . $parsed['port'] : '');
+ $basepath = unparse_url(array_filter(
+ $parsed,
+ fn (string $key) => in_array($key, ['scheme', 'host', 'port']),
+ ARRAY_FILTER_USE_KEY
+ ));
$owapath = SConfig::get($basepath,'system','openwebauth', $basepath . '/owa');
// This is ready-made for a plugin that provides a blacklist or "ask me" before blindly authenticating.
@@ -106,7 +110,7 @@ class Magic extends Controller {
$headers['Content-Type'] = 'application/x-zot+json' ;
$headers['X-Open-Web-Auth'] = random_string();
$headers['Host'] = $parsed['host'];
- $headers['(request-target)'] = 'get ' . '/owa';
+ $headers['(request-target)'] = 'get /owa';
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel),true,'sha512');
$redirects = 0;
diff --git a/Zotlabs/Module/Notes.php b/Zotlabs/Module/Notes.php
index 2fd719f25..ba693e4f2 100644
--- a/Zotlabs/Module/Notes.php
+++ b/Zotlabs/Module/Notes.php
@@ -13,31 +13,34 @@ class Notes extends Controller {
function post() {
- if(! local_channel())
- return EMPTY_STR;
+ if(!local_channel()) {
+ return;
+ }
- if(! Apps::system_app_installed(local_channel(), 'Notes'))
- return EMPTY_STR;
+ if(!Apps::system_app_installed(local_channel(), 'Notes')) {
+ return;
+ }
$ret = [
'success' => false,
'html' => ''
];
-
- if(array_key_exists('note_text',$_REQUEST)) {
+ if (array_key_exists('note_text',$_REQUEST)) {
$body = escape_tags($_REQUEST['note_text']);
// I've had my notes vanish into thin air twice in four years.
// Provide a backup copy if there were contents previously
// and there are none being saved now.
- if(! $body) {
- $old_text = get_pconfig(local_channel(),'notes','text');
- if($old_text)
- set_pconfig(local_channel(),'notes','text.bak',$old_text);
+ if(!$body) {
+ $old_text = get_pconfig(local_channel(), 'notes', 'text');
+ if ($old_text) {
+ set_pconfig(local_channel(), 'notes', 'text.bak', $old_text);
+ }
}
- set_pconfig(local_channel(),'notes','text',$body);
+
+ set_pconfig(local_channel(), 'notes', 'text', $body);
$ret['html'] = bbcode($body, ['tryoembed' => false]);
$ret['success'] = true;
@@ -55,8 +58,9 @@ class Notes extends Controller {
}
function get() {
- if(! local_channel())
+ if(!local_channel()) {
return EMPTY_STR;
+ }
if(! Apps::system_app_installed(local_channel(), 'Notes')) {
//Do not display any associated widgets at this point
@@ -65,6 +69,8 @@ class Notes extends Controller {
return Apps::app_render($papp, 'module');
}
+ App::$profile_uid = local_channel();
+
$w = new \Zotlabs\Widget\Notes;
$arr = ['app' => true];
diff --git a/Zotlabs/Module/Pubsites.php b/Zotlabs/Module/Pubsites.php
index cbaa66042..f58b4adff 100644
--- a/Zotlabs/Module/Pubsites.php
+++ b/Zotlabs/Module/Pubsites.php
@@ -49,18 +49,18 @@ class Pubsites extends \Zotlabs\Web\Controller {
}
$m = parse_url($jj['url']);
$host = strtolower(substr($jj['url'],strpos($jj['url'],'://')+3));
- $rate_links = ((local_channel()) ? '<td><a href="rate?f=&target=' . $host . '" class="btn-btn-default"><i class="fa fa-check-square-o"></i> ' . t('Rate') . '</a></td>' : '');
+ $rate_links = ((local_channel()) ? '<td><a href="rate?f=&target=' . $host . '" class="btn-btn-default"><i class="bi bi-check-square"></i> ' . t('Rate') . '</a></td>' : '');
$location = '';
if(!empty($jj['location'])) {
- $location = '<p title="' . t('Location') . '" style="margin: 5px 5px 0 0; text-align: right"><i class="fa fa-globe"></i> ' . $jj['location'] . '</p>';
+ $location = '<p title="' . t('Location') . '" style="margin: 5px 5px 0 0; text-align: right"><i class="bi bi-globe"></i> ' . $jj['location'] . '</p>';
}
else {
$location = '<br />&nbsp;';
}
$urltext = str_replace(array('https://'), '', $jj['url']);
- $o .= '<tr><td><a href="'. (($jj['sellpage']) ? $jj['sellpage'] : $jj['url'] . '/register' ) . '" ><i class="fa fa-link"></i> ' . $urltext . '</a>' . $location . '</td><td>' . $jj['access'] . '</td><td>' . $jj['register'] . '</td><!--td>' . '<a target="stats" href="https://hubchart-tarine.rhcloud.com/hub.jsp?hubFqdn=' . $m['host'] . '"><i class="fa fa-area-chart"></i></a></td--><td>' . ucwords($jj['project']) . (($jj['version']) ? ' ' . $jj['version'] : '') . '</td>';
+ $o .= '<tr><td><a href="'. (($jj['sellpage']) ? $jj['sellpage'] : $jj['url'] . '/register' ) . '" ><i class="bi bi-link-45deg"></i> ' . $urltext . '</a>' . $location . '</td><td>' . $jj['access'] . '</td><td>' . $jj['register'] . '</td><!--td>' . '<a target="stats" href="https://hubchart-tarine.rhcloud.com/hub.jsp?hubFqdn=' . $m['host'] . '"><i class="bi bi-graph-up"></i></a></td--><td>' . ucwords($jj['project']) . (($jj['version']) ? ' ' . $jj['version'] : '') . '</td>';
if($rating_enabled)
- $o .= '<td><a href="ratings/' . $host . '" class="btn-btn-default"><i class="fa fa-eye"></i> ' . t('View') . '</a></td>' . $rate_links ;
+ $o .= '<td><a href="ratings/' . $host . '" class="btn-btn-default"><i class="bi bi-eye"></i> ' . t('View') . '</a></td>' . $rate_links ;
$o .= '</tr>';
}
}
diff --git a/Zotlabs/Module/Settings/Conversation.php b/Zotlabs/Module/Settings/Conversation.php
index aa0ff6a7e..5f3d903a8 100644
--- a/Zotlabs/Module/Settings/Conversation.php
+++ b/Zotlabs/Module/Settings/Conversation.php
@@ -11,24 +11,19 @@ class Conversation {
$module = substr(strrchr(strtolower(static::class), '\\'), 1);
check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module);
-
+
$features = get_module_features($module);
process_module_features_post(local_channel(), $features, $_POST);
-
+
Libsync::build_sync_packet();
-
- if($_POST['aj']) {
- if($_POST['auto_update'] == 1)
- info(t('Settings saved.') . EOL);
- else
- info(t('Settings saved. Reload page please.') . EOL);
+ if($_POST['aj']) {
killme();
}
- else {
- return;
- }
+
+ return;
+
}
function get() {
@@ -48,7 +43,7 @@ class Conversation {
'$features' => process_module_features_get(local_channel(), $features),
'$submit' => t('Submit')
));
-
+
if($aj) {
echo $o;
killme();
diff --git a/Zotlabs/Module/Sse.php b/Zotlabs/Module/Sse.php
index daf344f2d..fda2f2be4 100644
--- a/Zotlabs/Module/Sse.php
+++ b/Zotlabs/Module/Sse.php
@@ -19,13 +19,14 @@ class Sse extends Controller {
function init() {
+ // This is important!
+ session_write_close();
+ ignore_user_abort(true);
+
if((observer_prohibited(true))) {
killme();
}
- // this is important!
- ignore_user_abort(true);
-
self::$uid = local_channel();
self::$ob_hash = get_observer_hash();
self::$sse_id = false;
@@ -102,19 +103,9 @@ class Sse extends Controller {
$lock = XConfig::Get(self::$ob_hash, 'sse', 'lock');
if (!$lock) {
- $result_db = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
- }
-
- if (!empty($_SESSION['sysmsg'])) {
- $result['notice']['notifications'] = $_SESSION['sysmsg'];
+ $result = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
}
- if (!empty($_SESSION['sysmsg_info'])) {
- $result['info']['notifications'] = $_SESSION['sysmsg_info'];
- }
-
- $result = array_merge($result, $result_db);
-
// 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'))) {
@@ -137,8 +128,9 @@ class Sse extends Controller {
if (connection_status() != CONNECTION_NORMAL || connection_aborted()) {
- // IMPORTANT: in case the channel was changed we need to reset the
- // session here to it's current stored state.
+ // In case session_write_close() failed for some reason and
+ // the channel was changed we might need to reset the
+ // session to it's current stored state here.
// Otherwise the uid might switch back to the previous value
// in the background.
@@ -147,9 +139,6 @@ class Sse extends Controller {
XConfig::Set(self::$ob_hash, 'sse', 'timestamp', NULL_DATE);
XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
- $_SESSION['sysmsg'] = [];
- $_SESSION['sysmsg_info'] = [];
-
if (ob_get_length() > 0) {
ob_end_flush();
}
@@ -168,12 +157,7 @@ class Sse extends Controller {
usleep($sleep);
if ($result) {
- if ($result_db) {
- XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
- }
-
- $_SESSION['sysmsg'] = [];
- $_SESSION['sysmsg_info'] = [];
+ XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
}
$i++;
@@ -184,7 +168,7 @@ class Sse extends Controller {
else {
// Fallback to traditional polling
- if(! self::$sse_id) {
+ if(!self::$sse_id) {
// Update chat presence indication
@@ -193,14 +177,14 @@ class Sse extends Controller {
dbesc($_SERVER['REMOTE_ADDR'])
);
$basic_presence = false;
- if($r) {
+ if ($r) {
$basic_presence = true;
q("update chatpresence set cp_last = '%s' where cp_id = %d",
dbesc(datetime_convert()),
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),
@@ -212,34 +196,17 @@ class Sse extends Controller {
}
$result = [];
- $result_db = [];
XConfig::Load(self::$ob_hash);
$lock = XConfig::Get(self::$ob_hash, 'sse', 'lock');
if (!$lock) {
- $result_db = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
- }
-
- if (!empty($_SESSION['sysmsg'])) {
- $result['notice']['notifications'] = $_SESSION['sysmsg'];
- }
-
- if (!empty($_SESSION['sysmsg_info'])) {
- $result['info']['notifications'] = $_SESSION['sysmsg_info'];
+ $result = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
}
- $result = array_merge($result, $result_db);
-
- if($result) {
- if ($result_db) {
- XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
- }
-
- $_SESSION['sysmsg'] = [];
- $_SESSION['sysmsg_info'] = [];
-
+ if ($result) {
+ XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
json_return_and_die($result);
}
diff --git a/Zotlabs/Storage/GitRepo.php b/Zotlabs/Storage/GitRepo.php
deleted file mode 100644
index 306abc0ba..000000000
--- a/Zotlabs/Storage/GitRepo.php
+++ /dev/null
@@ -1,159 +0,0 @@
-<?php
-
-namespace Zotlabs\Storage;
-
-use PHPGit\Git as PHPGit;
-
-require __DIR__ . '/../../library/PHPGit.autoload.php'; // Load PHPGit dependencies
-
-/**
- * Wrapper class for PHPGit class for git repositories managed by Hubzilla
- *
- * @author Andrew Manning <andrewmanning@grid.reticu.li>
- */
-class GitRepo {
-
- public $url = null;
- public $name = null;
- private $path = null;
- private $channel = null;
- public $git = null;
- private $repoBasePath = null;
-
- function __construct($channel = 'sys', $url = null, $clone = false, $name = null, $path = null) {
-
- if ($channel === 'sys' && !is_site_admin()) {
- logger('Only admin can use channel sys');
- return null;
- }
-
- $this->repoBasePath = __DIR__ . '/../../store/git';
- $this->channel = $channel;
- $this->git = new PHPGit();
-
- // Allow custom path for repo in the case of , for example
- if ($path) {
- $this->path = $path;
- } else {
- $this->path = $this->repoBasePath . "/" . $this->channel . "/" . $this->name;
- }
-
- if ($this->isValidGitRepoURL($url)) {
- $this->url = $url;
- }
-
- if ($name) {
- $this->name = $name;
- } else {
- $this->name = $this->getRepoNameFromURL($url);
- }
- if (!$this->name) {
- logger('Error creating GitRepo. No repo name found.');
- return null;
- }
-
- if (is_dir($this->path)) {
- // ignore the $url input if it exists
- // TODO: Check if the path is either empty or is a valid git repo and error if not
- $this->git->setRepository($this->path);
- // TODO: get repo metadata
- return;
- }
-
- if ($this->url) {
- // create the folder and clone the repo at url to that folder if $clone is true
- if ($clone) {
- if (mkdir($this->path, 0770, true)) {
- $this->git->setRepository($this->path);
- if (!$this->cloneRepo()) {
- // TODO: throw error
- logger('git clone failed: ' . json_encode($this->git));
- }
- } else {
- logger('git repo path could not be created: ' . json_encode($this->git));
- }
- }
- }
- }
-
- public function initRepo() {
- if(!$this->path) return false;
- try {
- return $this->git->init($this->path);
- } catch (\PHPGit\Exception\GitException $ex) {
- return false;
- }
- }
-
- public function pull() {
- try {
- $success = $this->git->pull();
- } catch (\PHPGit\Exception\GitException $ex) {
- return false;
- }
- return $success;
- }
-
- public function getRepoPath() {
- return $this->path;
- }
-
- public function setRepoPath($directory) {
- if (is_dir($directory)) {
- $this->path->$directory;
- $this->git->setRepository($directory);
- return true;
- }
- return false;
- }
-
- public function setIdentity($user_name, $user_email) {
- // setup user for commit messages
- $this->git->config->set("user.name", $user_name, ['global' => false, 'system' => false]);
- $this->git->config->set("user.email", $user_email, ['global' => false, 'system' => false]);
- }
-
- public function cloneRepo() {
- if (validate_url($this->url) && $this->isValidGitRepoURL($this->url) && is_dir($this->path)) {
- return $this->git->clone($this->url, $this->path);
- }
- }
-
- public function probeRepo() {
- $git = $this->git;
- $repo = array();
- $repo['remote'] = $git->remote();
- $repo['branches'] = $git->branch(['all' => true]);
- $repo['logs'] = $git->log(array('limit' => 50));
- return $repo;
- }
-
- // Commit changes to the repo. Default is to stage all changes and commit everything.
- public function commit($msg, $options = array()) {
- try {
- return $this->git->commit($msg, $options);
- } catch (\PHPGit\Exception\GitException $ex) {
- return false;
- }
- }
-
- public static function isValidGitRepoURL($url) {
- if (validate_url($url) && strrpos(parse_url($url, PHP_URL_PATH), '.')) {
- return true;
- } else {
- return false;
- }
- }
-
- public static function getRepoNameFromURL($url) {
- $urlpath = parse_url($url, PHP_URL_PATH);
- $lastslash = strrpos($urlpath, '/') + 1;
- $gitext = strrpos($urlpath, '.');
- if ($gitext) {
- return substr($urlpath, $lastslash, $gitext - $lastslash);
- } else {
- return null;
- }
- }
-
-}
diff --git a/Zotlabs/Web/WebServer.php b/Zotlabs/Web/WebServer.php
index 6f8a4b956..19f14ee8a 100644
--- a/Zotlabs/Web/WebServer.php
+++ b/Zotlabs/Web/WebServer.php
@@ -2,6 +2,8 @@
namespace Zotlabs\Web;
+use Zotlabs\Lib\Text;
+
class WebServer {
public function run() {
@@ -60,7 +62,7 @@ class WebServer {
\App::$query_string = strip_zids(\App::$query_string);
if(! local_channel()) {
if (!isset($_SESSION['my_address']) || $_SESSION['my_address'] != $_GET['zid']) {
- $_SESSION['my_address'] = $_GET['zid'];
+ $_SESSION['my_address'] = Text::escape_tags($_GET['zid']);
$_SESSION['authenticated'] = 0;
}
if(!$_SESSION['authenticated']) {
diff --git a/Zotlabs/Widget/Activity_filter.php b/Zotlabs/Widget/Activity_filter.php
index a8a00bda6..6884963d4 100644
--- a/Zotlabs/Widget/Activity_filter.php
+++ b/Zotlabs/Widget/Activity_filter.php
@@ -42,7 +42,7 @@ class Activity_filter {
$tabs[] = [
'label' => t('Direct Messages'),
- 'icon' => 'envelope-o',
+ 'icon' => 'envelope',
'url' => z_root() . '/' . $cmd . '/?f=&dm=1',
'sel' => $dm_active,
'title' => t('Show direct (private) messages')
@@ -51,7 +51,7 @@ class Activity_filter {
if(feature_enabled(local_channel(),'events_tab')) {
$tabs[] = [
'label' => t('Events'),
- 'icon' => 'calendar',
+ 'icon' => 'calendar-date',
'url' => z_root() . '/' . $cmd . '/?verb=%2EEvent',
'sel' => $events_active,
'title' => t('Show posts that include events')
@@ -93,7 +93,7 @@ class Activity_filter {
$tabs[] = [
'id' => 'privacy_groups',
'label' => t('Privacy Groups'),
- 'icon' => 'users',
+ 'icon' => 'person',
'url' => '#',
'sel' => (($filter_active == 'group') ? true : false),
'title' => t('Show my privacy groups'),
@@ -128,7 +128,7 @@ class Activity_filter {
$tabs[] = [
'id' => 'forums',
'label' => t('Forums'),
- 'icon' => 'comments-o',
+ 'icon' => 'chat-quote',
'url' => '#',
'sel' => (($filter_active == 'forums') ? true : false),
'title' => t('Show forums'),
@@ -161,7 +161,7 @@ class Activity_filter {
$tabs[] = [
'label' => t('Personal Posts'),
- 'icon' => 'user-circle',
+ 'icon' => 'person-circle',
'url' => z_root() . '/' . $cmd . '/?f=&conv=1',
'sel' => $conv_active,
'title' => t('Show posts that mention or involve me')
@@ -233,7 +233,7 @@ class Activity_filter {
if($filter_active) {
$reset = [
'label' => '',
- 'icon' => 'remove',
+ 'icon' => 'x-lg',
'url'=> z_root() . '/' . $cmd,
'sel'=> '',
'title' => t('Remove active filter')
diff --git a/Zotlabs/Widget/Channel_activities.php b/Zotlabs/Widget/Channel_activities.php
index a799ea81e..debaf20d4 100644
--- a/Zotlabs/Widget/Channel_activities.php
+++ b/Zotlabs/Widget/Channel_activities.php
@@ -91,7 +91,7 @@ class Channel_activities {
self::$activities['photos'] = [
'label' => t('Photos'),
- 'icon' => 'photo',
+ 'icon' => 'image',
'url' => z_root() . '/photos/' . self::$channel['channel_address'],
'date' => $r[0]['edited'],
'items' => $i,
@@ -123,7 +123,7 @@ class Channel_activities {
self::$activities['files'] = [
'label' => t('Files'),
- 'icon' => 'folder-open',
+ 'icon' => 'folder',
'url' => z_root() . '/cloud/' . self::$channel['channel_address'],
'date' => $r[0]['edited'],
'items' => $i,
@@ -166,7 +166,7 @@ class Channel_activities {
self::$activities['webpages'] = [
'label' => t('Webpages'),
- 'icon' => 'newspaper-o',
+ 'icon' => 'layout-text-sidebar',
'url' => z_root() . '/webpages/' . self::$channel['channel_address'],
'date' => $r[0]['edited'],
'items' => $i,
@@ -237,7 +237,7 @@ class Channel_activities {
self::$activities['channels'] = [
'label' => t('Channels'),
- 'icon' => 'home',
+ 'icon' => 'house',
'url' => z_root() . '/manage',
'date' => datetime_convert(),
'items' => $i,
diff --git a/Zotlabs/Widget/Helpindex.php b/Zotlabs/Widget/Helpindex.php
index 5264e1947..fd9204c9e 100644
--- a/Zotlabs/Widget/Helpindex.php
+++ b/Zotlabs/Widget/Helpindex.php
@@ -22,7 +22,9 @@ class Helpindex {
$this->find_help_file('toc', $this->lang['language']);
if (! empty($this->file_name)) {
- $this->contents = file_get_contents($this->file_name);
+ $this->contents = translate_projectname(
+ file_get_contents($this->file_name)
+ );
}
$tpl = get_markup_template('widget.tpl');
diff --git a/Zotlabs/Widget/Hq_controls.php b/Zotlabs/Widget/Hq_controls.php
index 51212d145..0db492c37 100644
--- a/Zotlabs/Widget/Hq_controls.php
+++ b/Zotlabs/Widget/Hq_controls.php
@@ -34,7 +34,7 @@ class Hq_controls {
'href' => '#',
'class' => 'btn notes-toggle',
'type' => 'button',
- 'icon' => 'sticky-note-o',
+ 'icon' => 'sticky',
'extra' => 'data-toggle="button"'
];
}
@@ -44,7 +44,7 @@ class Hq_controls {
'href' => '#',
'class' => 'btn channel-activities-toggle d-none',
'type' => 'button',
- 'icon' => 'user-circle-o',
+ 'icon' => 'person-circle',
'extra' => 'data-toggle="button"'
];
diff --git a/Zotlabs/Widget/Messages.php b/Zotlabs/Widget/Messages.php
index 8654d8e8f..f90b4f99e 100644
--- a/Zotlabs/Widget/Messages.php
+++ b/Zotlabs/Widget/Messages.php
@@ -23,20 +23,35 @@ class Messages {
$_SESSION['messages_loadtime'] = datetime_convert();
+ $r = q("SELECT DISTINCT(term) FROM term WHERE uid = %d AND ttype = %d ORDER BY term",
+ intval(local_channel()),
+ intval(TERM_FILE)
+ );
+
+ if ($r) {
+ foreach($r as $rr) {
+ $file_tags[] = $rr['term'];
+ }
+ }
+
$tpl = get_markup_template('messages_widget.tpl');
$o = replace_macros($tpl, [
'$entries' => $page['entries'] ?? [],
'$offset' => $page['offset'] ?? 0,
'$feature_star' => feature_enabled(local_channel(), 'star_posts'),
+ '$feature_file' => feature_enabled(local_channel(), 'filing'),
+ '$file_tags' => $file_tags,
'$strings' => [
'messages_title' => t('Public and restricted messages'),
'direct_messages_title' => t('Direct messages'),
'starred_messages_title' => t('Starred messages'),
+ 'filed_messages_title' => t('Filed messages'),
'notice_messages_title' => t('Notices'),
'loading' => t('Loading'),
'empty' => t('No messages'),
'unseen_count' => t('Unseen'),
- 'filter' => t('Filter by name or address')
+ 'filter' => t('Filter by name or address'),
+ 'file_filter' => t('Filter by file name')
]
]);
@@ -50,6 +65,7 @@ class Messages {
$offset = $options['offset'] ?? 0;
$type = $options['type'] ?? '';
$author = $options['author'] ?? '';
+ $file = $options['file'] ?? '';
if ($offset == -1) {
return;
@@ -67,8 +83,9 @@ class Messages {
$item_normal_c = str_replace('item.', 'c.', $item_normal);
$entries = [];
$limit = 30;
+ $order_sql = 'i.created DESC';
$dummy_order_sql = '';
- $author_sql = '';
+ $filter_sql = '';
$loadtime = (($offset) ? $_SESSION['messages_loadtime'] : datetime_convert());
$vnotify = get_pconfig(local_channel(), 'system', 'vnotify', -1);
@@ -84,43 +101,55 @@ class Messages {
$vnotify_sql_i = " AND i.verb NOT IN ('Dislike', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
}
- if($author) {
- $author_sql = " AND (i.owner_xchan = '" . protect_sprintf(dbesc($author)) . "') ";
+ if($type !== 'filed' && $author) {
+ $filter_sql = " AND (i.owner_xchan = '" . protect_sprintf(dbesc($author)) . "') ";
+ }
+
+ if($type === 'filed' && $file) {
+ $filed_filter_sql = " AND (term.term = '" . protect_sprintf(dbesc($file)) . "') ";
}
switch($type) {
case 'direct':
- $type_sql = ' AND i.item_private = 2 ';
+ $type_sql = ' AND i.item_private = 2 AND i.item_thread_top = 1 ';
// $dummy_order_sql has no other meaning but to trick
// some mysql backends into using the right index.
$dummy_order_sql = ', i.received DESC ';
break;
case 'starred':
- $type_sql = ' AND i.item_starred = 1 ';
+ $type_sql = ' AND i.item_starred = 1 AND i.item_thread_top = 1 ';
+ break;
+ case 'filed':
+ $type_sql = ' AND i.id IN (SELECT term.oid FROM term WHERE term.ttype = ' . TERM_FILE . ' AND term.uid = i.uid ' . $filed_filter_sql . ')';
break;
default:
- $type_sql = ' AND i.item_private IN (0, 1) ';
+ $type_sql = ' AND i.item_private IN (0, 1) AND i.item_thread_top = 1 ';
}
$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 $item_normal_c $vnotify_sql_c) AS unseen_count
- FROM item i WHERE i.uid = %d
+ FROM item i
+ WHERE i.uid = %d
AND i.created <= '%s'
$type_sql
- AND i.item_thread_top = 1
- $author_sql
+ $filter_sql
$item_normal_i
- ORDER BY i.created DESC $dummy_order_sql
+ ORDER BY $order_sql $dummy_order_sql
LIMIT $limit OFFSET $offset",
intval(local_channel()),
intval(local_channel()),
dbescdate($loadtime)
);
+ if ($type === 'filed') {
+ $items = fetch_post_tags($items);
+ }
+
xchan_query($items, false);
$i = 0;
$entries = [];
+ $ids = [];
foreach($items as $item) {
@@ -149,6 +178,16 @@ class Messages {
$info .= t('via') . ' ' . $item['source']['xchan_name'];
}
+ if ($type == 'filed') {
+ $info = '';
+ foreach ($item['term'] as $t) {
+ if ($t['ttype'] !== TERM_FILE) {
+ continue;
+ }
+ $info .= '<span class="badge rounded-pill bg-danger me-1"><i class="bi bi-folder"></i>&nbsp;' . $t['term'] . '</span>';
+ }
+ }
+
$summary = $item['title'];
if (!$summary) {
$summary = $item['summary'];
@@ -170,10 +209,10 @@ class Messages {
switch(intval($item['item_private'])) {
case 1:
- $icon = '<i class="fa fa-lock"></i>';
+ $icon = '<i class="bi bi-lock"></i>';
break;
case 2:
- $icon = '<i class="fa fa-envelope-o"></i>';
+ $icon = '<i class="bi bi-envelope"></i>';
break;
default:
$icon = '';
@@ -293,7 +332,7 @@ class Messages {
$entries[$i]['summary'] = $summary;
$entries[$i]['b64mid'] = (($notice['ntype'] & NOTIFY_INTRO) ? '' : ((str_contains($notice['hash'], '-')) ? $notice['hash'] : basename($notice['link'])));
$entries[$i]['href'] = (($notice['ntype'] & NOTIFY_INTRO) ? $notice['link'] : z_root() . '/hq/' . ((str_contains($notice['hash'], '-')) ? $notice['hash'] : basename($notice['link'])));
- $entries[$i]['icon'] = (($notice['ntype'] & NOTIFY_INTRO) ? '<i class="fa fa-user-plus"></i>' : '');
+ $entries[$i]['icon'] = (($notice['ntype'] & NOTIFY_INTRO) ? '<i class="bi bi-person-plus"></i>' : '');
$i++;
}
diff --git a/Zotlabs/Widget/Notes.php b/Zotlabs/Widget/Notes.php
index 836159edd..be4ec64a6 100644
--- a/Zotlabs/Widget/Notes.php
+++ b/Zotlabs/Widget/Notes.php
@@ -16,14 +16,17 @@ use Zotlabs\Lib\Apps;
class Notes {
function widget($arr) {
- if(! local_channel())
+ if(!local_channel()) {
return EMPTY_STR;
+ }
- if(App::$profile_uid !== local_channel())
+ if (App::$profile_uid !== local_channel()) {
return EMPTY_STR;
+ }
- if(! Apps::system_app_installed(local_channel(), 'Notes'))
+ if(!Apps::system_app_installed(local_channel(), 'Notes')) {
return EMPTY_STR;
+ }
$text = get_pconfig(local_channel(),'notes','text');
diff --git a/Zotlabs/Widget/Notifications.php b/Zotlabs/Widget/Notifications.php
index eeef1d7d4..225403535 100644
--- a/Zotlabs/Widget/Notifications.php
+++ b/Zotlabs/Widget/Notifications.php
@@ -18,7 +18,7 @@ class Notifications {
if(local_channel()) {
$notifications[] = [
'type' => 'network',
- 'icon' => 'th',
+ 'icon' => 'grid-3x3',
'severity' => 'secondary',
'label' => t('Network'),
'title' => t('New network activity notifications'),
@@ -38,7 +38,7 @@ class Notifications {
$notifications[] = [
'type' => 'home',
- 'icon' => 'home',
+ 'icon' => 'house',
'severity' => 'danger',
'label' => t('Home'),
'title' => t('New home activity notifications'),
@@ -76,7 +76,7 @@ class Notifications {
$notifications[] = [
'type' => 'all_events',
- 'icon' => 'calendar',
+ 'icon' => 'calendar-date',
'severity' => 'secondary',
'label' => t('Events'),
'title' => t('New events notifications'),
@@ -91,7 +91,7 @@ class Notifications {
$notifications[] = [
'type' => 'intros',
- 'icon' => 'users',
+ 'icon' => 'people',
'severity' => 'danger',
'label' => t('New Connections'),
'title' => t('New connections notifications'),
@@ -111,7 +111,7 @@ class Notifications {
$notifications[] = [
'type' => 'notify',
- 'icon' => 'exclamation',
+ 'icon' => 'exclamation-circle',
'severity' => 'danger',
'label' => t('Notices'),
'title' => t('Notices'),
@@ -126,7 +126,7 @@ class Notifications {
$notifications[] = [
'type' => 'forums',
- 'icon' => 'comments-o',
+ 'icon' => 'chat-quote',
'severity' => 'secondary',
'label' => t('Forums'),
'title' => t('Forums'),
@@ -139,7 +139,7 @@ class Notifications {
if(local_channel() && is_site_admin()) {
$notifications[] = [
'type' => 'register',
- 'icon' => 'user-o',
+ 'icon' => 'person-exclamation',
'severity' => 'danger',
'label' => t('Registrations'),
'title' => t('New registrations notifications'),
diff --git a/Zotlabs/Widget/Permcats.php b/Zotlabs/Widget/Permcats.php
index 9bda5b8f1..f0e43b937 100644
--- a/Zotlabs/Widget/Permcats.php
+++ b/Zotlabs/Widget/Permcats.php
@@ -40,7 +40,7 @@ class Permcats {
if($active_role) {
$roles[] = [
- 'name' => '<i class="fa fa-plus"></i>&nbsp;' . t('Add new role'),
+ 'name' => '<i class="bi bi-plus-lg"></i>&nbsp;' . t('Add new role'),
'url' => z_root() . '/permcats',
'active' => ''
];
diff --git a/Zotlabs/Widget/Privacygroups.php b/Zotlabs/Widget/Privacygroups.php
index 62f343ea6..129c939fd 100644
--- a/Zotlabs/Widget/Privacygroups.php
+++ b/Zotlabs/Widget/Privacygroups.php
@@ -42,7 +42,7 @@ class Privacygroups {
if ($active) {
$menu_items[] = [
'href' => $z_root . '/group',
- 'label' => '<i class="fa fa-plus"></i> &nbsp;' . t('Add new group'),
+ 'label' => '<i class="bi bi-plus-lg"></i> &nbsp;' . t('Add new group'),
'title' => '',
'active' => '',
'count' => ''
diff --git a/Zotlabs/Widget/Rating.php b/Zotlabs/Widget/Rating.php
index f8986ac93..a90052411 100644
--- a/Zotlabs/Widget/Rating.php
+++ b/Zotlabs/Widget/Rating.php
@@ -60,12 +60,12 @@ class Rating {
if((($remote) || (local_channel())) && (! $self)) {
if($remote)
- $o .= '<a class="btn btn-block btn-primary btn-sm" href="' . $url . '"><i class="fa fa-pencil"></i> ' . t('Rate Me') . '</a>';
+ $o .= '<a class="btn btn-block btn-primary btn-sm" href="' . $url . '"><i class="bi bi-pencil"></i> ' . t('Rate Me') . '</a>';
else
- $o .= '<div class="btn btn-block btn-primary btn-sm" onclick="doRatings(\'' . $hash . '\'); return false;"><i class="fa fa-pencil"></i> ' . t('Rate Me') . '</div>';
+ $o .= '<div class="btn btn-block btn-primary btn-sm" onclick="doRatings(\'' . $hash . '\'); return false;"><i class="bi bi-pencil"></i> ' . t('Rate Me') . '</div>';
}
- $o .= '<a class="btn btn-block btn-default btn-sm" href="ratings/' . $hash . '"><i class="fa fa-eye"></i> ' . t('View Ratings') . '</a>';
+ $o .= '<a class="btn btn-block btn-default btn-sm" href="ratings/' . $hash . '"><i class="bi bi-eye"></i> ' . t('View Ratings') . '</a>';
$o .= '</div>';
return $o;
diff --git a/Zotlabs/Widget/Tokens.php b/Zotlabs/Widget/Tokens.php
index 69452d628..08fe67680 100644
--- a/Zotlabs/Widget/Tokens.php
+++ b/Zotlabs/Widget/Tokens.php
@@ -38,7 +38,7 @@ class Tokens {
if ($active) {
$menu_items[] = [
'href' => $z_root . '/tokens',
- 'label' => '<i class="fa fa-plus"></i> &nbsp;' . t('Add new guest'),
+ 'label' => '<i class="bi bi-plus-lg"></i> &nbsp;' . t('Add new guest'),
'title' => '',
'active' => ''
];