mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-21 09:01:15 -04:00
Compare commits
176 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
173c4d242d | ||
|
|
76b8c36f7c | ||
|
|
f35352090e | ||
|
|
e5db47e0d5 | ||
|
|
6a52e502aa | ||
|
|
6a866fe904 | ||
|
|
d9d239bf3a | ||
|
|
429d15f009 | ||
|
|
2b44be58c3 | ||
|
|
c44db397ff | ||
|
|
a385fdff37 | ||
|
|
20aacb82c6 | ||
|
|
0d17d8dad9 | ||
|
|
2ab0118c13 | ||
|
|
30419bdbf6 | ||
|
|
c958cc6f90 | ||
|
|
38ac60e618 | ||
|
|
23a19ecf1f | ||
|
|
8b75f50f23 | ||
|
|
436b1673cf | ||
|
|
96210f5ecc | ||
|
|
9e9e8efb2d | ||
|
|
e9dc4b553b | ||
|
|
c70bd08c10 | ||
|
|
69109a558b | ||
|
|
4aff6d19d6 | ||
|
|
3cb5d14037 | ||
|
|
5f685bcf63 | ||
|
|
cb44f7e360 | ||
|
|
8f74ee67e3 | ||
|
|
b0a11537de | ||
|
|
4de9cb1142 | ||
|
|
158ddfb009 | ||
|
|
2b4f344181 | ||
|
|
2e5f922561 | ||
|
|
a6498a0cfc | ||
|
|
1073392398 | ||
|
|
76064dbb33 | ||
|
|
1ab4f36a1b | ||
|
|
cea9c88b9e | ||
|
|
babe118383 | ||
|
|
2b140e53cc | ||
|
|
fb1514a782 | ||
|
|
7679894684 | ||
|
|
520cf1015c | ||
|
|
64bd8eef4b | ||
|
|
aa42f6a6b2 | ||
|
|
13345d3cbe | ||
|
|
888ee16d52 | ||
|
|
0f3e01f343 | ||
|
|
79220ede66 | ||
|
|
b498e50f74 | ||
|
|
8c87b06caa | ||
|
|
339e702beb | ||
|
|
8750c5f7bc | ||
|
|
c3b4397ea3 | ||
|
|
a3f1189df7 | ||
|
|
2bc088e555 | ||
|
|
67d8b977b6 | ||
|
|
5b1e532791 | ||
|
|
0e1bf2cef0 | ||
|
|
4f129e05e5 | ||
|
|
3733a80c1d | ||
|
|
220571d2a9 | ||
|
|
f6b9a1dd3c | ||
|
|
393d5020f8 | ||
|
|
06ac41c005 | ||
|
|
39ee872f49 | ||
|
|
a7c51f5d65 | ||
|
|
5309c032db | ||
|
|
176298ffeb | ||
|
|
fdf19e659e | ||
|
|
e799589781 | ||
|
|
10acf90d06 | ||
|
|
b184533115 | ||
|
|
b50e06a9d9 | ||
|
|
66901dbe3e | ||
|
|
4a7879aad2 | ||
|
|
30aa0e3822 | ||
|
|
cadc7ee29e | ||
|
|
5a44b8c40c | ||
|
|
487e68ebd1 | ||
|
|
6cdbc28d79 | ||
|
|
4113bea104 | ||
|
|
294359d7f5 | ||
|
|
8ff870482f | ||
|
|
56cb6f1034 | ||
|
|
7eb23aa8b8 | ||
|
|
c793cea2f0 | ||
|
|
4e19f1c8be | ||
|
|
3d3fcd7334 | ||
|
|
61c03e4b4e | ||
|
|
dd0be272d0 | ||
|
|
b781739949 | ||
|
|
2221d8dd12 | ||
|
|
d67a0b14e3 | ||
|
|
b838632318 | ||
|
|
8c38466b75 | ||
|
|
2919b36e91 | ||
|
|
52f7b508af | ||
|
|
15f6bc93cf | ||
|
|
8c4269d037 | ||
|
|
7394c97f23 | ||
|
|
33e45d98a3 | ||
|
|
241cc1ad63 | ||
|
|
b26db5bde6 | ||
|
|
9be799de15 | ||
|
|
014737fe21 | ||
|
|
d3093dce1b | ||
|
|
61f9ad8274 | ||
|
|
7067a0adc2 | ||
|
|
eb8cab37f3 | ||
|
|
467e0b32b4 | ||
|
|
204d91c3c3 | ||
|
|
1bd52867fb | ||
|
|
898fb4f800 | ||
|
|
63a01c0214 | ||
|
|
39933052a9 | ||
|
|
719dbf091a | ||
|
|
2dad3a8fe5 | ||
|
|
d99ba64206 | ||
|
|
202b797fe6 | ||
|
|
9df96fa03b | ||
|
|
7afb01e488 | ||
|
|
ae140465d7 | ||
|
|
475cbf6510 | ||
|
|
39e5e29ce5 | ||
|
|
f4ffef967a | ||
|
|
77a6a21ea2 | ||
|
|
4e35d34226 | ||
|
|
3708896a65 | ||
|
|
7c3f28f9d2 | ||
|
|
afc8b88933 | ||
|
|
4668178dee | ||
|
|
bfec7b6901 | ||
|
|
f026afe11c | ||
|
|
f388fcaf08 | ||
|
|
9bd2b3ab17 | ||
|
|
2d0b216a2c | ||
|
|
c5bca0279c | ||
|
|
3fca63a15f | ||
|
|
c47900f366 | ||
|
|
84f64214c3 | ||
|
|
9cd01e2e13 | ||
|
|
841b4f7d81 | ||
|
|
70212cdb59 | ||
|
|
5f77e9f4ce | ||
|
|
6276f36b90 | ||
|
|
2461e709d2 | ||
|
|
1055718935 | ||
|
|
82f69018a6 | ||
|
|
c22f633ae0 | ||
|
|
c71eb401c0 | ||
|
|
5a1079750e | ||
|
|
3d03c24f06 | ||
|
|
983fc84f28 | ||
|
|
1861eeeb0a | ||
|
|
663aeca2a7 | ||
|
|
526730672a | ||
|
|
7f292d4765 | ||
|
|
99bff67168 | ||
|
|
bb3caeb629 | ||
|
|
65185a70d5 | ||
|
|
6d1f34284b | ||
|
|
2cfdbbd956 | ||
|
|
5f66ad5bc5 | ||
|
|
aff11443b4 | ||
|
|
6ced7ecf89 | ||
|
|
2d467a15ba | ||
|
|
28c8229218 | ||
|
|
0bcecc4baa | ||
|
|
78e68519e8 | ||
|
|
d2b06995c7 | ||
|
|
5cbae0fb81 | ||
|
|
2ddc087512 | ||
|
|
b0fe94b4b3 |
98
CHANGELOG
98
CHANGELOG
@@ -1,4 +1,100 @@
|
||||
Hubzilla 9.2 (2024-??-??)
|
||||
Hubzilla 9.4.4 (2024-11-06)
|
||||
- Update Norwegian translations
|
||||
- Fix error adding things when multiple profiles not enabled
|
||||
- Port mod thing to use $_GET/$_POST instead of $_REQUEST
|
||||
- Move Norwegian translations from nb-no to nb
|
||||
- Fix intact alernative network hublocs being marked deleted in Libsync::sync_locations()
|
||||
- Fix modals only partly removed when DOM emlement updated via ajax
|
||||
- Add explicit check for channel_address in channel_url()
|
||||
- Fix PHP deprecation warnings in mod setup
|
||||
- Fix PHP warning in Web/HttpMeta
|
||||
- Fix typo in UnitTestCase
|
||||
- Fix missing CSRF token checks in mod account_edit
|
||||
- Fix OCAP tokens only added to images
|
||||
- Fix unescaped zid parameter
|
||||
- Fix wrong date format in published date in update question activities
|
||||
- Fix include for en TOS page
|
||||
- Fix query in copy_of_pubitem() returning duplicate items
|
||||
- Fix edit button not clickable if below right aside when viewing webpages
|
||||
- Fix rendering of category tags icons in the editor
|
||||
- Fix regex to detect URLs in cleanup_bbcode
|
||||
- Fix duplicate posts from forum clones
|
||||
- Fix follow to non primary hub location in pubcrawl addon
|
||||
- Fix id host not rewritten to local host in pubcrawl addon
|
||||
- Fix regression when manually fetching items in pubcrawl addon
|
||||
|
||||
|
||||
Hubzilla 9.4.3 (2024-10-10)
|
||||
- Discard Add/Remove activities (Hubzilla 10 and (streams) compatibility)
|
||||
- Fix HQ channel activities icons
|
||||
- Fix saved search icons
|
||||
|
||||
|
||||
Hubzilla 9.4.2 (2024-10-04)
|
||||
- Indicate reacted state via icon color (community wish)
|
||||
- Fix modal backdrop not removed when reacting from the modal
|
||||
- Fix missing handle icon in mod pdledit_gui
|
||||
|
||||
|
||||
Hubzilla 9.4.1 (2024-10-02)
|
||||
- Various fixes for the help module
|
||||
- Update smarty library via composer
|
||||
- Fix URLs replaced with bbcode in codeblocks if markdown enabled
|
||||
- Fix unable to move multiple files when using postgresql DB backend
|
||||
- Adjust icon for post app
|
||||
- Fix check for while loop in wiki addon
|
||||
|
||||
|
||||
Hubzilla 9.4 (2024-09-25)
|
||||
- If we got an ocap token try to authenticate with it first
|
||||
- Hide comment titles
|
||||
- Adjust fix_attached_permissions() to only add the token if we got one
|
||||
- Allow uploading to comments if ocap tokens are enabled
|
||||
- Refactor get_security_ids() to remove legacy code
|
||||
- Add privacy scope sql to item_permissions_sql()
|
||||
- Removed fork awesome in favour of bootstrap icons
|
||||
- Improved content and comment collapse/expand rendering
|
||||
- Add support for inbound locations
|
||||
- Streamline item location rendering (use icon)
|
||||
- Fix html2bbcode table and add test
|
||||
- Store info/notice messages in xconfig instead of session
|
||||
- Refactor help and add tests
|
||||
- Do not run set_linkified_perms() if editing a post
|
||||
- Remove deprecated tag_deliver permissions
|
||||
- Make sure that tgroup_check() fails for group posts if they do not have the post_wall permission
|
||||
- Show repeat button to channel owners only
|
||||
- Refactor item buttons
|
||||
- Add util/update_db
|
||||
- Remove the unused f argument in various places
|
||||
- Streamline URLs used in attachments and body to ease deduplication
|
||||
- Code cleanup and remove some unused/deprecated functions
|
||||
|
||||
Bugfixes
|
||||
- Fix broken help pages search
|
||||
- Fix notes app not displaying anything - issue #1865
|
||||
|
||||
Addons
|
||||
- Cards: fix decoding issue when editing and minor cleanup
|
||||
- Articles: fix decoding issue when editing and minor cleanup
|
||||
- Wiki: fix markdown content not unescaped when undoing history - issue #1864
|
||||
- Gallery: update to photoswipe 5.4.4
|
||||
- Openstreemap: streamline location rendering
|
||||
- Socialauth: update version and contact details
|
||||
- Socialauth: fix rendering issue
|
||||
|
||||
Hubzilla 9.2.1 (2024-07-18)
|
||||
- Fix fatal error if gd function image{jpeg, png, webp}() does not exist for some reason
|
||||
- Add missing pdl for mod import
|
||||
- Escape queueworker json data
|
||||
- Fix missing object when repeating own posts
|
||||
- Improve display of system notifications in relation with page reloads
|
||||
- Add possibility to only display system notifications with notifications widget
|
||||
- Fix layout issue with socialauth addon
|
||||
- Save a db lookup if we have just reset notifications in sse addon
|
||||
- Fix php error if attachment was an empty string in pubcrawl addon
|
||||
|
||||
|
||||
Hubzilla 9.2 (2024-07-06)
|
||||
- Fail to import more gracefully if a channel has already been imported at some point but was deleted again
|
||||
- Use the doubleleft template by default for admin pages to work around some display issues
|
||||
- Reflect the censored state in the local xchan
|
||||
|
||||
@@ -503,15 +503,21 @@ class Activity {
|
||||
$ret['diaspora:guid'] = $i['uuid'];
|
||||
|
||||
$images = [];
|
||||
$audios = [];
|
||||
$videos = [];
|
||||
|
||||
$has_images = preg_match_all('/\[[zi]mg(.*?)](.*?)\[/ism', $i['body'], $images, PREG_SET_ORDER);
|
||||
$has_audios = preg_match_all('/\[zaudio](.*?)\[/ism', $i['body'], $audios, PREG_SET_ORDER);
|
||||
$has_videos = preg_match_all('/\[zvideo](.*?)\[/ism', $i['body'], $videos, PREG_SET_ORDER);
|
||||
|
||||
// provide ocap access token for private media.
|
||||
// set this for descendants even if the current item is not private
|
||||
// because it may have been relayed from a private item.
|
||||
|
||||
$token = IConfig::Get($i, 'ocap', 'relay');
|
||||
$matches_processed = [];
|
||||
|
||||
if ($token && $has_images) {
|
||||
$matches_processed = [];
|
||||
for ($n = 0; $n < count($images); $n++) {
|
||||
$match = $images[$n];
|
||||
if (str_starts_with($match[1], '=http') && str_contains($match[1], z_root() . '/photo/') && !in_array($match[1], $matches_processed)) {
|
||||
@@ -526,6 +532,28 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
if ($token && $has_audios) {
|
||||
for ($n = 0; $n < count($audios); $n++) {
|
||||
$match = $audios[$n];
|
||||
if (str_contains($match[1], z_root() . '/attach/') && !in_array($match[1], $matches_processed)) {
|
||||
$i['body'] = str_replace($match[1], $match[1] . '?token=' . $token, $i['body']);
|
||||
$audios[$n][1] = $match[1] . '?token=' . $token;
|
||||
$matches_processed[] = $match[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($token && $has_videos) {
|
||||
for ($n = 0; $n < count($videos); $n++) {
|
||||
$match = $videos[$n];
|
||||
if (str_contains($match[1], z_root() . '/attach/') && !in_array($match[1], $matches_processed)) {
|
||||
$i['body'] = str_replace($match[1], $match[1] . '?token=' . $token, $i['body']);
|
||||
$videos[$n][1] = $match[1] . '?token=' . $token;
|
||||
$matches_processed[] = $match[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($i['title'])
|
||||
$ret['name'] = unescape_tags($i['title']);
|
||||
|
||||
@@ -694,6 +722,8 @@ class Activity {
|
||||
|
||||
$ret = [];
|
||||
|
||||
$token = IConfig::Get($item, 'ocap', 'relay');
|
||||
|
||||
if (!$iconfig && array_key_exists('attach', $item)) {
|
||||
$atts = ((is_array($item['attach'])) ? $item['attach'] : json_decode($item['attach'], true));
|
||||
if ($atts) {
|
||||
@@ -702,11 +732,17 @@ class Activity {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($att['type']) && strpos($att['type'], 'image')) {
|
||||
$ret[] = ['type' => 'Image', 'mediaType' => $att['type'], 'name' => $att['title'], 'url' => $att['href']];
|
||||
if (str_starts_with($att['type'], 'image')) {
|
||||
$ret[] = ['type' => 'Image', 'mediaType' => $att['type'], 'name' => $att['title'], 'url' => $att['href'] . (($token) ? '?token=' . $token : '')];
|
||||
}
|
||||
elseif (str_starts_with($att['type'], 'audio')) {
|
||||
$ret[] = ['type' => 'Audio', 'mediaType' => $att['type'], 'name' => $att['title'], 'url' => $att['href'] . (($token) ? '?token=' . $token : '')];
|
||||
}
|
||||
elseif (str_starts_with($att['type'], 'video')) {
|
||||
$ret[] = ['type' => 'Video', 'mediaType' => $att['type'], 'name' => $att['title'], 'url' => $att['href'] . (($token) ? '?token=' . $token : '')];
|
||||
}
|
||||
else {
|
||||
$ret[] = ['type' => 'Link', 'mediaType' => $att['type'], 'name' => $att['title'], 'href' => $att['href']];
|
||||
$ret[] = ['type' => 'Link', 'mediaType' => $att['type'], 'name' => $att['title'], 'href' => $att['href'] . (($token) ? '?token=' . $token : '')];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2116,6 +2152,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 +3090,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 +3098,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) {
|
||||
@@ -3271,7 +3325,7 @@ class Activity {
|
||||
return $content;
|
||||
}
|
||||
|
||||
if ($act['type'] === 'Event') {
|
||||
if (isset($act['type']) && $act['type'] === 'Event') {
|
||||
$adjust = false;
|
||||
$event = [];
|
||||
$event['event_hash'] = $act['id'];
|
||||
@@ -3464,7 +3518,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'];
|
||||
}
|
||||
|
||||
|
||||
@@ -885,7 +885,7 @@ class Libsync {
|
||||
dbesc($t)
|
||||
);
|
||||
|
||||
q("update hubloc set hubloc_error = 1, hubloc_deleted = 1 where hubloc_url = '%s' and hubloc_sitekey != '%s'",
|
||||
q("update hubloc set hubloc_error = 1, hubloc_deleted = 1 where hubloc_url = '%s' and hubloc_sitekey != '%s' and hubloc_network = 'zot6'",
|
||||
dbesc($r[0]['hubloc_url']),
|
||||
dbesc($r[0]['hubloc_sitekey'])
|
||||
);
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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 '';
|
||||
|
||||
@@ -59,7 +59,7 @@ class QueueWorker {
|
||||
$transaction = new \DbaTransaction(\DBA::$dba);
|
||||
$r = q("INSERT INTO workerq (workerq_priority, workerq_data, workerq_uuid, workerq_cmd) VALUES (%d, '%s', '%s', '%s')",
|
||||
intval($priority),
|
||||
$workinfo_json,
|
||||
dbesc($workinfo_json),
|
||||
dbesc($uuid),
|
||||
dbesc($argv[0])
|
||||
);
|
||||
@@ -105,7 +105,7 @@ class QueueWorker {
|
||||
$transaction = new \DbaTransaction(\DBA::$dba);
|
||||
$r = q("INSERT INTO workerq (workerq_priority, workerq_data, workerq_uuid, workerq_cmd) VALUES (%d, '%s', '%s', '%s')",
|
||||
intval($priority),
|
||||
$workinfo_json,
|
||||
dbesc($workinfo_json),
|
||||
dbesc($uuid),
|
||||
dbesc($argv[0])
|
||||
);
|
||||
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,15 @@ trait HelpHelperTrait {
|
||||
private string $file_name = '';
|
||||
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.
|
||||
*
|
||||
@@ -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.")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ class XConfig {
|
||||
return $default;
|
||||
|
||||
if(! array_key_exists($xchan, \App::$config))
|
||||
load_xconfig($xchan);
|
||||
self::Load($xchan);
|
||||
|
||||
if((! array_key_exists($family, \App::$config[$xchan])) || (! array_key_exists($key, \App::$config[$xchan][$family])))
|
||||
return $default;
|
||||
|
||||
@@ -8,6 +8,11 @@ class Account_edit {
|
||||
|
||||
function post() {
|
||||
|
||||
// Validate CSRF token
|
||||
//
|
||||
// We terminate with a 403 Forbidden status if the check fails.
|
||||
check_form_security_token_ForbiddenOnErr('admin_account_edit', 'security');
|
||||
|
||||
$account_id = $_REQUEST['aid'];
|
||||
|
||||
if(! $account_id)
|
||||
@@ -18,7 +23,7 @@ class Account_edit {
|
||||
if($pass1 && $pass2 && ($pass1 === $pass2)) {
|
||||
$salt = random_string(32);
|
||||
$password_encoded = hash('whirlpool', $salt . $pass1);
|
||||
$r = q("update account set account_salt = '%s', account_password = '%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),
|
||||
@@ -34,7 +39,7 @@ class Account_edit {
|
||||
$account_level = 5;
|
||||
$account_language = trim($_REQUEST['account_language']);
|
||||
|
||||
$r = q("update account set account_service_class = '%s', account_level = %d, account_language = '%s'
|
||||
$r = q("update account set account_service_class = '%s', account_level = %d, account_language = '%s'
|
||||
where account_id = %d",
|
||||
dbesc($service_class),
|
||||
intval($account_level),
|
||||
@@ -62,8 +67,8 @@ class Account_edit {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
$a = replace_macros(get_markup_template('admin_account_edit.tpl'), [
|
||||
'$security' => get_form_security_token('admin_account_edit'),
|
||||
'$account' => $x[0],
|
||||
'$title' => t('Account Edit'),
|
||||
'$pass1' => [ 'pass1', t('New Password'), ' ','' ],
|
||||
|
||||
@@ -126,7 +126,7 @@ class Channels {
|
||||
goaway(z_root() . '/admin/channels' );
|
||||
}
|
||||
|
||||
$key = (($_REQUEST['key']) ? dbesc($_REQUEST['key']) : 'channel_id');
|
||||
$key = ((isset($_REQUEST['key']) && $_REQUEST['key']) ? dbesc($_REQUEST['key']) : 'channel_id');
|
||||
$dir = 'asc';
|
||||
if(array_key_exists('dir',$_REQUEST))
|
||||
$dir = ((intval($_REQUEST['dir'])) ? 'asc' : 'desc');
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -18,14 +19,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.
|
||||
*
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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))
|
||||
);
|
||||
|
||||
@@ -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)
|
||||
);
|
||||
|
||||
@@ -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>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,5 +12,5 @@ class Login extends \Zotlabs\Web\Controller {
|
||||
|
||||
return login(true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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 /> ';
|
||||
}
|
||||
$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>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Libsync::build_sync_packet();
|
||||
|
||||
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();
|
||||
|
||||
@@ -263,7 +263,10 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
|
||||
$this->check_htaccess($checks);
|
||||
|
||||
$checkspassed = array_reduce($checks, "self::check_passed", true);
|
||||
$checkspassed = array_reduce(
|
||||
$checks,
|
||||
"Zotlabs\Module\Setup::check_passed",
|
||||
true);
|
||||
|
||||
$tpl = get_markup_template('install_checks.tpl');
|
||||
$o .= replace_macros($tpl, array(
|
||||
|
||||
@@ -94,6 +94,12 @@ class Share extends \Zotlabs\Web\Controller {
|
||||
else
|
||||
killme();
|
||||
|
||||
$object = Activity::fetch_item([ 'id' => $item['mid'] ]);
|
||||
|
||||
if (!$object) {
|
||||
killme();
|
||||
}
|
||||
|
||||
$arr['aid'] = $item['aid'];
|
||||
$arr['uid'] = $item['uid'];
|
||||
|
||||
@@ -121,7 +127,7 @@ class Share extends \Zotlabs\Web\Controller {
|
||||
$arr['owner_xchan'] = $item['author_xchan'];
|
||||
$arr['source_xchan'] = '';
|
||||
|
||||
$arr['obj'] = $item['obj'];
|
||||
$arr['obj'] = $object;
|
||||
$arr['obj_type'] = $item['obj_type'];
|
||||
$arr['verb'] = ACTIVITY_SHARE;
|
||||
|
||||
|
||||
@@ -19,25 +19,20 @@ class Sse extends Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
// This is important!
|
||||
session_write_close();
|
||||
ignore_user_abort(true);
|
||||
|
||||
if((observer_prohibited(true))) {
|
||||
killme();
|
||||
}
|
||||
|
||||
if(! intval(Config::Get('system','open_pubstream',1))) {
|
||||
if(! get_observer_hash()) {
|
||||
killme();
|
||||
}
|
||||
}
|
||||
|
||||
// this is important!
|
||||
session_write_close();
|
||||
|
||||
self::$uid = local_channel();
|
||||
self::$ob_hash = get_observer_hash();
|
||||
self::$sse_id = false;
|
||||
self::$vnotify = -1;
|
||||
|
||||
if(! self::$ob_hash) {
|
||||
if (!self::$ob_hash) {
|
||||
if(session_id()) {
|
||||
self::$sse_id = true;
|
||||
self::$ob_hash = 'sse_id.' . session_id();
|
||||
@@ -55,7 +50,7 @@ class Sse extends Controller {
|
||||
|
||||
self::$sse_enabled = Config::Get('system', 'sse_enabled', 0);
|
||||
|
||||
if(self::$sse_enabled) {
|
||||
if (self::$sse_enabled) {
|
||||
|
||||
// Server Sent Events
|
||||
|
||||
@@ -73,7 +68,7 @@ class Sse extends Controller {
|
||||
$i = 0;
|
||||
}
|
||||
|
||||
if(!self::$sse_id && $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),
|
||||
@@ -82,7 +77,7 @@ class Sse extends Controller {
|
||||
|
||||
$basic_presence = false;
|
||||
|
||||
if($r) {
|
||||
if ($r) {
|
||||
$basic_presence = true;
|
||||
q("update chatpresence set cp_last = '%s' where cp_id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
@@ -90,7 +85,7 @@ class Sse extends Controller {
|
||||
);
|
||||
}
|
||||
|
||||
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),
|
||||
@@ -101,16 +96,16 @@ class Sse extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$result = [];
|
||||
|
||||
XConfig::Load(self::$ob_hash);
|
||||
|
||||
$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'))) {
|
||||
@@ -119,42 +114,61 @@ class Sse extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
if($result) {
|
||||
if ($result) {
|
||||
echo "event: notifications\n";
|
||||
echo 'data: ' . json_encode($result);
|
||||
echo "\n\n";
|
||||
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
|
||||
unset($result);
|
||||
}
|
||||
else {
|
||||
// if no result we will send a heartbeat to keep connected
|
||||
echo "event: heartbeat\n";
|
||||
echo 'data: {}';
|
||||
echo "\n\n";
|
||||
}
|
||||
|
||||
// always send heartbeat to detect disconnected clients
|
||||
echo "event: heartbeat\n";
|
||||
echo 'data: {}';
|
||||
echo "\n\n";
|
||||
if (connection_status() != CONNECTION_NORMAL || connection_aborted()) {
|
||||
|
||||
if(ob_get_length() > 0)
|
||||
ob_end_flush();
|
||||
// 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.
|
||||
|
||||
session_reset();
|
||||
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'timestamp', NULL_DATE);
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
|
||||
|
||||
if (ob_get_length() > 0) {
|
||||
ob_end_flush();
|
||||
}
|
||||
|
||||
flush();
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
if (ob_get_length() > 0) {
|
||||
ob_flush();
|
||||
}
|
||||
|
||||
flush();
|
||||
|
||||
if(connection_status() != CONNECTION_NORMAL || connection_aborted()) {
|
||||
//TODO: this does not seem to be triggered
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'timestamp', NULL_DATE);
|
||||
break;
|
||||
usleep($sleep);
|
||||
|
||||
if ($result) {
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
|
||||
}
|
||||
|
||||
$i++;
|
||||
|
||||
usleep($sleep);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// Fallback to traditional polling
|
||||
|
||||
if(! self::$sse_id) {
|
||||
if(!self::$sse_id) {
|
||||
|
||||
// Update chat presence indication
|
||||
|
||||
@@ -163,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),
|
||||
@@ -181,12 +195,17 @@ class Sse extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
$result = [];
|
||||
|
||||
XConfig::Load(self::$ob_hash);
|
||||
|
||||
$result = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
|
||||
$lock = XConfig::Get(self::$ob_hash, 'sse', 'lock');
|
||||
|
||||
if($result && !$lock) {
|
||||
if (!$lock) {
|
||||
$result = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
|
||||
}
|
||||
|
||||
if ($result) {
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
|
||||
json_return_and_die($result);
|
||||
}
|
||||
|
||||
@@ -50,24 +50,31 @@ class Thing extends \Zotlabs\Web\Controller {
|
||||
|
||||
$channel = \App::get_channel();
|
||||
|
||||
$term_hash = (($_REQUEST['term_hash']) ? $_REQUEST['term_hash'] : '');
|
||||
$term_hash = (($_POST['term_hash']) ? $_POST['term_hash'] : '');
|
||||
|
||||
$name = escape_tags($_REQUEST['term']);
|
||||
$verb = escape_tags($_REQUEST['verb']);
|
||||
$activity = intval($_REQUEST['activity']);
|
||||
$profile_guid = escape_tags($_REQUEST['profile_assign']);
|
||||
$url = $_REQUEST['url'];
|
||||
$photo = $_REQUEST['img'];
|
||||
$name = escape_tags($_POST['term']);
|
||||
$verb = escape_tags($_POST['verb']);
|
||||
$activity = intval($_POST['activity']);
|
||||
$url = $_POST['url'];
|
||||
$photo = $_POST['img'];
|
||||
|
||||
$profile_guid = isset($_POST['profile_assign'])
|
||||
? escape_tags($_POST['profile_assign'])
|
||||
: null;
|
||||
|
||||
$hash = new_uuid();
|
||||
|
||||
$verbs = obj_verbs();
|
||||
|
||||
/**
|
||||
* verbs: [0] = first person singular, e.g. "I want", [1] = 3rd person singular, e.g. "Bill wants"
|
||||
* We use the first person form when creating an activity, but the third person for use in activities
|
||||
* @FIXME There is no accounting for verb gender for languages where this is significant. We may eventually
|
||||
* require obj_verbs() to provide full conjugations and specify which form to use in the $_REQUEST params to this module.
|
||||
/*
|
||||
* verbs: [0] = first person singular, e.g. "I want", [1] = 3rd person
|
||||
* singular, e.g. "Bill wants" We use the first person form when
|
||||
* creating an activity, but the third person for use in activities
|
||||
*
|
||||
* @FIXME There is no accounting for verb gender for languages where
|
||||
* this is significant. We may eventually require obj_verbs() to
|
||||
* provide full conjugations and specify which form to use in the
|
||||
* $_POST params to this module.
|
||||
*/
|
||||
|
||||
$translated_verb = $verbs[$verb][1];
|
||||
@@ -100,7 +107,7 @@ class Thing extends \Zotlabs\Web\Controller {
|
||||
return;
|
||||
|
||||
$acl = new \Zotlabs\Access\AccessList($channel);
|
||||
$acl->set_from_array($_REQUEST);
|
||||
$acl->set_from_array($_POST);
|
||||
|
||||
$x = $acl->get();
|
||||
|
||||
@@ -394,7 +401,7 @@ class Thing extends \Zotlabs\Web\Controller {
|
||||
'$profile_lbl' => t('Select a profile'),
|
||||
'$profile_select' => contact_profile_assign(''),
|
||||
'$verb_lbl' => $channel['channel_name'],
|
||||
'$activity' => array('activity',t('Post an activity'),((array_key_exists('activity',$_REQUEST)) ? $_REQUEST['activity'] : true),t('Only sends to viewers of the applicable profile')),
|
||||
'$activity' => array('activity',t('Post an activity'),((array_key_exists('activity',$_GET)) ? $_GET['activity'] : true),t('Only sends to viewers of the applicable profile')),
|
||||
'$verb_select' => obj_verb_selector(),
|
||||
'$thing_lbl' => t('Name of thing e.g. something'),
|
||||
'$url_lbl' => t('URL of thing (optional)'),
|
||||
|
||||
@@ -111,7 +111,7 @@ class Wall_attach extends \Zotlabs\Web\Controller {
|
||||
// give a wee bit of time for the background thumbnail processor to do its thing
|
||||
// or else we'll never see a video poster
|
||||
sleep(3);
|
||||
$url = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path'];
|
||||
$url = z_root() . '/attach/' . $r['data']['hash'];
|
||||
$thumb = Linkinfo::get_video_poster($url);
|
||||
if($thumb) {
|
||||
$s = '[zvideo poster=\'' . $thumb . '\']' . $url . '[/zvideo]';
|
||||
@@ -120,8 +120,8 @@ class Wall_attach extends \Zotlabs\Web\Controller {
|
||||
$s = '[zvideo]' . $url . '[/zvideo]';
|
||||
}
|
||||
}
|
||||
if(strpos($r['data']['filetype'],'audio') === 0) {
|
||||
$url = z_root() . '/cloud/' . $channel['channel_address'] . '/' . $r['data']['display_path'];
|
||||
if(strpos($r['data']['filetype'], 'audio') === 0) {
|
||||
$url = z_root() . '/attach/' . $r['data']['hash'];
|
||||
$s = '[zaudio]' . $url . '[/zaudio]';
|
||||
}
|
||||
if ($r['data']['filetype'] === 'image/svg+xml') {
|
||||
|
||||
@@ -160,16 +160,28 @@ class PhotoGd extends PhotoDriver {
|
||||
|
||||
case 'image/png':
|
||||
$quality = Config::Get('system', 'png_quality');
|
||||
if((! $quality) || ($quality > 9))
|
||||
|
||||
if((! $quality) || ($quality > 9)) {
|
||||
$quality = PNG_QUALITY;
|
||||
\imagepng($this->image, NULL, $quality);
|
||||
}
|
||||
|
||||
if (function_exists('imagepng')) {
|
||||
\imagepng($this->image, NULL, $quality);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'image/webp':
|
||||
$quality = Config::Get('system', 'webp_quality');
|
||||
if((! $quality) || ($quality > 100))
|
||||
|
||||
if((! $quality) || ($quality > 100)) {
|
||||
$quality = WEBP_QUALITY;
|
||||
\imagewebp($this->image, NULL, $quality);
|
||||
}
|
||||
|
||||
if (function_exists('imagewebp')) {
|
||||
\imagewebp($this->image, NULL, $quality);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'image/jpeg':
|
||||
@@ -177,9 +189,15 @@ class PhotoGd extends PhotoDriver {
|
||||
|
||||
default:
|
||||
$quality = Config::Get('system', 'jpeg_quality');
|
||||
if((! $quality) || ($quality > 100))
|
||||
|
||||
if((! $quality) || ($quality > 100)) {
|
||||
$quality = JPEG_QUALITY;
|
||||
\imagejpeg($this->image, NULL, $quality);
|
||||
}
|
||||
|
||||
if (function_exists('imagejpeg')) {
|
||||
\imagejpeg($this->image, NULL, $quality);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,16 +5,9 @@ namespace Zotlabs\Web;
|
||||
|
||||
class HttpMeta {
|
||||
|
||||
private $vars = null;
|
||||
private $og = null;
|
||||
|
||||
function __construct() {
|
||||
|
||||
$this->vars = [];
|
||||
$this->og = [];
|
||||
$this->ogproperties = [];
|
||||
|
||||
}
|
||||
private $vars = [];
|
||||
private $og = [];
|
||||
private $ogproperties = [];
|
||||
|
||||
//Set Meta Value
|
||||
// Mode:
|
||||
|
||||
@@ -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']) {
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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"'
|
||||
];
|
||||
|
||||
|
||||
@@ -170,10 +170,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 +293,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++;
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
|
||||
|
||||
@@ -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'),
|
||||
@@ -173,6 +173,8 @@ class Notifications {
|
||||
'$notifications' => $notifications,
|
||||
'$no_notifications' => t('Sorry, you have got no notifications at the moment'),
|
||||
'$loading' => t('Loading'),
|
||||
'$sys_only' => empty($arr['sys_only']) ? 0 : 1
|
||||
|
||||
]);
|
||||
|
||||
return $o;
|
||||
|
||||
@@ -40,7 +40,7 @@ class Permcats {
|
||||
if($active_role) {
|
||||
|
||||
$roles[] = [
|
||||
'name' => '<i class="fa fa-plus"></i> ' . t('Add new role'),
|
||||
'name' => '<i class="bi bi-plus-lg"></i> ' . t('Add new role'),
|
||||
'url' => z_root() . '/permcats',
|
||||
'active' => ''
|
||||
];
|
||||
|
||||
@@ -42,7 +42,7 @@ class Privacygroups {
|
||||
if ($active) {
|
||||
$menu_items[] = [
|
||||
'href' => $z_root . '/group',
|
||||
'label' => '<i class="fa fa-plus"></i> ' . t('Add new group'),
|
||||
'label' => '<i class="bi bi-plus-lg"></i> ' . t('Add new group'),
|
||||
'title' => '',
|
||||
'active' => '',
|
||||
'count' => ''
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -38,7 +38,7 @@ class Tokens {
|
||||
if ($active) {
|
||||
$menu_items[] = [
|
||||
'href' => $z_root . '/tokens',
|
||||
'label' => '<i class="fa fa-plus"></i> ' . t('Add new guest'),
|
||||
'label' => '<i class="bi bi-plus-lg"></i> ' . t('Add new guest'),
|
||||
'title' => '',
|
||||
'active' => ''
|
||||
];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 2
|
||||
version: 3
|
||||
url: $baseurl/affinity
|
||||
requires: local_channel
|
||||
name: Affinity Tool
|
||||
photo: icon:arrows-h
|
||||
photo: icon:arrows
|
||||
categories: Networking
|
||||
desc: This app presents a slider control in your connection editor and also on your network page. The slider represents your degree of friendship (affinity) with each connection. It allows you to zoom in or out and display conversations from only your closest friends or everybody in your stream.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 2
|
||||
version: 4
|
||||
url: $baseurl/cdav/calendar, $baseurl/settings/calendar
|
||||
requires: local_channel
|
||||
name: Calendar
|
||||
photo: icon:calendar
|
||||
photo: icon:calendar-date
|
||||
categories: Productivity, nav_featured_app
|
||||
desc: DAV capable calendar
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/cdav/addressbook
|
||||
requires: local_channel
|
||||
name: CardDAV
|
||||
photo: icon:vcard-o
|
||||
photo: icon:person-vcard
|
||||
categories: Productivity, Personal
|
||||
desc: DAV capable addressbook
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 4
|
||||
version: 5
|
||||
url: $baseurl/channel/$nick, $baseurl/settings/channel_home
|
||||
requires: local_channel
|
||||
name: Channel
|
||||
photo: icon:home
|
||||
photo: icon:house
|
||||
categories: nav_featured_app, Personal
|
||||
desc: Your channel homepage featuring your personal posts.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/chat/$nick
|
||||
requires: local_channel
|
||||
name: Chatrooms
|
||||
photo: icon:comments-o
|
||||
photo: icon:chat-text
|
||||
categories: Productivity
|
||||
desc: Access controlled personal chatrooms.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/connections, $baseurl/settings/connections
|
||||
requires: local_channel
|
||||
name: Connections
|
||||
photo: icon:users
|
||||
photo: icon:people
|
||||
categories: nav_featured_app, Networking
|
||||
desc: Manage your connections.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/defperms
|
||||
requires: local_channel, custom_role
|
||||
name: Default Permissions
|
||||
photo: icon:unlock-alt
|
||||
photo: icon:person-lock
|
||||
categories: Access Control
|
||||
desc: Set custom default permissions for new connections.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/directory, $baseurl/settings/directory
|
||||
name: Directory
|
||||
photo: icon:sitemap
|
||||
photo: icon:diagram-3
|
||||
categories: nav_featured_app, Networking
|
||||
desc: Members directory of the Zot network.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 4
|
||||
version: 5
|
||||
url: $baseurl/group
|
||||
requires: local_channel
|
||||
name: Privacy Groups
|
||||
photo: icon:lock
|
||||
photo: icon:file-lock
|
||||
categories: Networking
|
||||
desc: A tool to create and manage privacy groups.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/help
|
||||
name: Help
|
||||
photo: icon:question
|
||||
photo: icon:question-lg
|
||||
categories: nav_featured_app, System
|
||||
desc: The Hubzilla help pages.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 2
|
||||
version: 3
|
||||
url: $baseurl/hq
|
||||
requires: local_channel
|
||||
name: HQ
|
||||
photo: icon:user-circle-o
|
||||
photo: icon:person-circle
|
||||
categories: nav_pinned_app
|
||||
desc: The default landing page after login. It provides a quick overview over recent posts and direct messages.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/invite
|
||||
requires: local_channel
|
||||
name: Invite
|
||||
photo: icon:user-plus
|
||||
photo: icon:person-plus
|
||||
categories: Networking
|
||||
desc: Send invite emails with an invite token. This app only works if your hub is configured to allow invites.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/lang
|
||||
name: Language
|
||||
photo: icon:language
|
||||
photo: icon:translate
|
||||
categories: System
|
||||
desc: A simple language selector.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/network, $baseurl/settings/network
|
||||
requires: local_channel
|
||||
name: Network
|
||||
photo: icon:th
|
||||
photo: icon:grid-3x3
|
||||
categories: nav_featured_app, Networking
|
||||
desc: Your network activity in a traditional timeline view.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/notes
|
||||
requires: local_channel
|
||||
name: Notes
|
||||
photo: icon:sticky-note-o
|
||||
photo: icon:sticky
|
||||
categories: Personal, Productivity
|
||||
desc: A simple notes app. It provides a dedicated notes app and a widget which can be added to other pages.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/oauth
|
||||
requires: local_channel
|
||||
name: OAuth Apps Manager
|
||||
photo: icon:chevron-circle-up
|
||||
photo: icon:1-circle-fill
|
||||
categories: Access Control
|
||||
desc: Manage OAuth authentication tokens for mobile and remote apps.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/oauth2
|
||||
requires: local_channel
|
||||
name: OAuth2 Apps Manager
|
||||
photo: icon:chevron-circle-up
|
||||
photo: icon:2-circle-fill
|
||||
categories: Access Control
|
||||
desc: Manage OAuth2 authentication tokens for mobile and remote apps.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 1
|
||||
version: 2
|
||||
url: $baseurl/pdledit_gui
|
||||
requires: local_channel
|
||||
name: PDL Editor
|
||||
photo: icon:object-group
|
||||
photo: icon:columns-gap
|
||||
categories: Appearance
|
||||
desc: An editor for system page layouts.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 5
|
||||
version: 6
|
||||
url: $baseurl/permcats
|
||||
requires: local_channel
|
||||
name: Contact Roles
|
||||
photo: icon:user-o
|
||||
photo: icon:person-lock
|
||||
categories: Access Control
|
||||
desc: Create and manage custom contact roles.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/photos/$nick, $baseurl/settings/photos
|
||||
requires: local_channel
|
||||
name: Photos
|
||||
photo: icon:photo
|
||||
photo: icon:image
|
||||
categories: nav_featured_app, Multimedia
|
||||
desc: A simple tool to view and manage your photos.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
url: $baseurl/rpost?f=&body=
|
||||
version: 4
|
||||
url: $baseurl/rpost
|
||||
requires: observer
|
||||
name: Post
|
||||
photo: icon:pencil-square
|
||||
photo: icon:pencil-fill
|
||||
categories: Productivity
|
||||
desc: A separate post editor.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 4
|
||||
version: 5
|
||||
url: $baseurl/zot_probe
|
||||
requires: local_channel
|
||||
name: Remote Diagnostics
|
||||
photo: icon:user-md
|
||||
photo: icon:tools
|
||||
categories: Developer
|
||||
desc: A diagnose tool useful for developers.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/randprof
|
||||
name: Random Channel
|
||||
target: randprof
|
||||
photo: icon:random
|
||||
photo: icon:shuffle
|
||||
categories: Networking
|
||||
desc: Visit a random channel in the network.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/sources
|
||||
requires: local_channel
|
||||
name: Channel Sources
|
||||
photo: icon:commenting-o
|
||||
photo: icon:chat-dots
|
||||
categories: Networking
|
||||
desc: Import channel content from other channels or feeds.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/cloud/$nick
|
||||
requires: local_channel
|
||||
name: Files
|
||||
photo: icon:folder-open
|
||||
photo: icon:folder
|
||||
categories: nav_featured_app, Productivity
|
||||
desc: A mighty tool to manage your files and folders.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/suggest
|
||||
requires: local_channel
|
||||
name: Suggest Channels
|
||||
photo: icon:lightbulb-o
|
||||
photo: icon:person-lines-fill
|
||||
categories: Networking
|
||||
desc: Suggestions for channels in the network you might be interested in.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/tokens
|
||||
requires: local_channel
|
||||
name: Guest Access
|
||||
photo: icon:user-secret
|
||||
photo: icon:incognito
|
||||
categories: Access Control
|
||||
desc: Create and manage guest access tokens. Those tokens are useful to share private content with people outside the Zot network.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/uexport
|
||||
requires: local_channel
|
||||
name: Channel Export
|
||||
photo: icon:download
|
||||
photo: icon:person-down
|
||||
categories: Personal, System
|
||||
desc: Export your channel.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 3
|
||||
version: 4
|
||||
url: $baseurl/webpages/$nick
|
||||
requires: local_channel
|
||||
name: Webpages
|
||||
photo: icon:newspaper-o
|
||||
photo: icon:layout-text-sidebar
|
||||
categories: nav_featured_app, Productivity
|
||||
desc: Create and manage web pages for your channel.
|
||||
|
||||
82
boot.php
82
boot.php
@@ -66,7 +66,7 @@ require_once('include/security.php');
|
||||
|
||||
|
||||
define('PLATFORM_NAME', 'hubzilla');
|
||||
define('STD_VERSION', '9.2');
|
||||
define('STD_VERSION', '9.4.4');
|
||||
define('ZOT_REVISION', '6.0');
|
||||
|
||||
define('DB_UPDATE_VERSION', 1263);
|
||||
@@ -1897,23 +1897,26 @@ function can_view_public_stream() {
|
||||
*/
|
||||
function notice($s) {
|
||||
|
||||
/*
|
||||
if(! session_id())
|
||||
return;
|
||||
/*
|
||||
|
||||
if(! x($_SESSION, 'sysmsg')) $_SESSION['sysmsg'] = array();
|
||||
if (!session_id()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore duplicated error messages which haven't yet been displayed
|
||||
// - typically seen as multiple 'permission denied' messages
|
||||
// as a result of auto-reloading a protected page with &JS=1
|
||||
if (!isset($_SESSION['sysmsg'])) {
|
||||
$_SESSION['sysmsg'] = [];
|
||||
}
|
||||
|
||||
if(in_array($s, $_SESSION['sysmsg']))
|
||||
return;
|
||||
// ignore duplicated error messages which haven't yet been displayed
|
||||
|
||||
if(App::$interactive) {
|
||||
$_SESSION['sysmsg'][] = $s;
|
||||
}
|
||||
*/
|
||||
if (in_array($s, $_SESSION['sysmsg'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (App::$interactive) {
|
||||
$_SESSION['sysmsg'][] = $s;
|
||||
}
|
||||
*/
|
||||
|
||||
$hash = get_observer_hash();
|
||||
$sse_id = false;
|
||||
@@ -1928,19 +1931,22 @@ function notice($s) {
|
||||
}
|
||||
}
|
||||
|
||||
$x = null;
|
||||
|
||||
$t = get_xconfig($hash, 'sse', 'timestamp', NULL_DATE);
|
||||
|
||||
if (datetime_convert('UTC', 'UTC', $t) < datetime_convert('UTC', 'UTC', '- 30 seconds')) {
|
||||
set_xconfig($hash, 'sse', 'notifications', []);
|
||||
$x = [];
|
||||
}
|
||||
|
||||
$x = get_xconfig($hash, 'sse', 'notifications');
|
||||
if ($x === null) {
|
||||
$x = get_xconfig($hash, 'sse', 'notifications', []);
|
||||
}
|
||||
|
||||
if ($x === false)
|
||||
$x = [];
|
||||
|
||||
if (isset($x['notice']) && in_array($s, $x['notice']['notifications']))
|
||||
if (isset($x['notice']) && in_array($s, $x['notice']['notifications'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (App::$interactive) {
|
||||
$x['notice']['notifications'][] = $s;
|
||||
@@ -1960,20 +1966,25 @@ function notice($s) {
|
||||
* @param string $s Text to display
|
||||
*/
|
||||
function info($s) {
|
||||
/*
|
||||
if (!session_id()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
if(! session_id())
|
||||
return;
|
||||
if (!isset($_SESSION['sysmsg_info'])) {
|
||||
$_SESSION['sysmsg_info'] = [];
|
||||
}
|
||||
|
||||
if(! x($_SESSION, 'sysmsg_info'))
|
||||
$_SESSION['sysmsg_info'] = array();
|
||||
// ignore duplicated error messages which haven't yet been displayed
|
||||
|
||||
if(in_array($s, $_SESSION['sysmsg_info']))
|
||||
return;
|
||||
if (in_array($s, $_SESSION['sysmsg_info'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(App::$interactive)
|
||||
$_SESSION['sysmsg_info'][] = $s;
|
||||
*/
|
||||
if (App::$interactive) {
|
||||
$_SESSION['sysmsg_info'][] = $s;
|
||||
}
|
||||
*/
|
||||
|
||||
$hash = get_observer_hash();
|
||||
$sse_id = false;
|
||||
@@ -1988,19 +1999,22 @@ function info($s) {
|
||||
}
|
||||
}
|
||||
|
||||
$x = null;
|
||||
|
||||
$t = get_xconfig($hash, 'sse', 'timestamp', NULL_DATE);
|
||||
|
||||
if (datetime_convert('UTC', 'UTC', $t) < datetime_convert('UTC', 'UTC', '- 30 seconds')) {
|
||||
set_xconfig($hash, 'sse', 'notifications', []);
|
||||
$x = [];
|
||||
}
|
||||
|
||||
$x = get_xconfig($hash, 'sse', 'notifications');
|
||||
if ($x === null) {
|
||||
$x = get_xconfig($hash, 'sse', 'notifications', []);
|
||||
}
|
||||
|
||||
if ($x === false)
|
||||
$x = [];
|
||||
|
||||
if (isset($x['info']) && in_array($s, $x['info']['notifications']))
|
||||
if (isset($x['info']) && in_array($s, $x['info']['notifications'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (App::$interactive) {
|
||||
$x['info']['notifications'][] = $s;
|
||||
|
||||
@@ -55,10 +55,11 @@
|
||||
"patrickschur/language-detection": "^5.3",
|
||||
"stephenhill/base58": "^1.1",
|
||||
"mmccook/php-json-canonicalization-scheme": "^1.0",
|
||||
"scssphp/scssphp": "^1.12"
|
||||
"scssphp/scssphp": "^1.12",
|
||||
"twbs/bootstrap-icons": "^1.11"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-yaml": "*",
|
||||
"ext-yaml": "*",
|
||||
"phpunit/phpunit": "^10.5",
|
||||
"php-mock/php-mock-phpunit": "^2.10",
|
||||
"phpmd/phpmd": "^2.6",
|
||||
|
||||
57
composer.lock
generated
57
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "2c6f7ad91fff98ebeb5fd339a8856d29",
|
||||
"content-hash": "a3d39881eecda53834cbcb595100e00e",
|
||||
"packages": [
|
||||
{
|
||||
"name": "blueimp/jquery-file-upload",
|
||||
@@ -1906,16 +1906,16 @@
|
||||
},
|
||||
{
|
||||
"name": "smarty/smarty",
|
||||
"version": "v4.4.1",
|
||||
"version": "v4.5.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/smarty-php/smarty.git",
|
||||
"reference": "f4152e9b814ae2369b6e4935c05e1e0c3654318d"
|
||||
"reference": "c11676e85aa71bc7c3cd9100f1655a9f4d14616e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/f4152e9b814ae2369b6e4935c05e1e0c3654318d",
|
||||
"reference": "f4152e9b814ae2369b6e4935c05e1e0c3654318d",
|
||||
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/c11676e85aa71bc7c3cd9100f1655a9f4d14616e",
|
||||
"reference": "c11676e85aa71bc7c3cd9100f1655a9f4d14616e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1966,9 +1966,9 @@
|
||||
"support": {
|
||||
"forum": "https://github.com/smarty-php/smarty/discussions",
|
||||
"issues": "https://github.com/smarty-php/smarty/issues",
|
||||
"source": "https://github.com/smarty-php/smarty/tree/v4.4.1"
|
||||
"source": "https://github.com/smarty-php/smarty/tree/v4.5.4"
|
||||
},
|
||||
"time": "2024-02-26T13:58:37+00:00"
|
||||
"time": "2024-08-14T20:04:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spomky-labs/otphp",
|
||||
@@ -2218,6 +2218,45 @@
|
||||
},
|
||||
"time": "2024-02-20T15:14:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "twbs/bootstrap-icons",
|
||||
"version": "v1.11.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twbs/icons.git",
|
||||
"reference": "8d88686c03c3768a2d82ba4f20c3c4e1b100fa29"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twbs/icons/zipball/8d88686c03c3768a2d82ba4f20c3c4e1b100fa29",
|
||||
"reference": "8d88686c03c3768a2d82ba4f20c3c4e1b100fa29",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Mark Otto",
|
||||
"email": "markdotto@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Official open source SVG icon library for Bootstrap",
|
||||
"homepage": "https://icons.getbootstrap.com/",
|
||||
"keywords": [
|
||||
"bootstrap",
|
||||
"icon font",
|
||||
"icons",
|
||||
"svg"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/twbs/icons/issues",
|
||||
"source": "https://github.com/twbs/icons/tree/v1.11.3"
|
||||
},
|
||||
"time": "2024-01-03T15:44:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "voku/portable-ascii",
|
||||
"version": "2.0.1",
|
||||
@@ -5241,8 +5280,6 @@
|
||||
"ext-sodium": "*",
|
||||
"ext-bcmath": "*"
|
||||
},
|
||||
"platform-dev": {
|
||||
"ext-yaml": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[size=large][b]Was ist $Projectname?[/b][/size]
|
||||
[h3]Was ist $Projectname?[/h3]
|
||||
|
||||
$Projectname ist ein dezentralisiertes Kommunikationsnetzwerk mit dem Ziel, Kommunikationsmöglichkeiten bereitzustellen, die Zensur umgehen, die Privatsphäre respektieren und somit frei sind von den Einschränkungen, die die heutigen kommerziellen Kommunikationsgiganten uns auferlegen. Diese stellen in erster Linie Spionagenetzwerke für zahlende Kunden aller Art zur Verfügung und monopolisieren und zentralisieren das ganze Internet – was ursprünglich eben gerade nicht unter den revolutionären Zielen war, die einst zum World Wide Web führten.
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
Privacy Policy
|
||||
==============
|
||||
|
||||
#include doc/gdpr1.md;
|
||||
#include doc/en/gdpr1.md;
|
||||
|
||||
|
||||
Terms of Service
|
||||
================
|
||||
|
||||
#include doc/SiteTOS.md;
|
||||
#include doc/en/SiteTOS.md;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ function populate_acl($defaults = null,$show_jotnets = true, $emptyACL_descripti
|
||||
|
||||
$allow_cid = $allow_gid = $deny_cid = $deny_gid = false;
|
||||
$showall_origin = '';
|
||||
$showall_icon = 'fa-globe';
|
||||
$showall_icon = 'bi-globe';
|
||||
$role = get_pconfig(local_channel(), 'system', 'permissions_role');
|
||||
|
||||
if(! $emptyACL_description) {
|
||||
|
||||
@@ -2599,33 +2599,31 @@ function attach_move($channel_id, $resource_id, $new_folder_hash, $newname = '',
|
||||
intval($r[0]['id'])
|
||||
);
|
||||
|
||||
if($r[0]['is_photo']) {
|
||||
q("update photo set album = '%s', filename = '%s', os_path = '%s', display_path = '%s'
|
||||
where resource_id = '%s' and uid = %d",
|
||||
dbesc($newalbumname),
|
||||
dbesc($filename),
|
||||
dbesc($x['os_path']),
|
||||
dbesc($x['path']),
|
||||
dbesc($resource_id),
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
q("update photo set content = CASE imgscale WHEN 0 THEN %s ELSE CONCAT(%s, '-', imgscale) END where resource_id = '%s' and uid = %d and os_storage = 1",
|
||||
dbescbin($newstorepath),
|
||||
dbescbin($newstorepath),
|
||||
dbesc($resource_id),
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
// now rename the thumbnails in os_storage - the original should have been copied before already
|
||||
$ps = q("SELECT content, imgscale FROM photo WHERE uid = %d AND resource_id = '%s' and imgscale > 0 and os_storage = 1",
|
||||
if ($r[0]['is_photo']) {
|
||||
// update the photo DB entries and copy the thumbnails
|
||||
$ps = q("SELECT imgscale FROM photo WHERE uid = %d AND resource_id = '%s' and os_storage = 1",
|
||||
intval($channel_id),
|
||||
dbesc($resource_id)
|
||||
);
|
||||
|
||||
if ($recurse) {
|
||||
foreach($ps as $p) {
|
||||
rename($oldstorepath . '-' . $p['imgscale'], $p['content']);
|
||||
q("update photo set album = '%s', filename = '%s', os_path = '%s', display_path = '%s', content = '%s'
|
||||
where resource_id = '%s' and imgscale = %d and uid = %d",
|
||||
dbesc($newalbumname),
|
||||
dbesc($filename),
|
||||
dbesc($x['os_path']),
|
||||
dbesc($x['path']),
|
||||
dbescbin($newstorepath . ((intval($p['imgscale']) > 0) ? '-' . $p['imgscale'] : '')),
|
||||
dbesc($resource_id),
|
||||
intval($p['imgscale']),
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
// the original should have been copied already
|
||||
if (intval($p['imgscale']) > 0) {
|
||||
rename($oldstorepath . '-' . $p['imgscale'], $newstorepath . '-' . $p['imgscale']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3106,7 +3106,7 @@ function pchan_to_chan($pchan) {
|
||||
}
|
||||
|
||||
function channel_url($channel) {
|
||||
return (($channel) ? z_root() . '/channel/' . $channel['channel_address'] : z_root());
|
||||
return ((isset($channel['channel_address'])) ? z_root() . '/channel/' . $channel['channel_address'] : z_root());
|
||||
}
|
||||
|
||||
function get_channel_hashes() {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\Config;
|
||||
use Zotlabs\Lib\PConfig;
|
||||
|
||||
require_once('include/items.php');
|
||||
|
||||
@@ -438,17 +439,22 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa
|
||||
|
||||
$uploading = false;
|
||||
|
||||
if(local_channel()) {
|
||||
$cur_channel = App::get_channel();
|
||||
if($cur_channel['channel_allow_cid'] === '' && $cur_channel['channel_allow_gid'] === ''
|
||||
&& $cur_channel['channel_deny_cid'] === '' && $cur_channel['channel_deny_gid'] === ''
|
||||
$channel = App::get_channel();
|
||||
$observer = App::get_observer();
|
||||
|
||||
if (local_channel()) {
|
||||
// Allow uploading if there is no default privacy and the view_storage permission is set to PERMS_PUBLIC
|
||||
if ($channel['channel_allow_cid'] === '' && $channel['channel_allow_gid'] === ''
|
||||
&& $channel['channel_deny_cid'] === '' && $channel['channel_deny_gid'] === ''
|
||||
&& intval(\Zotlabs\Access\PermissionLimits::Get(local_channel(),'view_storage')) === PERMS_PUBLIC) {
|
||||
$uploading = true;
|
||||
}
|
||||
}
|
||||
|
||||
$channel = App::get_channel();
|
||||
$observer = App::get_observer();
|
||||
// Allow uploading if OCAP tokens are enabled
|
||||
if (PConfig::Get(local_channel(), 'system', 'ocap_enabled')) {
|
||||
$uploading = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$update) {
|
||||
$_SESSION['return_url'] = App::$query_string;
|
||||
@@ -817,7 +823,7 @@ function thread_action_menu($item,$mode = '') {
|
||||
$menu[] = [
|
||||
'menu' => 'unfollow_thread',
|
||||
'title' => t('Unfollow Thread'),
|
||||
'icon' => 'minus',
|
||||
'icon' => 'dash',
|
||||
'action' => 'dounsubthread(' . $item['id'] . '); return false;',
|
||||
'href' => '#'
|
||||
];
|
||||
@@ -999,7 +1005,7 @@ function builtin_activity_puller($item, &$conv_responses) {
|
||||
|
||||
$name = (($item['author']['xchan_name']) ? $item['author']['xchan_name'] : t('Unknown'));
|
||||
|
||||
$moderate = ((intval($item['item_blocked']) === ITEM_MODERATED) ? '<a href="moderate/' . $item['id'] . '/approve" onclick="moderate_approve(' . $item['id'] . '); return false;" class="text-success pe-2" title="' . t('Approve this item') . '"><i class="fa fa-check" ></i></a><a href="moderate/' . $item['id'] . '/drop" onclick="moderate_drop(' . $item['id'] . '); return false;" class="text-danger pe-2" title="' . t('Delete this item') . '"><i class="fa fa-trash-o" ></i></a>' : '');
|
||||
$moderate = ((intval($item['item_blocked']) === ITEM_MODERATED) ? '<a href="moderate/' . $item['id'] . '/approve" onclick="moderate_approve(' . $item['id'] . '); return false;" class="text-success pe-2" title="' . t('Approve this item') . '"><i class="bi bi-check-lg" ></i></a><a href="moderate/' . $item['id'] . '/drop" onclick="moderate_drop(' . $item['id'] . '); return false;" class="text-danger pe-2" title="' . t('Delete this item') . '"><i class="bi bi-trash" ></i></a>' : '');
|
||||
|
||||
$url = (($item['author_xchan'] && $item['author']['xchan_photo_s'])
|
||||
? '<div class="dropdown-item">' . $moderate . '<a href="' . chanlink_hash($item['author_xchan']) . '" class="text-reset">' . '<img class="menu-img-1" src="' . zid($item['author']['xchan_photo_s']) . '" alt="' . urlencode($name) . '" /> ' . $name . '</a></div>'
|
||||
@@ -1467,14 +1473,18 @@ function render_location_default($item) {
|
||||
$location = $item['location'];
|
||||
$coord = $item['coord'];
|
||||
|
||||
if($coord) {
|
||||
if ($coord) {
|
||||
if($location)
|
||||
$location .= ' <span class="smalltext">(' . $coord . ')</span>';
|
||||
$location .= ' (' . $coord . ')';
|
||||
else
|
||||
$location = '<span class="smalltext">' . $coord . '</span>';
|
||||
$location = $coord;
|
||||
}
|
||||
|
||||
return $location;
|
||||
if (!$location) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return '<i class="bi bi-geo-alt" title="' . $location . '"></i>';
|
||||
}
|
||||
|
||||
|
||||
@@ -1525,6 +1535,12 @@ function get_responses($conv_responses,$response_verbs,$ob,$item) {
|
||||
|
||||
$ret = array();
|
||||
foreach($response_verbs as $v) {
|
||||
if ($v === 'answer') {
|
||||
// we require the structure to collect the response hashes
|
||||
// but we do not use them for display - do not collect them.
|
||||
continue;
|
||||
}
|
||||
|
||||
$ret[$v] = [];
|
||||
$ret[$v]['count'] = $conv_responses[$v][$item['mid']] ?? 0;
|
||||
$ret[$v]['list'] = ((isset($conv_responses[$v][$item['mid']])) ? $conv_responses[$v][$item['mid'] . '-l'] : '');
|
||||
@@ -1533,14 +1549,6 @@ function get_responses($conv_responses,$response_verbs,$ob,$item) {
|
||||
$ret[$v]['modal'] = (($ret[$v]['count'] > MAX_LIKERS) ? true : false);
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
foreach ($ret as $key) {
|
||||
if ($key['count'] == true)
|
||||
$count++;
|
||||
}
|
||||
|
||||
$ret['count'] = $count;
|
||||
|
||||
//logger('ret: ' . print_r($ret,true));
|
||||
|
||||
return $ret;
|
||||
@@ -1549,25 +1557,25 @@ function get_responses($conv_responses,$response_verbs,$ob,$item) {
|
||||
function get_response_button_text($v,$count) {
|
||||
switch($v) {
|
||||
case 'like':
|
||||
return ['label' => tt('Like','Likes',$count,'noun'), 'icon' => 'thumbs-o-up', 'class' => 'like'];
|
||||
return ['label' => tt('Like','Likes',$count,'noun'), 'icon' => 'hand-thumbs-up', 'class' => 'like', 'onclick' => 'dolike'];
|
||||
break;
|
||||
case 'announce':
|
||||
return ['label' => tt('Repeat','Repeats',$count,'noun'), 'icon' => 'retweet', 'class' => 'announce'];
|
||||
return ['label' => tt('Repeat','Repeats',$count,'noun'), 'icon' => 'repeat', 'class' => 'announce', 'onclick' => 'jotShare'];
|
||||
break;
|
||||
case 'dislike':
|
||||
return ['label' => tt('Dislike','Dislikes',$count,'noun'), 'icon' => 'thumbs-o-down', 'class' => 'dislike'];
|
||||
return ['label' => tt('Dislike','Dislikes',$count,'noun'), 'icon' => 'hand-thumbs-down', 'class' => 'dislike', 'onclick' => 'dolike'];
|
||||
break;
|
||||
case 'attendyes':
|
||||
return ['label' => tt('Attending','Attending',$count,'noun'), 'icon' => 'calendar-check-o', 'class' => 'attendyes'];
|
||||
return ['label' => tt('Attending','Attending',$count,'noun'), 'icon' => 'calendar-check', 'class' => 'attendyes', 'onclick' => 'dolike'];
|
||||
break;
|
||||
case 'attendno':
|
||||
return ['label' => tt('Not Attending','Not Attending',$count,'noun'), 'icon' => 'calendar-times-o', 'class' => 'attendno'];
|
||||
return ['label' => tt('Not Attending','Not Attending',$count,'noun'), 'icon' => 'calendar-x', 'class' => 'attendno', 'onclick' => 'dolike'];
|
||||
break;
|
||||
case 'attendmaybe':
|
||||
return ['label' => tt('Undecided','Undecided',$count,'noun'), 'icon' => 'calendar-o', 'class' => 'attendmaybe'];
|
||||
return ['label' => tt('Undecided','Undecided',$count,'noun'), 'icon' => 'calendar', 'class' => 'attendmaybe', 'onclick' => 'dolike'];
|
||||
break;
|
||||
default:
|
||||
return '';
|
||||
return [];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ function format_event_html($ev) {
|
||||
|
||||
$o = '<div class="vevent">' . "\r\n";
|
||||
|
||||
$o .= '<div class="event-title"><h3><i class="fa fa-calendar"></i> ' . zidify_links(smilies(bbcode($ev['summary']))) . '</h3></div>' . "\r\n";
|
||||
$o .= '<div class="event-title"><h3><i class="bi bi-calendar-date"></i> ' . zidify_links(smilies(bbcode($ev['summary']))) . '</h3></div>' . "\r\n";
|
||||
|
||||
$o .= '<div class="event-start"><span class="event-label">' . t('Starts:') . '</span> <span class="dtstart" title="'
|
||||
. datetime_convert('UTC', 'UTC', $ev['dtstart'], ((isset($ev['adjust']) && $ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
|
||||
|
||||
@@ -217,14 +217,11 @@ function html2bbcode($message)
|
||||
|
||||
node2bbcode($doc, 'hr', array(), "[hr]", "");
|
||||
|
||||
// node2bbcode($doc, 'table', array(), "", "");
|
||||
// node2bbcode($doc, 'tr', array(), "\n", "");
|
||||
// node2bbcode($doc, 'td', array(), "\t", "");
|
||||
|
||||
node2bbcode($doc, 'table', array(), "[table]", "[/table]");
|
||||
node2bbcode($doc, 'th', array(), "[th]", "[/th]");
|
||||
node2bbcode($doc, 'tr', array(), "[tr]", "[/tr]");
|
||||
node2bbcode($doc, 'td', array(), "[td]", "[/td]");
|
||||
node2bbcode($doc, 'table', array(), "[table]", "[/table]");
|
||||
|
||||
|
||||
node2bbcode($doc, 'h1', array(), "[h1]", "[/h1]");
|
||||
node2bbcode($doc, 'h2', array(), "[h2]", "[/h2]");
|
||||
|
||||
@@ -2951,35 +2951,32 @@ function tgroup_check($uid, $item) {
|
||||
// post to group via DM
|
||||
|
||||
if ($is_group) {
|
||||
if (intval($item['item_private']) === 2 && $item['mid'] === $item['parent_mid']) {
|
||||
if (intval($item['item_private']) === 2 && $item['mid'] === $item['parent_mid'] && perm_is_allowed($uid, $item['owner_xchan'], 'post_wall')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// see if we already have this item. Maybe it is being updated.
|
||||
|
||||
$r = q("select id from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($item['mid']),
|
||||
intval($uid)
|
||||
);
|
||||
if($r)
|
||||
|
||||
if ($r) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(! perm_is_allowed($uid,$item['author_xchan'],'tag_deliver'))
|
||||
return false;
|
||||
|
||||
$u = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
if(! $u)
|
||||
$u = channelx_by_n($uid);
|
||||
|
||||
if (!$u) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$max_forums = Config::Get('system','max_tagged_forums',2);
|
||||
$matched_forums = 0;
|
||||
|
||||
$link = normalise_link($u[0]['xchan_url']);
|
||||
$link = normalise_link($u['xchan_url']);
|
||||
|
||||
$terms = [];
|
||||
|
||||
@@ -2996,7 +2993,7 @@ function tgroup_check($uid, $item) {
|
||||
}
|
||||
|
||||
$mention = true;
|
||||
logger('tgroup_check: mention found for ' . $u[0]['channel_name']);
|
||||
logger('tgroup_check: mention found for ' . $u['channel_name']);
|
||||
|
||||
// At this point we've determined that the person receiving this post was mentioned in it.
|
||||
// Now let's check if this mention was inside a reshare so we don't spam a forum
|
||||
@@ -3199,7 +3196,9 @@ function start_delivery_chain($channel, $item, $item_id, $parent, $group = false
|
||||
|
||||
}
|
||||
else {
|
||||
$arr['uuid'] = item_message_id();
|
||||
// To prevent duplicates from possible clones of the forum/group,
|
||||
// will create a v5 UUID of the source item mid.
|
||||
$arr['uuid'] = uuid_from_url($item['mid']);
|
||||
$arr['mid'] = z_root() . '/item/' . $arr['uuid'];
|
||||
$arr['parent_mid'] = $arr['mid'];
|
||||
}
|
||||
@@ -5008,7 +5007,7 @@ function fix_attached_permissions($uid, $body, $str_contact_allow, $str_group_al
|
||||
|
||||
$attach = array_shift($attach_q);
|
||||
|
||||
$new_public = !(($str_contact_allow || $str_group_allow || $str_contact_deny || $str_group_deny));
|
||||
//$new_public = !(($str_contact_allow || $str_group_allow || $str_contact_deny || $str_group_deny));
|
||||
$existing_public = !(($attach['allow_cid'] || $attach['allow_gid'] || $attach['deny_cid'] || $attach['deny_gid']));
|
||||
|
||||
if ($existing_public) {
|
||||
@@ -5023,10 +5022,11 @@ function fix_attached_permissions($uid, $body, $str_contact_allow, $str_group_al
|
||||
continue;
|
||||
}
|
||||
|
||||
$item_private = 0;
|
||||
|
||||
if ($new_public === false) {
|
||||
$item_private = (($str_group_allow || ($str_contact_allow && substr_count($str_contact_allow,'<') > 2)) ? 1 : 2);
|
||||
if ($token) {
|
||||
$str_contact_allow = $attach['allow_cid'];
|
||||
$str_group_allow = $attach['allow_gid'];
|
||||
$str_contact_deny = $attach['deny_cid'];
|
||||
$str_group_deny = $attach['deny_gid'];
|
||||
|
||||
// preserve any existing tokens that may have been set for this file
|
||||
$token_matches = null;
|
||||
@@ -5054,7 +5054,7 @@ function fix_attached_permissions($uid, $body, $str_contact_allow, $str_group_al
|
||||
);
|
||||
|
||||
if ($attach['is_photo']) {
|
||||
$r = q("UPDATE photo SET allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s'
|
||||
q("UPDATE photo SET allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s'
|
||||
WHERE resource_id = '%s' AND uid = %d ",
|
||||
dbesc($str_contact_allow),
|
||||
dbesc($str_group_allow),
|
||||
@@ -5064,7 +5064,16 @@ function fix_attached_permissions($uid, $body, $str_contact_allow, $str_group_al
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
$r = q("UPDATE item SET allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d
|
||||
$item_private = 0;
|
||||
|
||||
if ($str_group_allow || $str_contact_deny || $str_group_deny) {
|
||||
$item_private = 1;
|
||||
}
|
||||
elseif ($str_contact_allow) {
|
||||
$item_private = 2;
|
||||
}
|
||||
|
||||
q("UPDATE item SET allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d
|
||||
WHERE resource_id = '%s' AND 'resource_type' = 'photo' AND uid = %d",
|
||||
dbesc($str_contact_allow),
|
||||
dbesc($str_group_allow),
|
||||
@@ -5103,25 +5112,19 @@ function copy_of_pubitem($channel,$mid) {
|
||||
return $item[0];
|
||||
}
|
||||
|
||||
|
||||
$r = q("select * from item where parent_mid = (select parent_mid from item where mid = '%s' and uid = %d ) order by id ",
|
||||
$r = q("select * from item where parent_mid = (select parent_mid from item where mid = '%s' and uid = %d) and uid = %d order by id ",
|
||||
dbesc($mid),
|
||||
intval($syschan['channel_id']),
|
||||
intval($syschan['channel_id'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
$items = fetch_post_tags($r,true);
|
||||
foreach($items as $rv) {
|
||||
$d = q("select id from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($rv['mid']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($d) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($rv['id']);
|
||||
unset($rv['parent']);
|
||||
|
||||
$rv['aid'] = $channel['channel_account_id'];
|
||||
$rv['uid'] = $channel['channel_id'];
|
||||
$rv['item_wall'] = 0;
|
||||
@@ -5134,5 +5137,6 @@ function copy_of_pubitem($channel,$mid) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ function js_strings() {
|
||||
'$delitem' => t('Delete this item?'),
|
||||
'$itemdel' => t('Item deleted'),
|
||||
'$comment' => t('Comment'),
|
||||
'$showmore' => sprintf( t('%s show all'), '<i class=\'fa fa-chevron-down\'></i>'),
|
||||
'$showfewer' => sprintf( t('%s show less'), '<i class=\'fa fa-chevron-up\'></i>'),
|
||||
'$divgrowmore' => sprintf( t('%s expand'), '<i class=\'fa fa-chevron-down\'></i>'),
|
||||
'$divgrowless' => sprintf( t('%s collapse'),'<i class=\'fa fa-chevron-up\'></i>'),
|
||||
'$showmore' => t('show all'),
|
||||
'$showfewer' => t('show less'),
|
||||
'$divgrowmore' => t('expand'),
|
||||
'$divgrowless' => t('collapse'),
|
||||
'$pwshort' => t("Password too short"),
|
||||
'$pwnomatch' => t("Passwords do not match"),
|
||||
'$everybody' => t('everybody'),
|
||||
|
||||
@@ -80,22 +80,6 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) {
|
||||
|
||||
$s = html2bbcode($s);
|
||||
|
||||
// $s = bb_code_protect($s);
|
||||
|
||||
// Convert everything that looks like a link to a link
|
||||
if($use_zrl) {
|
||||
if (strpos($s,'[/img]') !== false) {
|
||||
$s = preg_replace_callback("/\[img\](.*?)\[\/img\]/ism", 'use_zrl_cb_img', $s);
|
||||
$s = preg_replace_callback("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", 'use_zrl_cb_img_x', $s);
|
||||
}
|
||||
$s = preg_replace_callback("/([^\]\=\{\/]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)([\,\.\:\;]\s|$)/ismu", 'use_zrl_cb_link',$s);
|
||||
}
|
||||
else {
|
||||
$s = preg_replace("/([^\]\=\{\/]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)([\,\.\:\;]\s|$)/ismu", '$1[url=$2$3]$2$3[/url]$4',$s);
|
||||
}
|
||||
|
||||
// $s = bb_code_unprotect($s);
|
||||
|
||||
// remove duplicate adjacent code tags
|
||||
$s = preg_replace("/(\[code\])+(.*?)(\[\/code\])+/ism","[code]$2[/code]", $s);
|
||||
|
||||
|
||||
@@ -449,7 +449,7 @@ function channel_apps($is_owner = false, $nickname = null) {
|
||||
'sel' => ((argv(0) == 'channel') ? 'active' : ''),
|
||||
'title' => t('Status Messages and Posts'),
|
||||
'id' => 'status-tab',
|
||||
'icon' => 'home'
|
||||
'icon' => 'house'
|
||||
],
|
||||
];
|
||||
|
||||
@@ -462,7 +462,7 @@ function channel_apps($is_owner = false, $nickname = null) {
|
||||
'sel' => ((argv(0) == 'profile') ? 'active' : ''),
|
||||
'title' => t('Profile Details'),
|
||||
'id' => 'profile-tab',
|
||||
'icon' => 'user'
|
||||
'icon' => 'person'
|
||||
];
|
||||
}
|
||||
if ($p['view_storage']) {
|
||||
@@ -472,7 +472,7 @@ function channel_apps($is_owner = false, $nickname = null) {
|
||||
'sel' => ((argv(0) == 'photos') ? 'active' : ''),
|
||||
'title' => t('Photo Albums'),
|
||||
'id' => 'photo-tab',
|
||||
'icon' => 'photo'
|
||||
'icon' => 'image'
|
||||
];
|
||||
$tabs[] = [
|
||||
'label' => t('Files'),
|
||||
@@ -480,7 +480,7 @@ function channel_apps($is_owner = false, $nickname = null) {
|
||||
'sel' => ((argv(0) == 'cloud' || argv(0) == 'sharedwithme') ? 'active' : ''),
|
||||
'title' => t('Files and Storage'),
|
||||
'id' => 'files-tab',
|
||||
'icon' => 'folder-open'
|
||||
'icon' => 'folder'
|
||||
];
|
||||
}
|
||||
|
||||
@@ -491,7 +491,7 @@ function channel_apps($is_owner = false, $nickname = null) {
|
||||
'sel' => ((argv(0) == 'cal') ? 'active' : ''),
|
||||
'title' => t('Calendar'),
|
||||
'id' => 'event-tab',
|
||||
'icon' => 'calendar'
|
||||
'icon' => 'calendar-date'
|
||||
];
|
||||
}
|
||||
|
||||
@@ -505,7 +505,7 @@ function channel_apps($is_owner = false, $nickname = null) {
|
||||
'sel' => ((argv(0) == 'chat') ? 'active' : ''),
|
||||
'title' => t('Chatrooms'),
|
||||
'id' => 'chat-tab',
|
||||
'icon' => 'comments-o'
|
||||
'icon' => 'chat'
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -529,18 +529,7 @@ function channel_apps($is_owner = false, $nickname = null) {
|
||||
'sel' => ((argv(0) == 'webpages') ? 'active' : ''),
|
||||
'title' => t('View Webpages'),
|
||||
'id' => 'webpages-tab',
|
||||
'icon' => 'newspaper-o'
|
||||
];
|
||||
}
|
||||
|
||||
if ($p['view_wiki'] && Apps::system_app_installed($uid, 'Wiki')) {
|
||||
$tabs[] = [
|
||||
'label' => t('Wikis'),
|
||||
'url' => z_root() . '/wiki/' . $nickname,
|
||||
'sel' => ((argv(0) == 'wiki') ? 'active' : ''),
|
||||
'title' => t('Wiki'),
|
||||
'id' => 'wiki-tab',
|
||||
'icon' => 'pencil-square-o'
|
||||
'icon' => 'layout-text-sidebar'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -321,6 +321,7 @@ function change_channel($change_channel) {
|
||||
function permissions_sql($owner_id, $remote_observer = null, $table = '', $token = EMPTY_STR) {
|
||||
|
||||
$local_channel = local_channel();
|
||||
$observer = $remote_observer ?? get_observer_hash();
|
||||
|
||||
/**
|
||||
* Construct permissions
|
||||
@@ -344,15 +345,22 @@ function permissions_sql($owner_id, $remote_observer = null, $table = '', $token
|
||||
if (($local_channel) && ($local_channel == $owner_id)) {
|
||||
return EMPTY_STR;
|
||||
}
|
||||
/**
|
||||
* Authenticated visitor.
|
||||
*/
|
||||
|
||||
else {
|
||||
|
||||
$observer = ((!is_null($remote_observer)) ? $remote_observer : get_observer_hash());
|
||||
/*
|
||||
* OCAP token access
|
||||
*/
|
||||
|
||||
if ($observer) {
|
||||
if ($token) {
|
||||
$sql = " AND ( {$table}allow_cid like '" . protect_sprintf('%<token:' . $token . '>%') .
|
||||
"' OR ( {$table}allow_cid = '' AND {$table}allow_gid = '' AND {$table}deny_cid = '' AND {$table}deny_gid = '' ) )";
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticated visitor.
|
||||
*/
|
||||
|
||||
elseif ($observer) {
|
||||
|
||||
$sec = get_security_ids($owner_id, $observer);
|
||||
|
||||
@@ -400,16 +408,6 @@ function permissions_sql($owner_id, $remote_observer = null, $table = '', $token
|
||||
dbesc($gs)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* OCAP token access
|
||||
*/
|
||||
|
||||
elseif ($token) {
|
||||
$sql = " AND ( {$table}allow_cid like '" . protect_sprintf('%<token:' . $token . '>%') .
|
||||
"' OR ( {$table}allow_cid = '' AND {$table}allow_gid = '' AND {$table}deny_cid = '' AND {$table}deny_gid = '' ) )";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $sql;
|
||||
@@ -497,7 +495,7 @@ function item_permissions_sql($owner_id, $remote_observer = null) {
|
||||
" AND ( author_xchan = '%s' OR owner_xchan = '%s' OR
|
||||
(( NOT (deny_cid $regexop '%s' OR deny_gid $regexop '%s')
|
||||
AND ( allow_cid $regexop '%s' OR allow_gid $regexop '%s' OR ( allow_cid = '' AND allow_gid = '' AND item_private = 0 ))
|
||||
)))
|
||||
)) OR ( item_private = 1 $scope ))
|
||||
",
|
||||
dbesc($observer),
|
||||
dbesc($observer),
|
||||
@@ -708,56 +706,61 @@ function get_security_ids($channel_id, $ob_hash) {
|
||||
'allow_gid' => []
|
||||
];
|
||||
|
||||
if ($channel_id) {
|
||||
$ch = q("select channel_hash from channel where channel_id = %d",
|
||||
intval($channel_id)
|
||||
);
|
||||
if ($ch) {
|
||||
$ret['channel_id'][] = $ch[0]['channel_hash'];
|
||||
}
|
||||
$x = q("select xchan_hash from xchan where xchan_hash = '%s'",
|
||||
dbesc($ob_hash)
|
||||
);
|
||||
|
||||
if (!$x) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$ret['allow_cid'][] = $x[0]['xchan_hash'];
|
||||
|
||||
if (!$channel_id) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$ch = q("select channel_hash from channel where channel_id = %d",
|
||||
intval($channel_id)
|
||||
);
|
||||
if ($ch) {
|
||||
$ret['channel_id'][] = $ch[0]['channel_hash'];
|
||||
}
|
||||
|
||||
$groups = [];
|
||||
|
||||
$x = q("select * from xchan where xchan_hash = '%s'",
|
||||
dbesc($ob_hash)
|
||||
// private profiles are treated as a virtual group
|
||||
|
||||
$r = q("SELECT abook_profile from abook where abook_channel = %d and abook_xchan = '%s' and abook_profile != ''",
|
||||
intval($channel_id),
|
||||
dbesc(protect_sprintf($x[0]['xchan_hash']))
|
||||
);
|
||||
|
||||
if ($x) {
|
||||
|
||||
// include xchans for all zot-like networks
|
||||
|
||||
$xchans = q("select xchan_hash from xchan where xchan_hash = '%s' OR ( xchan_guid = '%s' AND xchan_pubkey = '%s' ) ",
|
||||
dbesc($ob_hash),
|
||||
dbesc($x[0]['xchan_guid']),
|
||||
dbesc($x[0]['xchan_pubkey'])
|
||||
);
|
||||
|
||||
if ($xchans) {
|
||||
$ret['allow_cid'] = ids_to_array($xchans, 'xchan_hash');
|
||||
$hashes = ids_to_querystr($xchans, 'xchan_hash', true);
|
||||
|
||||
// private profiles are treated as a virtual group
|
||||
|
||||
$r = q("SELECT abook_profile from abook where abook_xchan in ( " . protect_sprintf($hashes) . " ) and abook_profile != '' ");
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
$groups[] = 'vp.' . $rv['abook_profile'];
|
||||
}
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
if (!in_array('vp.' . $rv['abook_profile'], $groups)) {
|
||||
$groups[] = 'vp.' . $rv['abook_profile'];
|
||||
}
|
||||
|
||||
// physical groups this identity is a member of
|
||||
|
||||
$r = q("SELECT hash FROM pgrp left join pgrp_member on pgrp.id = pgrp_member.gid WHERE xchan in ( " . protect_sprintf($hashes) . " ) ");
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
$groups[] = $rv['hash'];
|
||||
}
|
||||
}
|
||||
$ret['allow_gid'] = $groups;
|
||||
}
|
||||
}
|
||||
|
||||
// physical groups this identity is a member of
|
||||
|
||||
$r = q("SELECT hash FROM pgrp left join pgrp_member on pgrp.id = pgrp_member.gid WHERE pgrp.uid = %d and pgrp_member.xchan = '%s'",
|
||||
intval($channel_id),
|
||||
dbesc(protect_sprintf($x[0]['xchan_hash']))
|
||||
);
|
||||
|
||||
if ($r) {
|
||||
foreach ($r as $rv) {
|
||||
if (!in_array($rv['hash'], $groups)) {
|
||||
$groups[] = $rv['hash'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ret['allow_gid'] = $groups;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1652,7 +1652,7 @@ function format_hashtags(&$item) {
|
||||
if($s)
|
||||
$s .= ' ';
|
||||
|
||||
$s .= '<span class="badge rounded-pill bg-info"><i class="fa fa-hashtag"></i> <a class="text-white" href="' . zid($t['url']) . '" >' . $term . '</a></span>';
|
||||
$s .= '<span class="badge rounded-pill bg-info"><i class="bi bi-hash"></i> <a class="text-white" href="' . zid($t['url']) . '" >' . $term . '</a></span>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1675,7 +1675,7 @@ function format_mentions(&$item) {
|
||||
continue;
|
||||
if($s)
|
||||
$s .= ' ';
|
||||
$s .= '<span class="badge rounded-pill bg-success"><i class="fa fa-at"></i> <a class="text-white" href="' . zid($t['url']) . '" >' . $term . '</a></span>';
|
||||
$s .= '<span class="badge rounded-pill bg-success"><i class="bi bi-at"></i> <a class="text-white" href="' . zid($t['url']) . '" >' . $term . '</a></span>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3203,53 +3203,53 @@ function linkify_tags(&$body, $uid, $in_network = true) {
|
||||
function getIconFromType($type) {
|
||||
$iconMap = array(
|
||||
//Folder
|
||||
'Collection' => 'fa-folder-o',
|
||||
'multipart/mixed' => 'fa-folder-o', //dirs in attach use this mime type
|
||||
'Collection' => 'bi-folder',
|
||||
'multipart/mixed' => 'bi-folder', //dirs in attach use this mime type
|
||||
//Common file
|
||||
'application/octet-stream' => 'fa-file-o',
|
||||
'application/octet-stream' => 'bi-file-earmark',
|
||||
//Text
|
||||
'text/plain' => 'fa-file-text-o',
|
||||
'text/markdown' => 'fa-file-text-o',
|
||||
'text/bbcode' => 'fa-file-text-o',
|
||||
'text/html' => 'fa-file-text-o',
|
||||
'application/msword' => 'fa-file-word-o',
|
||||
'application/pdf' => 'fa-file-pdf-o',
|
||||
'application/vnd.oasis.opendocument.text' => 'fa-file-word-o',
|
||||
'application/epub+zip' => 'fa-book',
|
||||
'text/plain' => 'bi-earmark-text',
|
||||
'text/markdown' => 'bi-filetype-md',
|
||||
'text/bbcode' => 'bi-file-earmark-text',
|
||||
'text/html' => 'bi-filetype-html',
|
||||
'application/msword' => 'bi-file-earmark-word',
|
||||
'application/pdf' => 'bi-file-earmark-pdf',
|
||||
'application/vnd.oasis.opendocument.text' => 'bifile--earmark-text',
|
||||
'application/epub+zip' => 'bi-file-earmark-text',
|
||||
//Spreadsheet
|
||||
'application/vnd.oasis.opendocument.spreadsheet' => 'fa-file-excel-o',
|
||||
'application/vnd.ms-excel' => 'fa-file-excel-o',
|
||||
'application/vnd.oasis.opendocument.spreadsheet' => 'bi-file-earmark-spreadsheet',
|
||||
'application/vnd.ms-excel' => 'bi-file-earmark-spreadsheet',
|
||||
//Image
|
||||
'image/jpeg' => 'fa-picture-o',
|
||||
'image/png' => 'fa-picture-o',
|
||||
'image/gif' => 'fa-picture-o',
|
||||
'image/webp' => 'fa-picture-o',
|
||||
'image/svg+xml' => 'fa-picture-o',
|
||||
'image/jpeg' => 'bi-file-earmark-image',
|
||||
'image/png' => 'bi-file-earmark-image',
|
||||
'image/gif' => 'bi-file-earmark-image',
|
||||
'image/webp' => 'bi-file-earmark-image',
|
||||
'image/svg+xml' => 'bi-filetype-svg',
|
||||
//Archive
|
||||
'application/zip' => 'fa-file-archive-o',
|
||||
'application/x-rar-compressed' => 'fa-file-archive-o',
|
||||
'application/zip' => 'bi-file-earmark-zip',
|
||||
'application/x-rar-compressed' => 'bi-file-earmark-zip',
|
||||
//Audio
|
||||
'audio/mpeg' => 'fa-file-audio-o',
|
||||
'audio/wav' => 'fa-file-audio-o',
|
||||
'application/ogg' => 'fa-file-audio-o',
|
||||
'audio/ogg' => 'fa-file-audio-o',
|
||||
'audio/webm' => 'fa-file-audio-o',
|
||||
'audio/mp4' => 'fa-file-audio-o',
|
||||
'audio/mpeg' => 'bi-file-earmark-music',
|
||||
'audio/wav' => 'bi-file-earmark-music',
|
||||
'application/ogg' => 'bi-file-earmark-music',
|
||||
'audio/ogg' => 'bi-file-earmark-music',
|
||||
'audio/webm' => 'bi-file-earmark-music',
|
||||
'audio/mp4' => 'bi-file-earmark-music',
|
||||
//Video
|
||||
'video/quicktime' => 'fa-file-video-o',
|
||||
'video/webm' => 'fa-file-video-o',
|
||||
'video/mp4' => 'fa-file-video-o',
|
||||
'video/x-matroska' => 'fa-file-video-o'
|
||||
'video/quicktime' => 'bi-file-earmark-play',
|
||||
'video/webm' => 'bi-file-earmark-play',
|
||||
'video/mp4' => 'bi-file-earmark-play',
|
||||
'video/x-matroska' => 'bi-file-earmark-play'
|
||||
);
|
||||
|
||||
$catMap = [
|
||||
'application' => 'fa-file-code-o',
|
||||
'multipart' => 'fa-folder',
|
||||
'audio' => 'fa-file-audio-o',
|
||||
'video' => 'fa-file-video-o',
|
||||
'text' => 'fa-file-text-o',
|
||||
'image' => 'fa=file-picture-o',
|
||||
'message' => 'fa-file-text-o'
|
||||
'application' => 'bi-file-earmark',
|
||||
'multipart' => 'bi-folder',
|
||||
'audio' => 'bi-file-earmark-music',
|
||||
'video' => 'bi-file-earmark-play',
|
||||
'text' => 'bi-file-earmark-text',
|
||||
'image' => 'bi-file-earmark-image',
|
||||
'message' => 'bi-file-earmark-text'
|
||||
];
|
||||
|
||||
|
||||
@@ -3266,7 +3266,7 @@ function getIconFromType($type) {
|
||||
}
|
||||
|
||||
if(! $iconFromType) {
|
||||
$iconFromType = 'fa-file-o';
|
||||
$iconFromType = 'bi-file-earmark';
|
||||
}
|
||||
|
||||
|
||||
@@ -3755,12 +3755,9 @@ function cleanup_bbcode($body) {
|
||||
$body = preg_replace_callback('/\[img(.*?)\[\/(img)\]/ism','\red_escape_codeblock',$body);
|
||||
$body = preg_replace_callback('/\[zmg(.*?)\[\/(zmg)\]/ism','\red_escape_codeblock',$body);
|
||||
|
||||
$body = preg_replace_callback("/([^\]\='".'"'."\;\/\{]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\\
|
||||
+\,\(\)]+)/ismu", '\nakedoembed', $body);
|
||||
|
||||
$body = preg_replace_callback("/([^\]\='".'"'."\;\/\{]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\\
|
||||
+\,\(\)]+)/ismu", '\red_zrl_callback', $body);
|
||||
$body = preg_replace_callback("/([^\]\='".'"'."\;\/\{]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\\+\,\(\)]+)/ismu", '\nakedoembed', $body);
|
||||
|
||||
$body = preg_replace_callback("/([^\]\='".'"'."\;\/\{]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\\+\,\(\)]+)/ismu", '\red_zrl_callback', $body);
|
||||
|
||||
$body = preg_replace_callback('/\[\$b64code(.*?)\[\/(code)\]/ism','\red_unescape_codeblock',$body);
|
||||
$body = preg_replace_callback('/\[\$b64summary(.*?)\[\/(summary)\]/ism','\red_unescape_codeblock',$body);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
12
library/fork-awesome/css/fork-awesome.min.css
vendored
12
library/fork-awesome/css/fork-awesome.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,446 +0,0 @@
|
||||
/*!
|
||||
Fork Awesome 1.2.0
|
||||
License - https://forkaweso.me/Fork-Awesome/license
|
||||
|
||||
Copyright 2018 Dave Gandy & Fork Awesome
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
.fas,
|
||||
.fab,
|
||||
.far {
|
||||
display: inline-block;
|
||||
font: normal normal normal 14px/1 ForkAwesome;
|
||||
font-size: inherit;
|
||||
text-rendering: auto;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
.fas.fa-chart-area:before {
|
||||
content: "\f1fe";
|
||||
}
|
||||
.fas.fa-arrows-alt:before {
|
||||
content: "\f047";
|
||||
}
|
||||
.fas.fa-expand-arrows-alt:before {
|
||||
content: "\f0b2";
|
||||
}
|
||||
.fas.fa-arrows-alt-h:before {
|
||||
content: "\f07e";
|
||||
}
|
||||
.fas.fa-arrows-alt-v:before {
|
||||
content: "\f07d";
|
||||
}
|
||||
.fas.fa-calendar-alt:before {
|
||||
content: "\f073";
|
||||
}
|
||||
.fas.fa-circle-notch:before {
|
||||
content: "\f1ce";
|
||||
}
|
||||
.fas.fa-cloud-download-alt:before {
|
||||
content: "\f0ed";
|
||||
}
|
||||
.fas.fa-cloud-upload-alt:before {
|
||||
content: "\f0ee";
|
||||
}
|
||||
.fas.fa-credit-card:before {
|
||||
content: "\f283";
|
||||
}
|
||||
.fas.fa-dollar-sign:before {
|
||||
content: "\f155";
|
||||
}
|
||||
.fas.fa-euro-sign:before {
|
||||
content: "\f153";
|
||||
}
|
||||
.fas.fa-exchange-alt:before {
|
||||
content: "\f0ec";
|
||||
}
|
||||
.fas.fa-external-link-alt:before {
|
||||
content: "\f08e";
|
||||
}
|
||||
.fas.fa-external-link-square-alt:before {
|
||||
content: "\f14c";
|
||||
}
|
||||
.fas.fa-eye-dropper:before {
|
||||
content: "\f1fb";
|
||||
}
|
||||
.fas.fa-pound-sign:before {
|
||||
content: "\f154";
|
||||
}
|
||||
.fas.fa-glass-martini:before {
|
||||
content: "\f000";
|
||||
}
|
||||
.fas.fa-shekel-sign:before {
|
||||
content: "\f20b";
|
||||
}
|
||||
.fas.fa-rupee-sign:before {
|
||||
content: "\f156";
|
||||
}
|
||||
.fas.fa-won-sign:before {
|
||||
content: "\f159";
|
||||
}
|
||||
.fas.fa-level-down-alt:before {
|
||||
content: "\f149";
|
||||
}
|
||||
.fas.fa-level-up-alt:before {
|
||||
content: "\f148";
|
||||
}
|
||||
.fas.fa-chart-line:before {
|
||||
content: "\f201";
|
||||
}
|
||||
.fas.fa-long-arrow-alt-down:before {
|
||||
content: "\f175";
|
||||
}
|
||||
.fas.fa-long-arrow-alt-left:before {
|
||||
content: "\f177";
|
||||
}
|
||||
.fas.fa-long-arrow-alt-right:before {
|
||||
content: "\f178";
|
||||
}
|
||||
.fas.fa-long-arrow-alt-up:before {
|
||||
content: "\f176";
|
||||
}
|
||||
.fas.fa-map-marker-alt:before {
|
||||
content: "\f041";
|
||||
}
|
||||
.fas.fa-mobile-alt:before {
|
||||
content: "\f10b";
|
||||
}
|
||||
.fas.fa-pencil-alt:before {
|
||||
content: "\f040";
|
||||
}
|
||||
.fas.fa-pen-square:before {
|
||||
content: "\f14b";
|
||||
}
|
||||
.fas.fa-chart-pie:before {
|
||||
content: "\f200";
|
||||
}
|
||||
.fas.fa-yen-sign:before {
|
||||
content: "\f157";
|
||||
}
|
||||
.fas.fa-ruble-sign:before {
|
||||
content: "\f158";
|
||||
}
|
||||
.fas.fa-shield-alt:before {
|
||||
content: "\f132";
|
||||
}
|
||||
.fas.fa-sign-in-alt:before {
|
||||
content: "\f090";
|
||||
}
|
||||
.fas.fa-sign-out-alt:before {
|
||||
content: "\f08b";
|
||||
}
|
||||
.fas.fa-sliders-h:before {
|
||||
content: "\f1de";
|
||||
}
|
||||
.fas.fa-tablet-alt:before {
|
||||
content: "\f10a";
|
||||
}
|
||||
.fas.fa-tachometer-alt:before {
|
||||
content: "\f0e4";
|
||||
}
|
||||
.fas.fa-thumbtack:before {
|
||||
content: "\f08d";
|
||||
}
|
||||
.fas.fa-ticket-alt:before {
|
||||
content: "\f145";
|
||||
}
|
||||
.fas.fa-trash-alt:before {
|
||||
content: "\f1f8";
|
||||
}
|
||||
.fas.fa-lira-sign:before {
|
||||
content: "\f195";
|
||||
}
|
||||
.fab.fa-linkedin-in:before {
|
||||
content: "\fe01";
|
||||
}
|
||||
.fab.fa-linkedin:before {
|
||||
content: "\f08c";
|
||||
}
|
||||
.far.fa-address-book:before {
|
||||
content: "\f2ba";
|
||||
}
|
||||
.far.fa-address-card:before {
|
||||
content: "\f2bc";
|
||||
}
|
||||
.far.fa-arrow-alt-circle-down:before {
|
||||
content: "\f01a";
|
||||
}
|
||||
.far.fa-arrow-alt-circle-left:before {
|
||||
content: "\f190";
|
||||
}
|
||||
.far.fa-arrow-alt-circle-right:before {
|
||||
content: "\f18e";
|
||||
}
|
||||
.far.fa-arrow-alt-circle-up:before {
|
||||
content: "\f01b";
|
||||
}
|
||||
.far.fa-bell:before {
|
||||
content: "\f0f3";
|
||||
}
|
||||
.far.fa-bell-slash:before {
|
||||
content: "\f1f7";
|
||||
}
|
||||
.far.fa-bookmark:before {
|
||||
content: "\f097";
|
||||
}
|
||||
.far.fa-building:before {
|
||||
content: "\f0f7";
|
||||
}
|
||||
.far.fa-calendar-check:before {
|
||||
content: "\f274";
|
||||
}
|
||||
.far.fa-calendar-minus:before {
|
||||
content: "\f272";
|
||||
}
|
||||
.far.fa-calendar:before {
|
||||
content: "\f133";
|
||||
}
|
||||
.far.fa-calendar-plus:before {
|
||||
content: "\f271";
|
||||
}
|
||||
.far.fa-calendar-times:before {
|
||||
content: "\f273";
|
||||
}
|
||||
.far.fa-caret-square-down:before {
|
||||
content: "\f150";
|
||||
}
|
||||
.far.fa-caret-square-left:before {
|
||||
content: "\f191";
|
||||
}
|
||||
.far.fa-caret-square-right:before {
|
||||
content: "\f152";
|
||||
}
|
||||
.far.fa-caret-square-up:before {
|
||||
content: "\f151";
|
||||
}
|
||||
.far.fa-check-circle:before {
|
||||
content: "\f05d";
|
||||
}
|
||||
.far.fa-check-square:before {
|
||||
content: "\f046";
|
||||
}
|
||||
.far.fa-circle:before {
|
||||
content: "\f10c";
|
||||
}
|
||||
.far.fa-clock:before {
|
||||
content: "\f017";
|
||||
}
|
||||
.far.fa-comment:before {
|
||||
content: "\f0e5";
|
||||
}
|
||||
.far.fa-comment-dots:before {
|
||||
content: "\f27b";
|
||||
}
|
||||
.far.fa-comments:before {
|
||||
content: "\f0e6";
|
||||
}
|
||||
.far.fa-dot-circle:before {
|
||||
content: "\f192";
|
||||
}
|
||||
.far.fa-id-card:before {
|
||||
content: "\f2c3";
|
||||
}
|
||||
.far.fa-envelope:before {
|
||||
content: "\f003";
|
||||
}
|
||||
.far.fa-envelope-open:before {
|
||||
content: "\f2b7";
|
||||
}
|
||||
.far.fa-file-archive:before {
|
||||
content: "\f1c6";
|
||||
}
|
||||
.far.fa-file-audio:before {
|
||||
content: "\f1c7";
|
||||
}
|
||||
.far.fa-file-code:before {
|
||||
content: "\f1c9";
|
||||
}
|
||||
.far.fa-file-excel:before {
|
||||
content: "\f1c3";
|
||||
}
|
||||
.far.fa-file-image:before {
|
||||
content: "\f1c5";
|
||||
}
|
||||
.far.fa-file-video:before {
|
||||
content: "\f1c8";
|
||||
}
|
||||
.far.fa-copy:before,
|
||||
.far.fa-file:before {
|
||||
content: "\f016";
|
||||
}
|
||||
.far.fa-file-pdf:before {
|
||||
content: "\f1c1";
|
||||
}
|
||||
.far.fa-file-powerpoint:before {
|
||||
content: "\f1c4";
|
||||
}
|
||||
.far.fa-file-alt:before {
|
||||
content: "\f0f6";
|
||||
}
|
||||
.far.fa-file-word:before {
|
||||
content: "\f1c2";
|
||||
}
|
||||
.far.fa-flag:before {
|
||||
content: "\f11d";
|
||||
}
|
||||
.far.fa-save:before {
|
||||
content: "\f0c7";
|
||||
}
|
||||
.far.fa-folder:before {
|
||||
content: "\f114";
|
||||
}
|
||||
.far.fa-folder-open:before {
|
||||
content: "\f115";
|
||||
}
|
||||
.far.fa-frown:before {
|
||||
content: "\f119";
|
||||
}
|
||||
.far.fa-futbol:before {
|
||||
content: "\f1e3";
|
||||
}
|
||||
.far.fa-hand-rock:before {
|
||||
content: "\f255";
|
||||
}
|
||||
.far.fa-hand-lizard:before {
|
||||
content: "\f258";
|
||||
}
|
||||
.far.fa-hand-point-down:before {
|
||||
content: "\f0a7";
|
||||
}
|
||||
.far.fa-hand-point-left:before {
|
||||
content: "\f0a5";
|
||||
}
|
||||
.far.fa-hand-point-right:before {
|
||||
content: "\f0a4";
|
||||
}
|
||||
.far.fa-hand-point-up:before {
|
||||
content: "\f0a6";
|
||||
}
|
||||
.far.fa-hand-paper:before {
|
||||
content: "\256";
|
||||
}
|
||||
.far.fa-hand-pointer:before {
|
||||
content: "\f25a";
|
||||
}
|
||||
.far.fa-hand-scissors:before {
|
||||
content: "\f257";
|
||||
}
|
||||
.far.fa-hand-spock:before {
|
||||
content: "\f259";
|
||||
}
|
||||
.far.fa-handshake:before {
|
||||
content: "\f2b5";
|
||||
}
|
||||
.far.fa-hdd:before {
|
||||
content: "\f0a0";
|
||||
}
|
||||
.far.fa-heart:before {
|
||||
content: "\f08a";
|
||||
}
|
||||
.far.fa-hospital:before {
|
||||
content: "\f0f8";
|
||||
}
|
||||
.far.fa-hourglass:before {
|
||||
content: "\f250";
|
||||
}
|
||||
.far.fa-id-card:before {
|
||||
content: "\f2c3";
|
||||
}
|
||||
.far.fa-keyboard:before {
|
||||
content: "\f11c";
|
||||
}
|
||||
.far.fa-lemon:before {
|
||||
content: "\f094";
|
||||
}
|
||||
.far.fa-lightbulb:before {
|
||||
content: "\f0eb";
|
||||
}
|
||||
.far.fa-meh:before {
|
||||
content: "\f11a";
|
||||
}
|
||||
.far.fa-minus-square:before {
|
||||
content: "\f147";
|
||||
}
|
||||
.far.fa-money-bill-alt:before {
|
||||
content: "\f0d6";
|
||||
}
|
||||
.far.fa-moon:before {
|
||||
content: "\f186";
|
||||
}
|
||||
.far.fa-newspaper:before {
|
||||
content: "\f1ea";
|
||||
}
|
||||
.far.fa-paper-plane:before {
|
||||
content: "\f1d9";
|
||||
}
|
||||
.far.fa-pause-circle:before {
|
||||
content: "\f28c";
|
||||
}
|
||||
.far.fa-edit:before {
|
||||
content: "\f044";
|
||||
}
|
||||
.far.fa-image:before {
|
||||
content: "\f03e";
|
||||
}
|
||||
.far.fa-play-circle:before {
|
||||
content: "\f01d";
|
||||
}
|
||||
.far.fa-plus-square:before {
|
||||
content: "\f196";
|
||||
}
|
||||
.far.fa-question-circle:before {
|
||||
content: "\f92c";
|
||||
}
|
||||
.far.fa-share-square:before {
|
||||
content: "\f045";
|
||||
}
|
||||
.far.fa-smile:before {
|
||||
content: "\f118";
|
||||
}
|
||||
.far.fa-snowflake:before {
|
||||
content: "\f2dc";
|
||||
}
|
||||
.far.fa-futbol:before {
|
||||
content: "\f1e3";
|
||||
}
|
||||
.far.fa-star-half:before {
|
||||
content: "\f089";
|
||||
}
|
||||
.far.fa-star:before {
|
||||
content: "\f006";
|
||||
}
|
||||
.far.fa-sticky-note:before {
|
||||
content: "\f24a";
|
||||
}
|
||||
.far.fa-stop-circle:before {
|
||||
content: "\f28e";
|
||||
}
|
||||
.far.fa-sun:before {
|
||||
content: "\f185";
|
||||
}
|
||||
.far.fa-thumbs-down:before {
|
||||
content: "\f088";
|
||||
}
|
||||
.far.fa-thumbs-up:before {
|
||||
content: "\f087";
|
||||
}
|
||||
.far.fa-times-circle:before {
|
||||
content: "\f05c";
|
||||
}
|
||||
.far.fa-window-close:before {
|
||||
content: "\f2d4";
|
||||
}
|
||||
.far.fa-trash-alt:before {
|
||||
content: "\f014";
|
||||
}
|
||||
.far.fa-user-circle:before {
|
||||
content: "\f2be";
|
||||
}
|
||||
.far.fa-user:before {
|
||||
content: "\f2c0";
|
||||
}
|
||||
12
library/fork-awesome/css/v5-compat.min.css
vendored
12
library/fork-awesome/css/v5-compat.min.css
vendored
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":["v5-compat.css"],"names":[],"mappings":";;;;;;;;;;;AAaA,KACA,KAFA,KAGE,QAAA,aACA,KAAA,OAAA,OAAA,OAAA,KAAA,EAAA,YACA,UAAA,QACA,eAAA,KACA,uBAAA,YACA,wBAAA,UAEgB,0BAChB,QAAA,QAEgB,0BAChB,QAAA,QAEuB,iCACvB,QAAA,QAEkB,4BAClB,QAAA,QAEkB,4BAClB,QAAA,QAEkB,4BAClB,QAAA,QAEkB,4BAClB,QAAA,QAEwB,kCACxB,QAAA,QAEsB,gCACtB,QAAA,QAEiB,2BACjB,QAAA,QAEiB,2BACjB,QAAA,QAEe,yBACf,QAAA,QAEkB,4BAClB,QAAA,QAEuB,iCACvB,QAAA,QAE8B,wCAC9B,QAAA,QAEiB,2BACjB,QAAA,QAEgB,0BAChB,QAAA,QAEmB,6BACnB,QAAA,QAEiB,2BACjB,QAAA,QAEgB,0BAChB,QAAA,QAEc,wBACd,QAAA,QAEoB,8BACpB,QAAA,QAEkB,4BAClB,QAAA,QAEgB,0BAChB,QAAA,QAEyB,mCACzB,QAAA,QAEyB,mCACzB,QAAA,QAE0B,oCAC1B,QAAA,QAEuB,iCACvB,QAAA,QAEoB,8BACpB,QAAA,QAEgB,0BAChB,QAAA,QAEgB,0BAChB,QAAA,QAEgB,0BAChB,QAAA,QAEe,yBACf,QAAA,QAEc,wBACd,QAAA,QAEgB,0BAChB,QAAA,QAEgB,0BAChB,QAAA,QAEiB,2BACjB,QAAA,QAEkB,4BAClB,QAAA,QAEe,yBACf,QAAA,QAEgB,0BAChB,QAAA,QAEoB,8BACpB,QAAA,QAEe,yBACf,QAAA,QAEgB,0BAChB,QAAA,QAEe,yBACf,QAAA,QAEe,yBACf,QAAA,QAEiB,2BACjB,QAAA,QAEc,wBACd,QAAA,QAEkB,4BAClB,QAAA,QAEkB,4BAClB,QAAA,QAE2B,qCAC3B,QAAA,QAE2B,qCAC3B,QAAA,QAE4B,sCAC5B,QAAA,QAEyB,mCACzB,QAAA,QAEU,oBACV,QAAA,QAEgB,0BAChB,QAAA,QAEc,wBACd,QAAA,QAEc,wBACd,QAAA,QAEoB,8BACpB,QAAA,QAEoB,8BACpB,QAAA,QAEc,wBACd,QAAA,QAEmB,6BACnB,QAAA,QAEoB,8BACpB,QAAA,QAEuB,iCACvB,QAAA,QAEuB,iCACvB,QAAA,QAEwB,kCACxB,QAAA,QAEqB,+BACrB,QAAA,QAEkB,4BAClB,QAAA,QAEkB,4BAClB,QAAA,QAEY,sBACZ,QAAA,QAEW,qBACX,QAAA,QAEa,uBACb,QAAA,QAEkB,4BAClB,QAAA,QAEc,wBACd,QAAA,QAEgB,0BAChB,QAAA,QAEa,uBACb,QAAA,QAEc,wBACd,QAAA,QAEmB,6BACnB,QAAA,QAEkB,4BAClB,QAAA,QAEgB,0BAChB,QAAA,QAEe,yBACf,QAAA,QAEgB,0BAChB,QAAA,QAEgB,0BAChB,QAAA,QAEgB,0BAChB,QAAA,QAEU,oBACA,oBACV,QAAA,QAEc,wBACd,QAAA,QAEqB,+BACrB,QAAA,QAEc,wBACd,QAAA,QAEe,yBACf,QAAA,QAEU,oBACV,QAAA,QAEU,oBACV,QAAA,QAEY,sBACZ,QAAA,QAEiB,2BACjB,QAAA,QAEW,qBACX,QAAA,QAEY,sBACZ,QAAA,QAEe,yBACf,QAAA,QAEiB,2BACjB,QAAA,QAEqB,+BACrB,QAAA,QAEqB,+BACrB,QAAA,QAEsB,gCACtB,QAAA,QAEmB,6BACnB,QAAA,QAEgB,0BAChB,QAAA,OAEkB,4BAClB,QAAA,QAEmB,6BACnB,QAAA,QAEgB,0BAChB,QAAA,QAEe,yBACf,QAAA,QAES,mBACT,QAAA,QAEW,qBACX,QAAA,QAEc,wBACd,QAAA,QAEe,yBACf,QAAA,QAEa,uBACb,QAAA,QAEc,wBACd,QAAA,QAEW,qBACX,QAAA,QAEe,yBACf,QAAA,QAES,mBACT,QAAA,QAEkB,4BAClB,QAAA,QAEoB,8BACpB,QAAA,QAEU,oBACV,QAAA,QAEe,yBACf,QAAA,QAEiB,2BACjB,QAAA,QAEkB,4BAClB,QAAA,QAEU,oBACV,QAAA,QAEW,qBACX,QAAA,QAEiB,2BACjB,QAAA,QAEiB,2BACjB,QAAA,QAEqB,+BACrB,QAAA,QAEkB,4BAClB,QAAA,QAEW,qBACX,QAAA,QAEe,yBACf,QAAA,QAEY,sBACZ,QAAA,QAEe,yBACf,QAAA,QAEU,oBACV,QAAA,QAEiB,2BACjB,QAAA,QAEiB,2BACjB,QAAA,QAES,mBACT,QAAA,QAEiB,2BACjB,QAAA,QAEe,yBACf,QAAA,QAEkB,4BAClB,QAAA,QAEkB,4BAClB,QAAA,QAEe,yBACf,QAAA,QAEiB,2BACjB,QAAA,QAEU,oBACV,QAAA"}
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 547 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
214
tests/unit/Module/AdminAccountEditTest.php
Normal file
214
tests/unit/Module/AdminAccountEditTest.php
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
/* Tests for Account_edit module
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Hubzilla Community
|
||||
* SPDX-FileContributor: Harald Eilertsen
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Tests\Unit\Module;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use PHPUnit\Framework\Attributes\{Before, After};
|
||||
use Zotlabs\Model\Account;
|
||||
|
||||
class AdminAccountEditTest extends TestCase {
|
||||
|
||||
#[Before]
|
||||
public function setup_mocks(): void {
|
||||
/*
|
||||
* As we're testing pages that should only be reachable by the
|
||||
* site admin, it makes no sense to have it return anything else
|
||||
* than true.
|
||||
*/
|
||||
$this->stub_is_site_admin =
|
||||
$this->getFunctionMock('Zotlabs\Module', 'is_site_admin')
|
||||
->expects($this->once())
|
||||
->willReturn(true);
|
||||
|
||||
$this->info = [];
|
||||
$this->stub_info =
|
||||
$this->getFunctionMock('Zotlabs\Module\Admin', 'info')
|
||||
->expects($this->any())
|
||||
->willReturnCallback(function (string $arg) {
|
||||
$this->info[] = $arg;
|
||||
});
|
||||
|
||||
$this->notice = [];
|
||||
$this->stub_notice =
|
||||
$this->getFunctionMock('Zotlabs\Module\Admin', 'notice')
|
||||
->expects($this->any())
|
||||
->willReturnCallback(function (string $arg) {
|
||||
$this->notice[] = $arg;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
#[After]
|
||||
public function tear_down_mocks(): void {
|
||||
$this->stub_is_site_admin = null;
|
||||
$this->stub_info = null;
|
||||
$this->stub_notice = null;
|
||||
$this->stub_check_security = null;
|
||||
$this->stub_get_form_security_token = null;
|
||||
}
|
||||
|
||||
public function test_rendering_admin_account_edit_page(): void {
|
||||
$this->stub_get_form_security_token =
|
||||
$this->getFunctionMock('Zotlabs\Module\Admin', 'get_form_security_token')
|
||||
->expects($this->once())
|
||||
->willReturn('the-csrf-token');
|
||||
|
||||
$account = $this->fixtures['account'][0];
|
||||
|
||||
$this->get("admin/account_edit/{$account['account_id']}");
|
||||
|
||||
$this->assertPageContains("<form action=\"admin/account_edit/{$account['account_id']}\" method=\"post\"");
|
||||
$this->assertPageContains($account['account_email']);
|
||||
|
||||
// Check that we generate a CSRF token for the form
|
||||
$this->assertPageContains("<input type=\"hidden\" name=\"security\" value=\"the-csrf-token\"");
|
||||
}
|
||||
|
||||
public function test_rendering_admin_account_edit_page_fails_if_id_is_not_found(): void {
|
||||
$this->get("admin/account_edit/666");
|
||||
|
||||
$this->assertEquals('', \App::$page['content']);
|
||||
}
|
||||
|
||||
public function test_rendering_admin_account_edit_page_fails_if_id_is_not_numeric(): void {
|
||||
$this->get("admin/account_edit/66invalid");
|
||||
|
||||
$this->assertEquals('', \App::$page['content']);
|
||||
}
|
||||
|
||||
public function test_post_empty_form_does_not_modify_account(): void {
|
||||
$this->stub_goaway();
|
||||
$this->stub_check_form_security(true);
|
||||
|
||||
$account = get_account_by_id($this->fixtures['account'][0]['account_id']);
|
||||
|
||||
try {
|
||||
$this->post(
|
||||
"admin/account_edit/{$account['account_id']}",
|
||||
[],
|
||||
[
|
||||
'aid' => $account['account_id'],
|
||||
'pass1' => '',
|
||||
'pass2' => '',
|
||||
'service_class' => $account['account_service_class'],
|
||||
'account_language' => $account['account_language'],
|
||||
'security' => 'The security token',
|
||||
]
|
||||
);
|
||||
} catch (RedirectException $ex) {
|
||||
$this->assertEquals(z_root() . '/admin/accounts', $ex->getMessage());
|
||||
}
|
||||
|
||||
$reloaded = get_account_by_id($account['account_id']);
|
||||
|
||||
$this->assertEquals($account, $reloaded);
|
||||
|
||||
// Not sure if this is expected behaviour, but this is how it is today.
|
||||
$this->assertContains('Account settings updated.' . EOL, $this->info);
|
||||
}
|
||||
|
||||
public function test_post_form_changes_account(): void {
|
||||
$this->stub_goaway();
|
||||
$this->stub_check_form_security(true);
|
||||
|
||||
// clone account from fixture, to ensure it's not replaced with
|
||||
// the reloaded one below.
|
||||
$account = get_account_by_id($this->fixtures['account'][0]['account_id']);
|
||||
|
||||
try {
|
||||
$this->post(
|
||||
"admin/account_edit/{$account['account_id']}",
|
||||
[],
|
||||
[
|
||||
'aid' => $account['account_id'],
|
||||
'pass1' => 'hunter2',
|
||||
'pass2' => 'hunter2',
|
||||
'service_class' => 'Some other class',
|
||||
'account_language' => 'nn',
|
||||
'security' => 'The security token',
|
||||
]
|
||||
);
|
||||
} catch (RedirectException $ex) {
|
||||
$this->assertEquals(z_root() . '/admin/accounts', $ex->getMessage());
|
||||
}
|
||||
|
||||
$reloaded = get_account_by_id($account['account_id']);
|
||||
|
||||
$this->assertNotEquals($account, $reloaded);
|
||||
$this->assertEquals('Some other class', $reloaded['account_service_class']);
|
||||
$this->assertEquals('nn', $reloaded['account_language']);
|
||||
|
||||
$now = new DateTimeImmutable('now');
|
||||
$this->assertEquals($now->format('Y-m-d H:i:s'), $reloaded['account_password_changed']);
|
||||
|
||||
$this->assertContains('Account settings updated.' . EOL, $this->info);
|
||||
$this->assertContains("Password changed for account {$account['account_id']}." . EOL, $this->info);
|
||||
}
|
||||
|
||||
public function test_form_with_missing_or_incalid_csrf_token_is_rejected(): void {
|
||||
$this->expectException(KillmeException::class);
|
||||
|
||||
// Emulate a failed CSRF check
|
||||
$this->stub_check_form_security(false);
|
||||
|
||||
$account_id = $this->fixtures['account'][0]['account_id'];
|
||||
|
||||
$this->post(
|
||||
"admin/account_edit/{$account_id}",
|
||||
[],
|
||||
[
|
||||
'aid' => $account_id,
|
||||
'pass1' => 'hunter2',
|
||||
'pass2' => 'hunter2',
|
||||
'service_class' => 'Some other class',
|
||||
'account_language' => 'nn',
|
||||
'security' => 'Invalid security token',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Override the stub_goaway method because we need the stub to live in the
|
||||
* Admin namespace.
|
||||
*/
|
||||
protected function stub_goaway(): void {
|
||||
$this->goaway_stub = $this->getFunctionMock('Zotlabs\Module\Admin', 'goaway')
|
||||
->expects($this->once())
|
||||
->willReturnCallback(
|
||||
function (string $uri) {
|
||||
throw new RedirectException($uri);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stub the check_form_security_token_ForbiddenOnErr.
|
||||
*
|
||||
* In these tests we're not really interested in _how_ the form security
|
||||
* tokens work, but that the code under test perform the checks. This stub
|
||||
* allows us to do that without having to worry if everything is set up so
|
||||
* that the real function would work or not.
|
||||
*
|
||||
* @param bool $valid true if emulating a valid token, false otherwise.
|
||||
*/
|
||||
protected function stub_check_form_security(bool $valid): void {
|
||||
$this->stub_check_security =
|
||||
$this->getFunctionMock('Zotlabs\Module\Admin', 'check_form_security_token_ForbiddenOnErr')
|
||||
->expects($this->once())
|
||||
->with(
|
||||
$this->identicalTo('admin_account_edit'),
|
||||
$this->identicalTo('security'))
|
||||
->willReturnCallback(function () use ($valid) {
|
||||
if (! $valid) {
|
||||
throw new KillmeException();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -31,30 +31,7 @@ class HelpTest extends \Zotlabs\Tests\Unit\Module\TestCase {
|
||||
* ["html"]
|
||||
*/
|
||||
public function test_get_request_when_help_file_exists(string $ext): void {
|
||||
// Stub file exists, to only retur true for the file with the current
|
||||
// extension
|
||||
$fe_stub = $this->getFunctionMock('Zotlabs\Lib\Traits', 'file_exists');
|
||||
$fe_stub
|
||||
->expects($this->any())
|
||||
->willReturnCallback(
|
||||
fn (string $path) => $path === "doc/en/about/help_topic.{$ext}"
|
||||
);
|
||||
|
||||
// Use a value map to make the `file_get_contents` stub return the
|
||||
// correct content for the file types.
|
||||
$file_content_map = [
|
||||
[ 'doc/en/about/help_topic.md', "### Help heading\n\$Projectname help content" ],
|
||||
[ 'doc/en/about/help_topic.bb', "[h3]Help heading[/h3]\n\n\$Projectname help content" ],
|
||||
[ 'doc/en/about/help_topic.html', "<h3>Help heading</h3><p>\$Projectname help content</p>" ],
|
||||
];
|
||||
|
||||
// Stub `file_get_contents` to plant our own content.
|
||||
$fgc_stub = $this->getFunctionMock('Zotlabs\Module', 'file_get_contents');
|
||||
$fgc_stub
|
||||
->expects($this->once())
|
||||
->willReturnMap($file_content_map);
|
||||
|
||||
|
||||
$stubs = $this->prepare_stubs($ext);
|
||||
$this->get("help/about/help_topic");
|
||||
|
||||
// Check that markdown content was correctly rendered
|
||||
@@ -104,6 +81,11 @@ class HelpTest extends \Zotlabs\Tests\Unit\Module\TestCase {
|
||||
$this->get('help');
|
||||
}
|
||||
|
||||
public function test_getting_locale_with_no_topic_should_redirect_to_about_page(): void {
|
||||
$this->expectRedirectTo('help/about/about');
|
||||
$this->get('help/de');
|
||||
}
|
||||
|
||||
public function test_find_help_file_returns_first_match(): void {
|
||||
// Stub file exists, to always return true
|
||||
$fe_stub = $this->getFunctionMock('Zotlabs\Lib\Traits', 'file_exists');
|
||||
@@ -121,6 +103,16 @@ class HelpTest extends \Zotlabs\Tests\Unit\Module\TestCase {
|
||||
$this->get('help/first');
|
||||
}
|
||||
|
||||
public function test_fall_back_to_english_if_localized_topic_dont_exist(): void {
|
||||
\App::$language = 'nb';
|
||||
|
||||
$stubs = $this->prepare_stubs('bb');
|
||||
$this->get('help/about/help_topic');
|
||||
|
||||
$this->assertPageContains('Hubzilla Documentation: About');
|
||||
$this->assertPageContains('This page is not yet available in norsk bokmål');
|
||||
}
|
||||
|
||||
public function test_includes(): void {
|
||||
// Stub `file_get_contents` to plant our own content.
|
||||
$fgc_stub = $this->getFunctionMock('Zotlabs\Module', 'file_get_contents');
|
||||
@@ -176,4 +168,31 @@ class HelpTest extends \Zotlabs\Tests\Unit\Module\TestCase {
|
||||
|
||||
$this->assertPageContains('<h3>This is the included file.</h3>');
|
||||
}
|
||||
|
||||
private function prepare_stubs(string $ext): array {
|
||||
// Stub file exists, to only retur true for the file with the current
|
||||
// extension
|
||||
$fe_stub = $this->getFunctionMock('Zotlabs\Lib\Traits', 'file_exists');
|
||||
$fe_stub
|
||||
->expects($this->any())
|
||||
->willReturnCallback(
|
||||
fn (string $path) => $path === "doc/en/about/help_topic.{$ext}"
|
||||
);
|
||||
|
||||
// Use a value map to make the `file_get_contents` stub return the
|
||||
// correct content for the file types.
|
||||
$file_content_map = [
|
||||
[ 'doc/en/about/help_topic.md', "### Help heading\n\$Projectname help content" ],
|
||||
[ 'doc/en/about/help_topic.bb', "[h3]Help heading[/h3]\n\n\$Projectname help content" ],
|
||||
[ 'doc/en/about/help_topic.html', "<h3>Help heading</h3><p>\$Projectname help content</p>" ],
|
||||
];
|
||||
|
||||
// Stub `file_get_contents` to plant our own content.
|
||||
$fgc_stub = $this->getFunctionMock('Zotlabs\Module', 'file_get_contents');
|
||||
$fgc_stub
|
||||
->expects($this->once())
|
||||
->willReturnMap($file_content_map);
|
||||
|
||||
return [ 'file_exists' => $fe_stub, 'file_get_contents' => $fgc_stub ];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
namespace Zotlabs\Tests\Unit\Module;
|
||||
|
||||
use PHPUnit\Framework\Attributes\After;
|
||||
use Zotlabs\Tests\Unit\UnitTestCase;
|
||||
use App;
|
||||
|
||||
@@ -25,6 +26,31 @@ class TestCase extends UnitTestCase {
|
||||
// Import PHPMock methods into this class
|
||||
use \phpmock\phpunit\PHPMock;
|
||||
|
||||
#[After]
|
||||
public function cleanup_stubs(): void {
|
||||
$this->killme_stub = null;
|
||||
$this->goaway_stub = null;
|
||||
}
|
||||
|
||||
protected function do_request(string $method, string $uri, array $query = [], array $params = []): void {
|
||||
$_GET['q'] = $uri;
|
||||
$_GET = array_merge($_GET, $query);
|
||||
$_POST = $params;
|
||||
|
||||
$_SERVER['REQUEST_METHOD'] = $method;
|
||||
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
||||
$_SERVER['QUERY_STRING'] = "q={$uri}";
|
||||
// phpcs:disable Generic.PHP.DisallowRequestSuperglobal.Found
|
||||
$_REQUEST = array_merge($_GET, $_POST);
|
||||
// phpcs::enable
|
||||
|
||||
\App::init();
|
||||
\App::$page['content'] = '';
|
||||
|
||||
$router = new \Zotlabs\Web\Router();
|
||||
$router->Dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulate a GET request.
|
||||
*
|
||||
@@ -34,24 +60,21 @@ class TestCase extends UnitTestCase {
|
||||
* as keys.
|
||||
*/
|
||||
protected function get(string $uri, array $query = []): void {
|
||||
$_GET['q'] = $uri;
|
||||
$this->do_request('GET', $uri, $query);
|
||||
}
|
||||
|
||||
if (!empty($query)) {
|
||||
$_GET = array_merge($_GET, $query);
|
||||
}
|
||||
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
||||
$_SERVER['QUERY_STRING'] = "q={$uri}";
|
||||
// phpcs:disable Generic.PHP.DisallowRequestSuperglobal.Found
|
||||
$_REQUEST = $_GET;
|
||||
// phpcs::enable
|
||||
|
||||
\App::init();
|
||||
\App::$page['content'] = '';
|
||||
|
||||
$router = new \Zotlabs\Web\Router();
|
||||
$router->Dispatch();
|
||||
/**
|
||||
* Emulate a POST request.
|
||||
*
|
||||
* @param string $uri The URI to request. Typically this will be the module
|
||||
* name, followed by any req args separated by slashes.
|
||||
* @param array $query Associative array of query args, with the parameters
|
||||
* as keys.
|
||||
* @param array $params Associative array of POST params, with the param names
|
||||
* as keys.
|
||||
*/
|
||||
protected function post(string $uri, array $query = [], array $params = []): void {
|
||||
$this->do_request('POST', $uri, $query, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,8 +123,7 @@ class TestCase extends UnitTestCase {
|
||||
* @throws KillmeException
|
||||
*/
|
||||
protected function stub_killme(): void {
|
||||
$killme_stub = $this->getFunctionMock('Zotlabs\Module', 'killme');
|
||||
$killme_stub
|
||||
$this->killme_stub = $this->getFunctionMock('Zotlabs\Module', 'killme')
|
||||
->expects($this->once())
|
||||
->willReturnCallback(
|
||||
function () {
|
||||
@@ -147,8 +169,7 @@ class TestCase extends UnitTestCase {
|
||||
* @throws RedirectException
|
||||
*/
|
||||
protected function stub_goaway(): void {
|
||||
$goaway_stub = $this->getFunctionMock('Zotlabs\Module', 'goaway');
|
||||
$goaway_stub
|
||||
$this->goaway_stub = $this->getFunctionMock('Zotlabs\Module', 'goaway')
|
||||
->expects($this->once())
|
||||
->willReturnCallback(
|
||||
function (string $uri) {
|
||||
|
||||
@@ -47,7 +47,7 @@ require_once 'include/dba/dba_transaction.php';
|
||||
*/
|
||||
class UnitTestCase extends TestCase {
|
||||
protected array $fixtures = array();
|
||||
protected ?\DbaTransaction $db_transacton = null;
|
||||
protected ?\DbaTransaction $db_transaction = null;
|
||||
|
||||
/**
|
||||
* Connect to the test db, load fixtures and global config.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user