Compare commits

..

464 Commits
8.2 ... 8.8

Author SHA1 Message Date
Mario
0fd8e02a88 Merge branch '8.8RC' 2023-11-25 17:12:28 +01:00
Mario
55c4bfb670 version 8.8 2023-11-25 17:11:07 +01:00
Mario
ea1030f8bf Merge branch 'dev' into 8.8RC 2023-11-25 17:06:55 +01:00
Mario
6dd285811a changelog 2023-11-25 17:06:25 +01:00
Mario
ee149ed1eb Merge branch 'dev' into 8.8RC 2023-11-25 17:05:08 +01:00
Mario
c3aa96d423 update changelog 2023-11-24 14:40:58 +01:00
Mario
6e59d95da5 Merge branch 'dev' into 8.8RC 2023-11-23 20:25:13 +00:00
Mario
a396e74a79 like in get_cached_actor() also remove fragment in get_actor() 2023-11-23 13:21:56 +00:00
Mario
80bdb39ae3 case insensitive digest algo 2023-11-22 16:41:44 +00:00
Mario
5cb1a9dcc6 Merge branch 'dev' into 8.8RC 2023-11-22 16:21:58 +00:00
Mario
1cfa81450c remove follow (does not make any sense to add follow link of the logged in channel), add startpage 2023-11-21 08:07:40 +00:00
Mario
1f18fed3a2 add additional observer and channel info to nav if applicable 2023-11-21 08:01:03 +00:00
Mario
33cb429e15 remove unused variable 2023-11-20 21:56:31 +00:00
Mario
cfdbf02e6b the additional parameter has been deprecated there is no need to check the version anymore 2023-11-20 21:52:40 +00:00
Mario
f8c631a3f0 Merge branch 'dev' into 8.8RC 2023-11-20 20:32:46 +00:00
Mario
74911e9f6d revert dreport changes - too chatty 2023-11-20 20:32:14 +00:00
Mario
0f453ae4cf version 8.8RC2 2023-11-20 20:27:35 +00:00
Mario
febebc8d3d more do not provide channel info for templates and code cleanup 2023-11-20 20:21:03 +00:00
Mario
166c45f97f do not provide channel info for templates 2023-11-20 19:22:06 +00:00
Mario
af58364fef only check for privacy mismatch if observer != owner 2023-11-17 07:50:10 +00:00
Mario
eadf83d61b work around a possible privacy mismatch when processing zot requests 2023-11-16 15:57:03 +00:00
Mario
3c20231aad add backlink to profile to profile vcard and adjust switch colors for better visibility 2023-11-15 22:11:20 +00:00
Mario
402bf395d1 bump dev version 2023-11-10 08:25:10 +00:00
Mario
9a45938fe6 run composer dump-auotoload 2023-11-10 08:20:57 +00:00
Mario
d963e4a2c4 version and strings 2023-11-10 08:15:57 +00:00
Mario
1063a67ae2 a possible fix for issue #1816 2023-11-09 21:37:28 +00:00
Mario
602ef883bb version 2023-11-09 21:00:52 +00:00
Mario
aad6042d42 DB Update 1259 2023-11-09 20:09:49 +00:00
Mario
85d8c1a97e some low level work on native repeats 2023-11-09 19:32:29 +00:00
Mario
547e6542ba move color_mode related code to theme_init.php 2023-11-07 10:09:31 +00:00
Mario
f74044f9b0 Merge branch 'owa_improvement' into 'dev'
work with Mastodon-style keyId

See merge request hubzilla/core!2060
2023-11-07 08:46:15 +00:00
Mario
42651707f8 check if required keys are set 2023-11-07 08:40:34 +00:00
Mario
95c13eaf5a remove logging 2023-11-07 08:34:13 +00:00
Mario
c74068ae4d libzot: correctly attribute streams repeats 2023-11-07 08:33:22 +00:00
Mario
ca92dd0299 bbcode: do not overrule default list style 2023-11-07 08:30:27 +00:00
Mario
798f791b6b simplepie: fix fatal error with php 8.2 - issue is filed upstream but probably will not be fixed any time soon 2023-11-07 08:28:42 +00:00
Mario
331622309f if channel is not defined we need to provide an empty array 2023-11-01 15:47:16 +00:00
Mario
4f334525c2 only show tools to creators if they still have perms 2023-11-01 15:38:53 +00:00
Mario Vavti
82e704ec5b remove the directory updates entry if the channel was removed
(cherry picked from commit 67aaa97904)
2023-10-26 14:08:33 +00:00
Mario Vavti
67aaa97904 remove the directory updates entry if the channel was removed 2023-10-26 16:06:15 +02:00
Mario
4f55248a6c Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-10-25 13:06:24 +00:00
Mario
61b46f1a3e add stats logging to zotfinger 2023-10-25 13:05:56 +00:00
Mario Vavti
286104a988 slightly less noise when logging normal 2023-10-25 14:45:26 +02:00
Mario Vavti
8ea6ead08a use Activity::get_actor() which will check for the cache record in xconfig before fetching 2023-10-21 21:42:14 +02:00
Mario
bd9cc23681 update logger statements 2023-10-20 09:30:52 +00:00
Mario
f2d7298cf4 check if we have the record in the short time cache before actually fetching it 2023-10-20 09:30:29 +00:00
Mario
da636ca881 css fix 2023-10-20 09:27:53 +00:00
Mario
39bfa30185 css fix 2023-10-19 11:27:50 +00:00
Mario
d7c005a2f1 refactor actor_store() 2023-10-19 06:59:13 +00:00
Mario
763b69bf5b enable reset button in mod rpost 2023-10-12 08:39:18 +00:00
Mario
2f2e353ece use new lang detect library which supports much more languages 2023-10-07 16:00:34 +00:00
Mario Vavti
0092b7c0a4 should be tinyint instead of numeric for mysql 2023-10-06 14:28:59 +02:00
Mario Vavti
9f48109640 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-10-06 14:24:51 +02:00
Mario Vavti
b976adb8aa add missing columns in install script 2023-10-06 14:24:33 +02:00
Mario
fe38c81e07 use the correct variable 2023-10-06 08:50:11 +00:00
Mario
fed9bc7072 use encode_person() instead of plain xchan_url since the function makes some special effort to determine the real actor id 2023-10-06 08:49:36 +00:00
Mario
044e252d19 composer update html to markdown 2023-10-05 11:35:02 +00:00
Mario
6920fb2793 composer update oauth2 server 2023-10-05 11:33:28 +00:00
Mario
3d1171de8d composer update smarty 2023-10-05 10:24:46 +00:00
Mario
6e09754d06 rever iconv in gitlab ci 2023-10-05 10:20:03 +00:00
Mario
32f2de17d4 composer update bootstrap 2023-10-05 10:17:07 +00:00
Mario
600e8081a8 fix regression 2023-10-05 09:29:53 +00:00
Mario
59fd7c3c9a css fix 2023-10-04 19:15:53 +00:00
Mario Vavti
7e70fe1126 bump version 2023-10-04 21:01:30 +02:00
Mario Vavti
5265c774ae move right aside into bottom of left aside if screen width is < 1200px 2023-10-04 21:00:00 +02:00
Mario Vavti
d1421d720c parse the event object in first place and use the body bbcode as backup 2023-10-04 20:11:05 +02:00
Pascal
2bd09d3b30 work with Mastodon-style keyId 2023-10-04 17:00:19 +02:00
Mario
56e54ac820 if the item is sourced and provides an event add it to the calendar 2023-09-28 16:55:49 +00:00
Mario
08d85798ed since the activity filter widget requires the network module we can link to the module directly so that it will work as quicklink widget in other modules 2023-09-27 13:27:35 +00:00
Mario
38c2b36606 ÅÅfix narrow navbar 2023-09-25 20:00:33 +00:00
Mario
01b747287a fix php warnings 2023-09-22 09:24:04 +00:00
Mario
c925e13e5a cleanup and warnings 2023-09-21 14:47:56 +00:00
Mario
1ced89a869 fix javascript error 2023-09-21 09:14:15 +00:00
Mario
a5e32dc3de more deprecate $a 2023-09-21 08:34:02 +00:00
Mario
150174c3bb jsonld: return object instead of json string 2023-09-21 08:33:17 +00:00
Mario
601ee0b40b only show theme switch icon if switching is supported by the theme 2023-09-21 08:31:53 +00:00
Mario
9627c3e7c8 store the actor cache date so we can easily invalidate it after a period of time 2023-09-21 06:14:24 +00:00
Mario
d88c67eba3 deprecate the ancient $a variable 2023-09-20 10:45:33 +00:00
Mario
bb38a90dda use small profile images instead of medium 2023-09-17 13:35:55 +00:00
Mario
c36743f7ee css fixes 2023-09-16 19:17:02 +00:00
Mario
860275f888 typo 2023-09-16 18:37:34 +00:00
Mario
670228ff63 more changelog
(cherry picked from commit 4338e4ef86)
2023-09-16 20:16:59 +02:00
Mario
4338e4ef86 more changelog 2023-09-16 18:16:13 +00:00
Mario
dbc712c53c version 8.6.3 2023-09-16 18:02:22 +00:00
Mario
bb6011ea73 Revert "version 8.6.3"
This reverts commit 1915f34de8
2023-09-16 18:00:42 +00:00
Mario
1915f34de8 version 8.6.3 2023-09-16 17:59:31 +00:00
Mario
675f26fe90 changelog
(cherry picked from commit 491e309911)
2023-09-16 19:58:52 +02:00
Mario
491e309911 changelog 2023-09-16 17:55:59 +00:00
Mario
283d27c5b1 css fix 2023-09-16 11:35:41 +00:00
Mario
24d862c1bc fix regression in jsonld_document_loader()
(cherry picked from commit 3708c1ac8c)
2023-09-16 13:26:38 +02:00
Mario
3708c1ac8c fix regression in jsonld_document_loader() 2023-09-16 10:51:28 +00:00
Mario
df60be423a redbasic: add functions for reference 2023-09-15 13:50:19 +00:00
Mario
a1e583129f more type checking
(cherry picked from commit a06b28b693)
2023-09-15 15:46:15 +02:00
Mario
a06b28b693 more type checking 2023-09-15 13:45:24 +00:00
System user; apache
198070700c only select the required fields to prevent memory exhaustion on big result sets
(cherry picked from commit 3a01aa40d8)
2023-09-15 15:32:38 +02:00
System user; apache
3a01aa40d8 only select the required fields to prevent memory exhaustion on big result sets 2023-09-15 15:28:13 +02:00
Mario
b628af2258 allow themes to manipulate app icons (photos) via a hook 2023-09-15 06:55:27 +00:00
Mario
0cb5d0d63e also look for widgets in view/theme/themename/widget 2023-09-14 12:30:14 +00:00
Mario
526c85e2ca fix minor regression after recent changes 2023-09-14 10:00:24 +00:00
Mario
8a21c8e618 more theme fixes 2023-09-13 20:56:27 +00:00
Mario
8d3d5747d2 more theme fixes 2023-09-13 16:31:38 +00:00
Mario
f1f1406596 revert extra padding 2023-09-13 15:53:40 +00:00
Mario
9e42be9884 theme fixes 2023-09-13 15:51:10 +00:00
Mario
75e75b93cf an attempt to cache seen item mids for the purpose that we can hide seen pubstream items from the notifications - might revert if it turns out that it does not scale 2023-09-10 19:09:55 +00:00
Mario
0e8ecbc9fc theme fixes to make a barebones theme work slightly better 2023-09-10 08:00:18 +00:00
Mario
a88236b36f possible fix for item widget not respecting ACL if added by title - issue #1799 2023-09-09 18:52:30 +00:00
Mario
df06c54bd2 Merge branch 'translations/update-norwegian-bokmål-strings' into 'dev'
Update translations for Norwegian Bokmål.

See merge request hubzilla/core!2059
2023-09-09 18:02:52 +00:00
Mario
f2d88387c9 Merge branch 'redbasic/fix-darktheme-colorbox' into 'dev'
redbasic: Use body background color for colorboxes.

See merge request hubzilla/core!2058
2023-09-09 18:01:00 +00:00
Mario
db4c6bbd3b Merge branch 'cherry-pick-847732bd-2' into 'dev'
Update Spanish strings

See merge request hubzilla/core!2057
2023-09-09 17:59:48 +00:00
Harald Eilertsen
c8e7f79f50 Update translations for Norwegian Bokmål. 2023-09-09 15:41:18 +02:00
Mario
1157dc7dc8 make sure to set the other relevant dates aswell to omit discrepancies if they would be set a splitsecond later when we store the item 2023-09-07 19:55:15 +00:00
Harald Eilertsen
c12833521f Transparent background for colorbox controls icons.
This makes it blend in better when using dark style. I've kept the
actual button/control colours unchanged though.
2023-09-07 20:34:40 +02:00
Harald Eilertsen
5d9346999e redbasic: Use body background color for colorboxes.
Typically (only?) used by the "view source" function.
2023-09-07 13:30:58 +02:00
mjfriaza:4GF~eYj,-iAv
52c0631833 Update Spanish strings
(cherry picked from commit 847732bd8ac4b79f206981af7d90f183ee8ea58a)
2023-09-02 16:37:25 +02:00
Mario
e16aefec2c call init allthough it does not contain anything atm. it will set up things we need later e.g. App::$page["htmlhead"] and php will raise a warning if it does not exist. Also minor cleanup 2023-08-30 08:44:18 +00:00
Mario
053a247cc8 work around sabre caldav php warnings 2023-08-28 08:11:32 +00:00
Mario
1426b7a6dc order by hubloc_id like everywhere else for this reason and do not include deleted hublocs 2023-08-27 20:29:30 +00:00
Mario
ec66949b35 version 8.6.2 2023-08-27 19:06:14 +00:00
Mario
bc9d8d1136 changelog 2023-08-27 19:03:21 +00:00
Mario
542a527d0d changelog 2023-08-27 19:02:55 +00:00
Mario Vavti
5e0c392287 test refactor the previous commit
(cherry picked from commit 0a3094fc9a)
2023-08-27 20:01:01 +02:00
Mario Vavti
05ff94941c allow public stream comments/reactions if item_fetched is set, when fetching parent of a reaction fetch the thr_parent
(cherry picked from commit 816bbad28a)
2023-08-27 20:00:30 +02:00
Mario
a27d75d610 fix notification text for likes in cases where obj.actor is not set
(cherry picked from commit ce4150cd06)
2023-08-27 19:59:24 +02:00
Mario
446e842904 make sure that we allow "0" as pathname
(cherry picked from commit be19b75031)
2023-08-27 19:58:55 +02:00
Mario
ba153e2c18 mising pdl file
(cherry picked from commit 2d5c99f459)
2023-08-27 19:58:07 +02:00
Mario
3342ea6891 fix unable to create folders with name 0
(cherry picked from commit c4af4e3297)
2023-08-27 19:57:01 +02:00
Mario
8c3d5fd295 fix index name mixup
(cherry picked from commit 1acfc05e2d)
2023-08-27 19:56:26 +02:00
Mario
5fc58fb10a missing semicolon
(cherry picked from commit b40c38f58c)
2023-08-27 19:56:10 +02:00
Mario
4e2ae9cd4e remove unused variable
(cherry picked from commit 0ec715d7c9)
2023-08-27 19:55:49 +02:00
DM42.Net Hubzilla Development
4167ca2e5c Fix Typo
(cherry picked from commit 3bd2a91992)
2023-08-27 19:55:23 +02:00
Mario
9b3e9dcf02 fix cached jsonld files fetched via network 2023-08-27 17:53:40 +00:00
Mario
f203fcc92e more performance improvements
(cherry picked from commit 4b1384be83)
2023-08-27 19:50:39 +02:00
Mario
0b20069c20 move trigger out of the loop for better performance and some var -> let 2023-08-27 17:49:52 +00:00
Mario
bad7b778b3 fix php warning 2023-08-27 17:48:10 +00:00
Mario
f89ce93940 ignore internal follow activity
(cherry picked from commit 7200c71673)
2023-08-27 19:45:51 +02:00
Mario
1ddbc8a26d fix admin table highlight by adding the correct classes
(cherry picked from commit c412c01a65)
2023-08-27 19:43:09 +02:00
Mario Vavti
0a3094fc9a test refactor the previous commit 2023-08-21 10:45:12 +02:00
Mario Vavti
816bbad28a allow public stream comments/reactions if item_fetched is set, when fetching parent of a reaction fetch the thr_parent 2023-08-21 10:07:51 +02:00
Mario
ce4150cd06 fix notification text for likes in cases where obj.actor is not set 2023-08-19 08:55:17 +00:00
Mario
be19b75031 make sure that we allow "0" as pathname 2023-08-15 12:05:50 +00:00
Mario
3ddab5966b only try to fetch the icon if we actually got one 2023-08-14 18:13:58 +00:00
Mario
2d5c99f459 mising pdl file 2023-08-14 09:40:51 +00:00
Mario
a5a1bbf5d7 move profile photo fetching to background 2023-08-14 09:21:45 +00:00
Mario
c4af4e3297 fix unable to create folders with name 0 2023-08-14 08:17:47 +00:00
Mario
1acfc05e2d fix index name mixup 2023-08-14 07:58:44 +00:00
Mario
b40c38f58c missing semicolon 2023-08-14 07:38:36 +00:00
Mario
87c41cb9ac Merge branch 'DM42-Manifest-Typo-20230725' into 'dev'
Fix Typo

See merge request hubzilla/core!2055
2023-08-11 09:03:29 +00:00
Mario
0ec715d7c9 remove unused variable 2023-08-09 08:18:27 +00:00
Mario
e6a261a789 now all acl fields are checked. if they are not complete the check will fail 2023-08-09 08:01:18 +00:00
DM42.Net Hubzilla Development
3bd2a91992 Fix Typo 2023-07-25 09:07:32 -04:00
Mario
c721bc672c Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-07-21 12:07:57 +00:00
Mario
931b876b44 fix cached jsonld files fetched via network 2023-07-21 12:07:17 +00:00
Mario
87b91e5023 Merge branch 'DM42-20230718-fixjsonldrawfile' into 'dev'
add .jsonld to the list of allowed file suffixes for direct download.  Fixes...

See merge request hubzilla/core!2053
2023-07-21 10:02:41 +00:00
Mario
4b1384be83 more performance improvements 2023-07-21 08:17:45 +00:00
Mario
8da6e6a096 move trigger out of the loop for better performance and some var -> let 2023-07-20 19:20:56 +00:00
Mario
5181e575b4 fix accesslist in two cases 2023-07-20 11:46:40 +00:00
Mario
ca994735be Merge branch 'zotlabs/improve-access-list-type-safety' into 'dev'
Zotlabs: Improve type safety for AccessList class.

See merge request hubzilla/core!2052
2023-07-20 09:05:42 +00:00
Harald Eilertsen
718c303086 Zotlabs: More type safety for AccessList class.
Add more type declarations to class attributes and functions.

This should ensure that only strings and null values can be assigned to
the various access list members. This is still a bit loose, as we should
probably aim for lists of channel or group id's instead of a generic
type like a string.

I'll leave that for later, though.
2023-07-19 20:19:00 +02:00
Mario
7200c71673 ignore internal follow activity 2023-07-19 12:52:41 +00:00
DM42.Net Hubzilla Development
14c97799c6 add .jsonld to the list of allowed file suffixes for direct download. Fixes 404 error when trying to get /library/w3org/security-v1.jsonld and /library/w3org/activitystreams.jsonld 2023-07-18 14:34:10 -04:00
Harald Eilertsen
a06e8bfaee Zotlabs: Improve type safety for AccessList class.
Add type annotations for constructor and set* methods, and throw an
exception if the passed in arrays are missing required keys. This means
that both invalid input types and missing keys will throw and exception
rather than just die with a runtime error.

There's not checks to verify that the contents of the required array
keys are valid or make sense, though. They are just assigned, and
returned as is by the get method when requested.

Also, the set_from_array method is not well tested at the moment.
2023-07-18 20:18:42 +02:00
Mario
7dad60bbd5 version 8.6.1 2023-07-18 13:09:56 +00:00
Mario
a66b4626fb changelog
(cherry picked from commit 330add963d)
2023-07-18 15:08:07 +02:00
Mario
330add963d changelog 2023-07-18 13:04:34 +00:00
Mario
da1ccc620b Merge branch 'DM42-20230717-fixfatalerron304' into 'dev'
Skip logging when DB functions are not yet loaded (logging requires db lookup).

See merge request hubzilla/core!2051
2023-07-18 11:12:11 +00:00
Mario
c412c01a65 fix admin table highlight by adding the correct classes 2023-07-18 11:00:21 +00:00
Mario
74d7fa61d9 fix hcard addon regression
(cherry picked from commit ef6ea4484e)
2023-07-18 12:11:50 +02:00
Mario
ef6ea4484e fix hcard addon regression 2023-07-18 09:57:38 +00:00
DM42.Net Hubzilla Development
ba2d775215 Skip logging when DB functions are not yet loaded (logging requires db lookup). 2023-07-17 20:34:16 -04:00
Mario
f866771854 Merge branch 'tests/cleanup-unit-tests' into 'dev'
Cleanup unit tests

See merge request hubzilla/core!2049
2023-07-17 08:43:08 +00:00
Mario
70b8c57d22 basic per item rtl language support - issue ##1780 2023-07-13 09:47:50 +00:00
Harald Eilertsen
b04e0d0fd4 tests: AccessListTest expand is_private test. 2023-07-12 21:57:27 +02:00
Harald Eilertsen
3f9d5e11d1 tests: AccessListTest move type annotation to code
This cleans up the doc comment. Should probably try to do this
everywhere.
2023-07-12 21:56:09 +02:00
Harald Eilertsen
09fe271b25 tests: AccessListTests nitpicking on doc comment. 2023-07-12 21:39:37 +02:00
Harald Eilertsen
d5c1a49984 tests: AccessListTest collect defaults in one testcase.
Just no need to have them spread around in various other tests cases.
2023-07-12 21:38:10 +02:00
Harald Eilertsen
e80d3653c9 test: Enable and cleanup GetTagsTest.
These tests actually tests both the get_tags() function, and the
handle_tags() function. The latter don't work, and should probably be
split into it's own test cases.

There's also some stubs here that we may want to deal with in another
way.

Also removed meaningless "test" of intval() builtin function. It behaves
as documented, no need for us to test it.
2023-07-12 20:42:37 +02:00
Harald Eilertsen
30b0d0a5cc tests: Cleanup ContainsAttribute test.
Mostly cosmetic to satisfy phpcs + remove explicit require.
2023-07-12 20:42:37 +02:00
Harald Eilertsen
9beceb9b02 tests: Cleanup Autoname test.
Not sure if this test is actually useful, but leave it for now.
2023-07-12 20:42:37 +02:00
Harald Eilertsen
6f13cabfba tests: Don't explicitly require CUT in AntiXSSTest.
Rely on PHPUnit config to load the app and the code under test.
2023-07-12 20:42:37 +02:00
Harald Eilertsen
7bd2de9967 unit-tests: There's no need to test builtin func hex2bin 2023-07-12 20:42:37 +02:00
Harald Eilertsen
b0b0973e2d unit tests: Cosmetic fixes in AntiXSSTest.php
- Start comments with capital letter
- Fix indentation
- Add missing doc comments
2023-07-12 20:42:36 +02:00
Mario
3d866e8975 update date 2023-07-11 19:55:08 +00:00
Mario
63fb8d0392 Merge branch '8.6RC' 2023-07-11 18:57:18 +00:00
Mario
384de0925e version 8.6 2023-07-11 18:56:21 +00:00
Mario
5b5c569c82 RC2 2023-07-05 10:06:57 +00:00
Mario
6f2371ee74 changelog 2023-07-05 10:05:38 +00:00
Mario
d6e7d90197 fix regression after recent changes 2023-07-05 09:29:33 +00:00
Mario
aa73db0fe6 bump dev version 2023-07-04 18:05:37 +00:00
Mario
d85088fc3d version and strings 2023-07-04 18:00:33 +00:00
Mario
7e21aeedcd css fix 2023-07-04 17:51:16 +00:00
Mario
342460fa17 css fixes 2023-07-04 11:19:04 +00:00
Mario
e57211fbd1 also filter deleted hublocs 2023-07-04 09:07:39 +00:00
Mario
d31eb4c89c update fullcalendar 2023-07-04 08:47:22 +00:00
Mario
6753d260e4 do not linkify in nobb and noparse tags - issue #1776 2023-07-04 08:05:00 +00:00
Mario
a3092204a1 fix issue #1771 2023-07-03 18:35:10 +00:00
Mario
10b49af776 fix php warning 2023-07-03 12:42:46 +00:00
Mario
3497ced9f9 Ãfix php warning 2023-07-03 10:49:34 +00:00
Mario
7a0f22b0a7 make sure to return infos from current hub where applicable - fix issue #1770 2023-07-03 10:37:32 +00:00
Mario
4f03272a5f unify code for selecting deliverable abook xchans 2023-07-01 11:03:26 +00:00
Mario
7755936a2e remove unused pseudo abook code 2023-06-29 12:31:32 +00:00
Mario
9f6844ec30 pass $escape to stringify_array_elms() 2023-06-29 11:43:02 +00:00
Mario
c2952aa803 make sure to not allow moderation of poll answers 2023-06-29 11:29:48 +00:00
Mario
8f7383f5c2 text 2023-06-28 12:05:55 +00:00
Mario
750641ef19 implement inline moderation of reactions 2023-06-27 14:53:23 +00:00
Mario
fb48dfc082 bump version 2023-06-24 21:30:39 +00:00
Mario
1de5bce1c1 remove logging 2023-06-24 21:00:24 +00:00
Mario
676603239d Merge branch 'cherry-pick-1baa3489' into 'dev'
Update Spanish translation-2

See merge request hubzilla/core!2048
2023-06-23 12:39:19 +00:00
Mario
4c87f36a8c bump version 2023-06-23 12:37:07 +00:00
Mario
12b2137a04 fix relaying and syncing in Activity::drop(), change wording for moderation request notices and redirect moderation request for reactions to mod moderate 2023-06-23 12:35:41 +00:00
mjfriaza
762e1c9c2b Update Spanish translation-2
(cherry picked from commit 1baa34894f6799cac3d973db8c1205239ad6179b)
2023-06-23 13:44:18 +02:00
Mario
cd26ead043 implement optional moderation of unsolicited comments, minor css fixes and some more work on ocap 2023-06-23 09:13:51 +00:00
Mario
6a560cfec4 always check pageflags otherwise site specific flags will be overwritten when a sync package arrives from a clone that has no flags for this channel - fix issue #1769 2023-06-21 09:20:25 +00:00
Mario
489ba72d5c fix issues in mod oep 2023-06-19 19:47:01 +00:00
Mario Vavti
5df9779669 make sure to use the correct url 2023-06-18 22:27:33 +02:00
Mario
e49d2f6b8f remove deprecated templates 2023-06-18 09:20:57 +00:00
Mario
9550a7a954 more html fix 2023-06-18 09:02:10 +00:00
Mario
d9f855b97e fix bogus html 2023-06-18 09:00:54 +00:00
Mario
e275dae6e3 use function to get actor hublocs 2023-06-18 08:43:05 +00:00
Mario
88ccc2a3b9 bump version 2023-06-17 07:59:16 +00:00
Mario
84487edc05 undefined variable and return null in fetch_local if we did not find anything (we also return null in fetch) 2023-06-16 12:27:08 +00:00
Mario
7177649969 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-06-16 12:16:47 +00:00
Mario
18b7b3f125 deprecate ActivityStreams::fetch() and provide the possibility to fetch local items directly 2023-06-16 12:16:22 +00:00
Mario
89c7e1a8ee Merge branch 'help' into 'dev'
typo in hooklist.bb

See merge request hubzilla/core!2042
2023-06-15 20:41:06 +00:00
Mario
774a9b118e Merge branch 'make-unit-tests-pass' into 'dev'
Make unit tests pass

See merge request hubzilla/core!2041
2023-06-15 20:40:28 +00:00
Mario
327841280b Merge branch 'dev' into 'dev'
Simplified version auf automated install script

See merge request hubzilla/core!2040
2023-06-15 20:36:22 +00:00
OJ Random
1e0a686561 Simplified version auf automated install script 2023-06-15 20:36:20 +00:00
OJ Random
96883100b4 typo in hooklist.bb 2023-06-15 19:19:08 +02:00
Harald Eilertsen
1fcb05ed8c Unit tests: Update Markdown tests to reflect that it works. 2023-06-14 23:02:13 +02:00
Harald Eilertsen
8c85516c57 Unit tests: Book Hubzilla to make app env available in tests.
Not quite unit test clean, but a somewhat pragmatic approach to make the
tests pass as is.
2023-06-14 23:00:44 +02:00
Mario
6989a3eaad fix string replacement if a match is available more than once 2023-06-12 19:05:37 +00:00
Mario
57796a2f96 only remove the owner from delivery if its their post and minor cleanup
(cherry picked from commit 59b217f7ea)
2023-06-12 10:17:17 +02:00
Mario
59b217f7ea only remove the owner from delivery if its their post and minor cleanup 2023-06-12 08:13:42 +00:00
Mario
fb9a193c44 do not add deleted xchans for poco 2023-06-08 16:24:02 +00:00
Mario
2739f1f3f0 remove logging 2023-06-08 15:34:00 +00:00
Mario
0c2cb18578 shuffle queue deliveries for more randomness 2023-06-08 15:33:02 +00:00
Mario
db2c5aae84 bump version 2023-06-02 19:56:50 +00:00
Mario
aa2cec103b Merge branch 'dev' into 'dev'
Update 'full' and 'minimal' layouts to use color_mode functionality

See merge request hubzilla/core!2039
2023-06-02 19:54:59 +00:00
ivan zlax
a532a70ac0 Update 'full' and 'minimal' layouts to use color_mode functionality 2023-06-02 19:54:59 +00:00
Mario
ec6cec8854 even more changelog
(cherry picked from commit 3fb22d27ab)
2023-06-02 21:47:41 +02:00
Mario
3fb22d27ab even more changelog 2023-06-02 19:46:49 +00:00
Mario
1cbaab5889 more changelog
(cherry picked from commit fef19b47c2)
2023-06-02 21:39:27 +02:00
Mario
fef19b47c2 more changelog 2023-06-02 19:38:46 +00:00
Mario
5126613825 update bootstrap to version 5.3 2023-06-02 19:35:23 +00:00
Mario
07097d2fa3 version 8.4.2 2023-06-02 19:27:36 +00:00
Mario
8c9fb32ca0 changelog
(cherry picked from commit 68d921e918)
2023-06-02 21:26:22 +02:00
Mario
68d921e918 changelog 2023-06-02 19:25:49 +00:00
Mario
330b36159d work around hubloc confusion in mod rmagic
(cherry picked from commit 02089f15c4)
2023-06-02 21:18:52 +02:00
Mario
046152e798 improved unseen forums notification
(cherry picked from commit 6a27afa6ac)
2023-06-02 21:18:30 +02:00
Mario
11ca5bb7d5 owa: workaround for friendica when using nginx until this will be fixed at their side and check prrofile uid for features instead of local channel
(cherry picked from commit 423fdc0a96)
2023-06-02 21:16:56 +02:00
Mario
e0838ff8ab fix wrong array key
(cherry picked from commit 11a2419c22)
2023-06-02 21:13:31 +02:00
Mario
11a2419c22 fix wrong array key 2023-06-02 19:10:53 +00:00
Mario
f3420c0adb bump version 2023-06-02 18:30:04 +00:00
Mario
bd84ff4838 update bootstrap to version 5.3 2023-06-02 16:36:57 +00:00
Mario
87689df062 even more adjust text 2023-06-02 15:59:26 +00:00
Mario
1bfbd57ee4 more adjust text 2023-06-02 15:34:06 +00:00
Mario
64d7585282 adjust text 2023-06-02 15:29:24 +00:00
Mario
0ee03a565f remove custom acl from rpost 2023-06-02 12:02:50 +00:00
Mario Vavti
1b0e268416 fix theme_attachments()
(cherry picked from commit 65a472c113)
2023-06-02 13:35:39 +02:00
Mario
0e8d1afcaf Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-06-02 11:34:08 +00:00
Mario
48a33f08e2 ocap initial checkin 2023-06-02 11:33:44 +00:00
Mario Vavti
f9ca956510 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-06-02 13:30:36 +02:00
Mario Vavti
65a472c113 fix theme_attachments() 2023-06-02 13:30:21 +02:00
Mario
4b17ea04a7 add owner and author to item_permissions_sql() 2023-06-01 10:15:35 +00:00
Mario
423fdc0a96 owa: workaround for friendica when using nginx until this will be fixed at their side and check prrofile uid for features instead of local channel 2023-06-01 08:15:33 +00:00
Mario
396b124e84 do not parse x-multicode as bbcode 2023-05-30 09:11:30 +00:00
Mario
6a27afa6ac improved unseen forums notification 2023-05-30 08:59:29 +00:00
Mario
b9812ba06a update composer libs 2023-05-30 08:36:17 +00:00
Mario
bc6aded074 fix a possible privacy mismatch 2023-05-29 18:16:38 +00:00
Mario
904401617a mod magic make a get request instead of post and remove digest header 2023-05-26 10:17:53 +00:00
Mario
02089f15c4 work around hubloc confusion in mod rmagic 2023-05-26 08:19:34 +00:00
Mario
43a18a2569 update description 2023-05-25 09:01:29 +00:00
Mario
4c2dc2bf16 Merge branch 'dev' into 'dev'
double columns templates

See merge request hubzilla/core!2035
2023-05-25 08:53:03 +00:00
ivan zlax
e6eb2a8476 double columns templates 2023-05-25 08:53:03 +00:00
Mario
af5ae163f3 more fixes for where keyId = acct:xxx@yyy.zz 2023-05-25 08:18:16 +00:00
Mario
d00860430f owa fixes for where keyId = acct:xxx@yyy.zz 2023-05-25 08:03:10 +00:00
Mario
af0b4a0fca return hubloc_hash instead of hubloc_id_url for AP and improved check for location 2023-05-24 09:08:32 +00:00
Mario
404189f88c backgound url must be between quotation marks 2023-05-20 17:38:37 +00:00
Mario
1a27fad9b9 backgound url must be between quotation marks 2023-05-20 12:40:28 +00:00
Mario
c2cfe481df version 8.4.1 2023-05-20 09:28:32 +00:00
Mario
3a56fb6ec6 Merge branch 'dev' 2023-05-20 09:27:45 +00:00
Mario
61950decb3 changelog 2023-05-20 09:27:31 +00:00
Mario
1a614ea023 instead of setting the value to 0 just continue so that already existing values will not be overwritten 2023-05-19 13:17:45 +00:00
Mario
a83b6a5e63 instead of setting the value to 0 just continue so that already existing values will not be overwritten 2023-05-19 13:16:53 +00:00
Mario
65d98af24c Merge branch '8.4RC' 2023-05-17 13:28:23 +00:00
Mario
62d35627f3 version 8.4 2023-05-17 13:28:05 +00:00
Mario
84f1ed1587 Merge branch 'dev' into 8.4RC 2023-05-17 13:26:01 +00:00
Mario
31b4fb343d changelog 2023-05-17 13:25:33 +00:00
Mario
3c3f5c60da changelog 2023-05-16 09:26:45 +00:00
Mario
18914f2081 Merge branch 'dev' into 8.4RC 2023-05-15 08:04:02 +00:00
Mario
b50da2d8b7 fix parent_mid and thr_parent not set correctly for response activities 2023-05-15 08:03:27 +00:00
Mario
5bdd699c9d Merge branch 'dev' into 8.4RC 2023-05-13 19:52:52 +00:00
Mario
29e8e6d95c fix parent and parent_mid for likes 2023-05-13 19:51:25 +00:00
Mario Vavti
049fc91615 Merge branch 'dev' into 8.4RC 2023-05-13 21:38:08 +02:00
Mario Vavti
b7c96f2cbd Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-05-13 21:37:45 +02:00
Mario Vavti
1e6408df13 fix regression decoding the uuid for responses 2023-05-13 21:37:33 +02:00
Mario
7b90548c1d save a query 2023-05-12 17:45:30 +00:00
Mario
5d330e18ff save a query 2023-05-12 16:29:42 +00:00
Mario
07662ff076 Merge branch 'dev' into 8.4RC 2023-05-12 08:02:19 +00:00
Mario
9252ae1596 css fixes 2023-05-12 08:01:25 +00:00
Mario
0155e9131d remove outdated comments 2023-05-11 12:51:25 +00:00
Mario
247cf40ace bump version 2023-05-10 20:45:33 +00:00
Mario
4a6b450c55 Merge branch 'dev' into 8.4RC 2023-05-10 20:44:43 +00:00
Mario
5b80d57a54 php warning 2023-05-10 20:40:10 +00:00
Mario
8ac4547e73 php warnings 2023-05-10 20:33:38 +00:00
Mario
3658975b69 typo 2023-05-10 20:22:18 +00:00
Mario
abc3545ef9 use act->objprop() in decode_note() 2023-05-10 20:11:54 +00:00
Mario
01f8cb698d check if we have a type and a href 2023-05-10 18:38:43 +00:00
Mario
5e4d0f45fc check if var is set and escape $ sign in ru translation 2023-05-10 16:43:00 +00:00
Mario
efd2f78274 check if var is set and escape $ sign in ru translation 2023-05-10 16:42:12 +00:00
Mario
690ff955fa Merge branch 'dev' into 8.4RC 2023-05-10 16:09:36 +00:00
Mario Vavti
3fb27bdc55 fix query for postgres 2023-05-10 18:04:19 +02:00
Mario
d8306fca6f Merge branch 'dev' into 8.4RC 2023-05-10 12:05:15 +00:00
Mario Vavti
380775540d missing function 2023-05-10 14:03:37 +02:00
Mario Vavti
65e3b0dafd deal with arrays and json 2023-05-10 13:53:03 +02:00
Mario
4ae81d753c Merge branch 'dev' into 8.4RC 2023-05-10 08:16:09 +00:00
Mario
0f01aac823 wording 2023-05-10 08:15:21 +00:00
Mario
ce0a96351e make sure we have a xchan and a hubloc - otherwise re-discover 2023-05-10 08:14:51 +00:00
Mario
93dda6f1fd Merge branch 'dev' into 8.4RC 2023-05-09 09:20:48 +00:00
Mario
5e83db959e more changelog 2023-05-09 09:20:21 +00:00
Mario
74436eb03e Merge branch 'dev' into 8.4RC 2023-05-09 09:08:06 +00:00
Mario
993178fc49 changelog 2023-05-09 09:07:32 +00:00
Mario
1c217cf446 es translation as per manuel 2023-05-09 07:58:41 +00:00
Mario
0bf2be1f9d Merge branch 'owa-compat-friendica' into 'dev'
Owa compatibility for Friendica

See merge request hubzilla/core!2036
2023-05-09 07:50:30 +00:00
Pascal Deklerck
548589be4d Owa compatibility for Friendica 2023-05-09 07:48:52 +00:00
Max Kostikov
697a1b1ed1 Merge branch 'dev' into 'dev'
Update Russian translation

See merge request hubzilla/core!2037
2023-05-08 12:44:18 +00:00
Max Kostikov
d893c7eb33 Update Russian hstrings.php 2023-05-08 12:42:17 +00:00
Max Kostikov
8957d24752 Update Russian hmessages.po 2023-05-08 12:41:46 +00:00
Mario
677e730235 Merge branch 'dev' into 8.4RC 2023-05-07 14:25:17 +00:00
Mario
4227d973b9 missing class 2023-05-07 14:24:59 +00:00
Mario
06c0af50c3 Merge branch 'dev' into 8.4RC 2023-05-07 12:48:14 +00:00
Mario
4d3a48d1c1 cropper fixup 2023-05-07 12:47:13 +00:00
Mario
f6b66f4cad Merge branch 'dev' into 8.4RC 2023-05-07 12:17:09 +00:00
Mario
a56f9ab4e6 more css and whitespace 2023-05-07 12:16:52 +00:00
Mario
ca913e5077 Merge branch 'dev' into 8.4RC 2023-05-07 12:04:54 +00:00
Mario
b25ebe12c5 more css 2023-05-07 12:03:42 +00:00
Mario
984980b170 version 2023-05-07 11:31:50 +00:00
Mario
be45005dbb css fixes 2023-05-07 11:29:45 +00:00
Mario
b8c9f04989 bump version 2023-05-07 09:04:10 +00:00
Mario
bf2d41eb14 composer autoload 2023-05-07 08:46:28 +00:00
Mario Vavti
158f9afb37 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-05-07 10:42:10 +02:00
Mario Vavti
f884e31d21 composer autoload 2023-05-07 10:41:57 +02:00
Mario
d3a5ff9d68 version and strings 2023-05-07 08:39:59 +00:00
Mario Vavti
7185780d4e h3 adds bottom margin - remove it 2023-05-07 10:30:34 +02:00
Mario Vavti
f995b2822f exclude deleted hublocs 2023-05-07 10:03:27 +02:00
Mario Vavti
d7490ac738 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-05-07 09:52:38 +02:00
Mario Vavti
383d0e17f2 fix directory search 2023-05-07 09:52:27 +02:00
Mario
7c1a3ab36e css fix 2023-05-07 07:11:54 +00:00
Mario
edc8d17031 slightly change online status display 2023-05-06 20:42:04 +00:00
Mario
f3f861234d minor css fix 2023-05-06 20:28:29 +00:00
Mario
93278c00b7 update profile vcard to implement the cover image 2023-05-06 19:41:02 +00:00
Mario
5bbe93d49f minor de strings update 2023-05-05 17:49:08 +00:00
Mario
21cd8d31d7 css fix 2023-05-05 17:46:53 +00:00
Mario
d649b4df28 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-05-05 16:10:12 +00:00
Mario
2bb9550343 slightly more robust get_quote_bbcode() 2023-05-05 16:09:53 +00:00
Mario Vavti
ef0feff4a5 Hidden > Spam 2023-05-05 12:33:39 +02:00
Mario
dfa43b4856 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-05-04 09:28:05 +00:00
Mario
a24a1ca6d7 update 1258 to remove traces of channelreputation 2023-05-04 09:27:31 +00:00
Mario Vavti
2d4b35fbc9 provide possibility to flag via ajax calls to prevent pageloads 2023-05-03 22:42:52 +02:00
Mario Vavti
57e2910477 flag new xtags with the xchan flag 2023-05-03 18:13:47 +02:00
Mario Vavti
ffbaa7e4dc when flagging an entry also flag its xtags and improved keywords query in dirsearch 2023-05-03 15:25:47 +02:00
Mario
df42036100 make sure config.system.trusted_directory_servers is an array 2023-05-03 08:47:21 +00:00
Mario Vavti
ca9491d343 move trusted directory servers to security and implement in backend 2023-04-29 22:43:49 +02:00
Mario
96ae569eaf trusted dir servers frontend 2023-04-29 19:38:34 +00:00
Mario Vavti
fb295d53f1 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-04-29 20:17:19 +02:00
Mario Vavti
95d07974f4 fix php warning 2023-04-29 20:13:52 +02:00
Mario
39d78064da Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-04-28 21:50:01 +00:00
Mario
a2bcbb90ed fix regression decoding obj type 2023-04-28 21:44:12 +00:00
Mario
c31b37f570 bootstrap files 2023-04-28 19:23:28 +00:00
Mario
2a1341b910 update bootstrap 2023-04-28 19:02:23 +00:00
Mario Vavti
354e341d69 mastodon says hashtag is a subset of link - issue #1750 2023-04-28 12:50:57 +02:00
Mario Vavti
13946b2b76 fix and document edge case 2023-04-28 10:03:05 +02:00
Mario Vavti
29aa52df6a fix poller after refactor 2023-04-28 09:29:15 +02:00
Mario Vavti
c3267a27d3 fix column name 2023-04-28 09:04:02 +02:00
Mario Vavti
3543e6dd32 slightly refactor dir sync 2023-04-28 08:57:21 +02:00
Mario Vavti
5412ba617d more dir sync testing 2023-04-28 00:58:46 +02:00
Mario Vavti
1f81a2cb1b remove updates entry if a xchan_hash mismatch is encountered 2023-04-27 22:54:45 +02:00
Mario Vavti
5da58d42f6 adjust args in libzotdir update and some dir sync fixes 2023-04-27 22:26:53 +02:00
Mario Vavti
299b6037c9 remove logging 2023-04-27 11:24:26 +02:00
Mario Vavti
1ed8b9dd14 fix php error 2023-04-27 11:17:53 +02:00
Mario Vavti
cf4912cb3d use shorter strings 2023-04-27 11:08:21 +02:00
Mario Vavti
e6ec87f910 update doco and fix safemode 2023-04-27 11:00:43 +02:00
Mario Vavti
f72fb974a9 for flag updates also match site directory and ud host 2023-04-27 07:07:38 +02:00
Mario Vavti
bdb25315b6 initial commit for directory flags federation 2023-04-26 23:01:56 +02:00
Mario
60f0739c3e update 1257 ud_guid > ud_host 2023-04-26 16:28:20 +00:00
Mario
0faab9277f fix update 2023-04-26 16:09:14 +00:00
Mario Vavti
51fce12cd7 update 1256 2023-04-26 17:59:20 +02:00
Mario Vavti
d79290df75 dirsync update column 2023-04-26 17:58:35 +02:00
Mario Vavti
0bf65bcad5 remove rate entry and move ignore button to the right 2023-04-26 13:46:25 +02:00
Mario Vavti
44dbf19e89 wrong variable 2023-04-26 12:59:04 +02:00
Mario Vavti
469a76f1f6 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-04-26 12:50:56 +02:00
Mario Vavti
f851c272fa enable dir admins to flag or hide entries 2023-04-26 12:50:37 +02:00
Mario
027a9fec61 fix potential security issue as per friendica 2023-04-26 06:28:24 +00:00
Mario
09fde2f839 correctly set some perms when our follow request was accepted 2023-04-25 08:36:20 +00:00
Mario
8a14e4261d check for uuid so that will be also catch items that were posted from alternate locations 2023-04-23 18:44:39 +00:00
Mario
6c9f1de265 remove logging 2023-04-23 18:05:17 +00:00
Mario
3ad0179b62 fix regression when rendering event items 2023-04-23 16:07:57 +00:00
Mario Vavti
81f33da499 improved fetch_conversation() 2023-04-23 13:02:38 +02:00
Mario
80d70e64f5 bump version 2023-04-23 09:26:30 +00:00
Mario
eec4845cd0 add the conversation endpoint and implement paginated fetch for zot requests in mod item 2023-04-23 09:23:39 +00:00
Mario
b99a4ade1a bump version 2023-04-21 10:39:17 +00:00
Mario
84e25e8fd2 Fetch conversations in the background. Otherwise it might sgnificantly delay delivery 2023-04-21 10:34:55 +00:00
Mario
39e14eb95c hotfix: make sure to not pass an empty path to fopen() 2023-04-21 10:33:05 +00:00
Mario
f277d08244 queue and poller testing 2023-04-21 07:45:32 +00:00
Mario
d7c479fa6d % values in format_poll() should be rounded 2023-04-19 11:01:49 +00:00
Mario Vavti
44e5dc7d97 bump version 2023-04-19 11:14:46 +02:00
Mario Vavti
fdd54057a8 also return deleted channels info in webfinger and document why 2023-04-19 11:12:35 +02:00
Mario Vavti
d43485141f use empty for check 2023-04-16 20:12:04 +02:00
Mario Vavti
2350561903 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-04-16 17:13:00 +02:00
Mario Vavti
5674badccd improved update_directory_entry(), update ud_last even if webfinger failed 2023-04-16 17:12:49 +02:00
Mario
a793f4414d fix php warning 2023-04-16 13:47:48 +00:00
Mario
e99957f99f fix php warning 2023-04-16 11:20:02 +00:00
Mario
ad5bbc463b fix wrong variable 2023-04-16 10:59:26 +00:00
Mario
81993cf2a3 cleanup 2023-04-15 15:15:55 +00:00
Mario
5d40742ee6 fix wrong variable 2023-04-15 07:53:30 +00:00
Mario
1ce050d911 update es strings as per Manuel 2023-04-14 19:02:37 +00:00
Mario
8e7393fc26 update it string as per Giaco 2023-04-14 18:55:45 +00:00
Mario Vavti
ad45205ddf this has been moved to cron for now 2023-04-14 10:45:01 +02:00
Mario Vavti
409e9208ee Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-04-14 09:21:46 +02:00
Mario Vavti
d8811b499d improved item_expire() 2023-04-14 09:21:33 +02:00
Mario
dd1f9494f1 css fix 2023-04-14 06:04:44 +00:00
Mario Vavti
20f4538db4 update remove_all_xchan_resources() and remove deletion of deprecated conv table 2023-04-13 22:28:08 +02:00
Mario Vavti
d08c8e6edc Revert "zot_info(): improved check for deleted"
This reverts commit f1667dbbe6.
2023-04-13 21:50:13 +02:00
Mario Vavti
f1667dbbe6 zot_info(): improved check for deleted 2023-04-13 21:25:03 +02:00
Mario Vavti
2bab7e2693 prevent duplicate definitions 2023-04-13 18:51:13 +02:00
Mario Vavti
824497b97a fix wrong array key, check for xchan_deleted with empty() which will also catch a possibly already removed xchan (which will be null) and bump version 2023-04-13 11:37:01 +02:00
Mario Vavti
0b7bece8e3 remove pre zot6 compatibility tweaks 2023-04-13 11:01:57 +02:00
Mario Vavti
6ddf1a5786 update zotinfo to use as much info as possible from channel since in some cases the xchan might be history already 2023-04-13 10:45:36 +02:00
Mario Vavti
b9827dfe02 move colon to the variable 2023-04-12 23:11:02 +02:00
Mario Vavti
64f30831ac rename update_modtime() to update() and only bump ud_date if something actually changed 2023-04-12 23:07:19 +02:00
Mario Vavti
bf5722cd25 always call update_modtime() foer now; 2023-04-12 19:07:28 +02:00
Mario Vavti
ae074153c8 remouve updates stuff from import_directory_profile() 2023-04-12 18:40:51 +02:00
Mario Vavti
63d46dbdfb more logging 2023-04-12 18:27:04 +02:00
Mario Vavti
bdf1b23198 reset ud_last if we had contact and some cleanup 2023-04-12 18:24:44 +02:00
Mario Vavti
6f1c261f6b deprecate ud_flags and ud_arr in import_xchan() 2023-04-12 18:01:35 +02:00
Mario Vavti
3233d5485f Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-04-12 17:51:09 +02:00
Mario Vavti
aa06400a50 deprecate flags and transaction_id and only return results which are currently updated 2023-04-12 17:50:39 +02:00
Mario
30724bd7c4 update updates if anything changed 2023-04-12 15:35:21 +00:00
Mario Vavti
0d3b389538 fix php warning 2023-04-12 13:35:41 +02:00
Mario Vavti
9f7dbe16fd adjust check 2023-04-12 13:21:26 +02:00
Mario Vavti
432024123a update updates if we are provided an ud_arr or we imported a new xchan 2023-04-12 13:17:23 +02:00
Mario Vavti
261762448e use url instead of addr for updates and clean up local_dir_update() and update_modtime() 2023-04-12 11:36:34 +02:00
Mario Vavti
7ce4175876 initial commit directory sync rewrite - should work but still requires lots of cleanup 2023-04-12 09:29:51 +02:00
Mario
a57739c462 Merge branch 'dev' 2023-04-09 20:01:22 +00:00
Mario
03bdbfa705 set ud_last after successfully probing a channel 2023-04-09 20:00:54 +00:00
Mario
92246ce3a8 Merge branch 'dev' 2023-04-09 19:53:27 +00:00
Mario
cdf74c2e41 Revert "make sure to update ud_last timestamp if we successfully fingered a channel"
This reverts commit f76d9b7908.
2023-04-09 19:52:54 +00:00
Mario
4a72ea6666 Merge branch 'dev' 2023-04-09 19:45:04 +00:00
Mario
f76d9b7908 make sure to update ud_last timestamp if we successfully fingered a channel 2023-04-09 19:44:35 +00:00
Mario
dcfdf3a5d7 Merge branch 'dev' 2023-04-09 19:02:36 +00:00
Mario
4873f61d6c disable thread listener interface by default and minor fixes 2023-04-09 18:51:55 +00:00
Mario
1538107ae4 minor queueworker fixes 2023-04-08 20:25:31 +00:00
Mario
9b93dc5137 split up a potentially long running sql query 2023-04-08 20:18:17 +00:00
Mario Vavti
5ec721b978 likes not synced between clones 2023-03-31 09:31:28 +02:00
Mario
24568c0e2f add some explanation and remove logging 2023-03-30 13:23:16 +00:00
Mario
92a89ca258 version 8.3.1 2023-03-30 13:10:47 +00:00
Mario
ba71c53bc6 ignore deliveries by our own channel which do not origin from the local hub. instead rely on the sync delivery. 2023-03-30 12:08:43 +00:00
Mario Vavti
b3cfeb573a do not add not_here, anon, token and rss contacts to receivers 2023-03-29 21:46:28 +02:00
Mario
9083e99d2a in fact this can be removed
(cherry picked from commit 70ca247c88)
2023-03-24 10:29:09 +01:00
Mario
70ca247c88 in fact this can be removed 2023-03-24 09:22:10 +00:00
Mario
14fc0c735b encode object after we have dealt with deleted items and work around a php error
(cherry picked from commit 70b3c8080e)
2023-03-24 10:05:37 +01:00
Mario
70b3c8080e encode object after we have dealt with deleted items and work around a php error 2023-03-24 09:01:06 +00:00
Mario
2c483c460a initial check in to allow all mentions option 2023-03-23 20:11:18 +00:00
Mario
79405cf1d3 Merge branch 'dev' 2023-03-21 09:20:57 +00:00
Mario
5c755fdd1c PHP 8.1 is the required minimum version 2023-03-21 09:20:22 +00:00
1645 changed files with 139299 additions and 71076 deletions

158
.debianinstall/README.md Normal file
View File

@@ -0,0 +1,158 @@
# How to use
## Disclaimers
- **This script does work with a fresh install of Debian 12 only**.
- Do not use if you have already installed and configured a webserver or sql server that was not installed by this script.
### Keep it Simple and Stupid
The script keeps everything as simple as possible (KISS):
- Apache as webserver (there is no choice to use another webserver like nginx)
- default PHP version of Debian
- one single Hubzilla intance only
- re-running the script does no harm
### When to use other Scripts
Use the scripts under [homeinstall](https://framagit.org/hubzilla/core/-/tree/master/.homeinstall)
if you look for more choices. The main differences are:
- Apache or nginx as webserver
- install multiple instances (domains) that run side by side on the server
- adds apache vhosts (instead of using the standard doc root /var/www/html)
- install PHP from https://packages.sury.org/php/ (instead of using the Debian repository)
- graphical installer whiptail
- The script stops (fails) if it finds results of a previous installation. (The [debian-setup.sh](https://framagit.org/ojrandom/core/-/tree/dev/.debianinstall) will just jump over it.)
- If something fails the script tries to clean up everything that was installed up to the point of failure. (That might cause trouble if certbot registered a certificate already.)
- The script under [homeinstall](https://framagit.org/hubzilla/core/-/tree/master/.homeinstall) seems to be an older version of the scripts used for Streams
+ [autoinstall](https://codeberg.org/streams/streams/src/branch/dev/contrib/autoinstall)
+ [easyinstall](https://codeberg.org/streams/streams/src/branch/dev/contrib/easyinstall)
## Preconditions
Hardware
+ internet connection and router at home
+ computer connected to your router (a Raspberry 3 will do for very small Hubs)
Software
+ fresh installation of Debian 12 (bookworm)
+ router with open ports 80 and 443 for your web server
You can of course run the script on a VPS or any distant server as long as the above sotfware requirements are satisfied.
## How to run the script
+ Register your own domain (for example at selfHOST) or a free subdomain (for example at freeDNS)
+ Log on to your fresh Debian
- apt-get install git
- mkdir -p /var/www
- cd /var/www
- git clone https://framagit.org/hubzilla/core.git html
- cd html/.debianinstall
- cp config.txt.template config.txt
- nano config.txt
- read the comments carefully
- enter your values: db pass, domain
- (optionally) Enter your values for dyn DNS
- ./debian-setup.sh as root
- ... wait, wait, wait until the script is finished
+ Open your domain with a browser and step throught the initial configuration of your hubzilla instance.
- default database name = hubzilla
- default dababase user = hubzilla
## Optional - Switch verification of email on/off
Do this just before you register the first user without email verification.
In a terminal
su -
cd /var/www/html
Check the current setting
util/config system verify_email
Switch the verification off
util/config system verify_email 0
## What the script will do for you...
+ install everything required by your hubzilla instance, basically a web server (Apache), PHP, a database (MySQL), certbot,...
+ create a database
+ run certbot to have everything for a secure connection (httpS)
+ create a script for daily maintenance
- renew certfificate (letsencrypt)
- update of your hubzilla instance for core and addons (git)
- update of Debian
- restart
+ create cron jobs for
- DynDNS (selfHOST.de or freedns.afraid.org) every 5 minutes
- Master.php for your hubzilla instance every 10 minutes
- daily maintenance script every day at 05:30
The script is known to work without adjustments with
+ Hardware
- standard PC with Debian 12 (bookworm)
- Raspberry 4 with Raspbian, Debian 12 (TODO: needs confirmation after swich to Debian12)
- for tesing purposes: under localhost inside a virtual machine, [KVM](https://wiki.debian.org/KVM)
+ DynDNS
- selfHOST.de
- freedns.afraid.org
# Step-by-Step - some Details
## Preparations
## Configure your Router
Your webserver has to be visible in the internet.
Open the ports 80 and 443 on your router for your Debian. Make sure your web server is marked as "exposed host".
## Preparations Dynamic IP Address
Follow the instructions in .debianinstall/config.txt.
In short...
Your Hubzilla server must be reachable by a domain that you can type in your browser
cooldomain.org
You can use subdomains as well
my.cooldomain.org
There are two ways to get a domain...
### Method 1: Buy a Domain
...for example buy at selfHOST.de
The cost is 1,50 € per month (2019).
### Method 2: Register a free subdomain
...for example register at freedns.afraid.org
## Note on Rasperry
It is recommended to run the Raspi without graphical frontend (X-Server). Use...
sudo raspi-config
to boot the Rapsi to the client console.
DO NOT FORGET TO CHANGE THE DEFAULT PASSWORD FOR USER PI!
## Reminder for Different Web Wervers
For those of you who feel adventurous enough to use a different web server (i.e. Lighttpd...), don't forget that this script will install Apache or Nginx and that you can only have one web server listening to ports 80 & 443. Also, don't forget to tweak your daily shell script in /var/www/ accordingly.

View File

@@ -0,0 +1,111 @@
###############################################
### MANDATORY - database password #############
#
# Please give your database password
# It is better to not use blanks inside the password.
# Example: db_pass=pass_word_with_no_blanks_in_it
db_pass=
###############################################
### MANDATORY - let's encrypt #################
#
# Zot requires encrypted communication via secure HTTP (HTTPS).
# This script automates installation of an SSL certificate from
# Let's Encrypt (https://letsencrypt.org)
#
# Please give the domain name of your hub/instance
#
# Example: my.cooldomain.org
# Example: cooldomain.org
#
# You might use "localhost" for a LOCAL TEST installation.
# This is usefull if you want to debug the server inside a VM.
#
# Example: localhost
#
# Email is optional if you use "localhost".
#
#
le_domain=
le_email=
###############################################
### OPTIONAL - selfHOST - dynamic IP address ##
#
# 1. Register a domain at selfhost.de
# - choose offer "DOMAIN dynamisch" 1,50€/mon at 04/2019
# 2. Get your configuration for dynamic IP update
# - Log in at selfhost.de
# - go to "DynDNS Accounte"
# - klick "Details" of your (freshly) registered domain
# - You will find the configuration there
# - Benutzername (user name) > use this for "selfhost_user="
# - Passwort (pass word) > use this for "selfhost_pass="
#
#
selfhost_user=
selfhost_pass=
###############################################
### OPTIONAL - FreeDNS - dynamic IP address ###
#
# Please give the alpha-numeric-key of freedns
#
# Get a free subdomain from freedns and use it for your dynamic ip address
# Documentation under http://www.techjawab.com/2013/06/setup-dynamic-dns-dyndns-for-free-on.html
#
# - Register for a Free domain at http://freedns.afraid.org/signup/
# - WATCH THIS: Make sure you choose a domain with as less subdomains as
# possible. Why? Let's encrpyt issues a limited count of certificates each
# day. Possible other users of this domain will try to issue a certificate
# at the same day.
# - Logon to FreeDNS (where you just registered)
# - Goto http://freedns.afraid.org/dynamic/
# - Right click on "Direct Link" and copy the URL and paste it somewhere.
# - You should notice a large and unique alpha-numeric key in the URL
#
# http://freedns.afraid.org/dynamic/update.php?alpha-numeric-key
#
# Provided your url from freedns is
#
# http://freedns.afraid.org/dynamic/update.php?U1Z6aGt2R0NzMFNPNWRjbWxxZGpsd093OjE1Mzg5NDE5
#
# Then you have to provide
#
# freedns_key=U1Z6aGt2R0NzMFNPNWRjbWxxZGpsd093OjE1Mzg5NDE5
#
#
freedns_key=
###############################################
### OPTIONAL - do not mess with things below ##
# (...if you are not certain)
#
# Usually you are done here
# Everything below is OPTIONAL
#
###############################################
#
# Database for your hub/instance
# If left empty, both your database and user will be named after your zot instance (hubzilla, zap or misty)
# Use custom name, at least fo the database, if you plan to run more than one hub/instance on the same server
#
zotserver_db_name=
zotserver_db_user=
zotserver_db_pass=$db_pass
#
#
# Password for package mysql-server
# Example: mysqlpass=aberhallo
# Example: mysqlpass="aber hallo has blanks in it"
#
mysqlpass=$db_pass
# Password for package phpmyadmin
# Example: phpmyadminpass=aberhallo
# Example: phpmyadminpass="aber hallo has blanks in it"
phpmyadminpass=$db_pass

View File

@@ -0,0 +1,527 @@
#!/bin/bash
#
# How to use
# ----------
#
# This file automates the installation of hubzilla: https://framagit.org/hubzilla/core
# under Debian Linux "bookworm"
#
# 1) Copy the file "config.txt.template" to "config.txt"
# Follow the instuctions there
#
# 2) Switch to user "root" by typing "su -"
#
# 3) Run with "./debian-setup.sh"
# If this fails check if you can execute the script.
# - To make it executable type "chmod +x debian-setup.sh"
# - or run "bash debian-setup.sh"
#
#
# What does this script do basically?
# -----------------------------------
#
# This file automates the installation of a Hubzilla instance under Debian Linux
# - install
# * apache webserver,
# * php,
# * mariadb,
# * adminer,
# * addons
# - configure cron
# * "Master.php" for regular background processes of your hubzilla instance
# * "apt-get update" and "apt-get dist-upgrade" and "apt-get autoremove" to keep linux up-to-date
# * run command to keep the IP up-to-date > DynDNS provided by selfHOST.de or freedns.afraid.org
# - run letsencrypt to create, register and use a certifacte for https
#
#
# Credits
# -------
#
# The script is derived from the easyinstall script of the Streams repository, which is based on
# - Tom Wiedenhöfts (OJ Random) script homeinstall (for Hubzilla, ZAP,...) that was based on
# - Thomas Willinghams script "debian-setup.sh" which he used to install the red#matrix.
function check_sanity {
# Do some sanity checking.
print_info "Sanity check..."
if [ $(/usr/bin/id -u) != "0" ]
then
die 'Must be run by root user'
fi
if [ -f /etc/lsb-release ]
then
die "Distribution is not supported"
fi
if [ ! -f /etc/debian_version ]
then
die "Debian is supported only"
fi
if ! grep -q 'Linux 12' /etc/issue
then
die "Linux 12 (bookworm) is supported only"x
fi
}
function check_config {
print_info "config check..."
# Check for required parameters
if [ -z "$db_pass" ]
then
die "db_pass not set in $configfile"
fi
if [ -z "$le_domain" ]
then
die "le_domain not set in $configfile"
fi
}
function die {
echo "ERROR: $1" > /dev/null 1>&2
exit 1
}
function update_upgrade {
print_info "updated and upgrade..."
# Run through the apt-get update/upgrade first. This should be done before
# we try to install any package
apt-get -q -y update && apt-get -q -y dist-upgrade && apt-get -q -y autoremove
print_info "updated and upgraded linux"
}
function nocheck_install {
# export DEBIAN_FRONTEND=noninteractive ... answers from the package configuration database
# - q ... without progress information
# - y ... answer interactive questions with "yes"
# DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -q -y install $2
# DEBIAN_FRONTEND=noninteractive apt-get --install-suggests -q -y install $1
DEBIAN_FRONTEND=noninteractive apt-get -q -y install $1
print_info "installed $1"
}
function print_info {
echo -n -e '\e[1;34m'
echo -n $1
echo -e '\e[0m'
}
function print_warn {
echo -n -e '\e[1;31m'
echo -n $1
echo -e '\e[0m'
}
function stop_zotserver {
print_info "stopping apache..."
systemctl stop apache2
print_info "stopping mysql db..."
systemctl stop mariadb
}
function install_apache {
print_info "installing apache..."
nocheck_install "apache2 apache2-utils"
a2enmod rewrite
systemctl restart apache2
}
function install_imagemagick {
print_info "installing imagemagick..."
nocheck_install "imagemagick"
}
function install_curl {
print_info "installing curl..."
nocheck_install "curl"
}
function install_wget {
print_info "installing wget..."
nocheck_install "wget"
}
function install_sendmail {
print_info "installing sendmail..."
nocheck_install "sendmail sendmail-bin"
}
function install_php {
# openssl and mbstring are included in libapache2-mod-php
print_info "installing php..."
nocheck_install "libapache2-mod-php php php-pear php-curl php-gd php-mbstring php-xml php-zip"
phpversion=$(php -v|grep --only-matching --perl-regexp "(PHP )\d+\.\\d+\.\\d+"|cut -c 5-7)
sed -i "s/^upload_max_filesize =.*/upload_max_filesize = 100M/g" /etc/php/$phpversion/apache2/php.ini
sed -i "s/^post_max_size =.*/post_max_size = 100M/g" /etc/php/$phpversion/apache2/php.ini
}
function install_composer {
print_info "We check if Composer is already downloaded"
if [ ! -f /usr/local/bin/composer ]
then
EXPECTED_CHECKSUM="$(php -r 'copy("https://composer.github.io/installer.sig", "php://stdout");')"
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
then
>&2 echo 'ERROR: Invalid installer checksum'
rm composer-setup.php
die 'ERROR: Invalid installer checksum'
fi
php composer-setup.php --quiet
RESULT=$?
rm composer-setup.php
# exit $RESULT
# We install Composer globally
mv composer.phar /usr/local/bin/composer
print_info "Composer was successfully downloaded."
else
print_info "Composer is already downloaded on this system."
fi
cd $install_path
export COMPOSER_ALLOW_SUPERUSER=1;
/usr/local/bin/composer install --no-dev
/usr/local/bin/composer show
export COMPOSER_ALLOW_SUPERUSER=0;
}
function install_mysql {
print_info "installing mysql..."
if [ -z "$mysqlpass" ]
then
die "mysqlpass not set in $configfile"
fi
if type mysql ; then
echo "Yes, mysql is installed"
else
echo "mariadb-server"
nocheck_install "mariadb-server"
systemctl status mariadb
systemctl start mariadb
mysql --user=root <<_EOF_
UPDATE mysql.user SET Password=PASSWORD('${mysqlpass}') WHERE User='root';
DELETE FROM mysql.user WHERE User='';
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
FLUSH PRIVILEGES;
_EOF_
fi
}
function install_adminer {
print_info "installing adminer..."
nocheck_install "adminer"
if [ ! -f /etc/adminer/adminer.conf ]
then
echo "Alias /adminer /usr/share/adminer/adminer" > /etc/adminer/adminer.conf
ln -s /etc/adminer/adminer.conf /etc/apache2/conf-available/adminer.conf
else
print_info "file /etc/adminer/adminer.conf exists already"
fi
a2enmod rewrite
if [ ! -f /etc/apache2/apache2.conf ]
then
die "could not find file /etc/apache2/apache2.conf"
fi
sed -i \
"s/AllowOverride None/AllowOverride all/" \
/etc/apache2/apache2.conf
a2enconf adminer
systemctl restart mariadb
systemctl reload apache2
}
function create_zotserver_db {
print_info "creating zotserver database..."
if [ -z "$db_name" ]
then
die "db_name not set in $configfile"
fi
if [ -z "$db_user" ]
then
die "db_user not set in $configfile"
fi
if [ -z "$db_pass" ]
then
die "db_pass not set in $configfile"
fi
systemctl restart mariadb
# Make sure we don't write over an already existing database if we install more than one Zot hub/instance
if [ -z $(mysql -h localhost -u root -p$mysqlpass -e "SHOW DATABASES;" | grep $db_name) ]
then
Q1="CREATE DATABASE IF NOT EXISTS $db_name;"
Q2="GRANT USAGE ON *.* TO $db_user@localhost IDENTIFIED BY '$db_pass';"
Q3="GRANT ALL PRIVILEGES ON $name.* to $db_user@localhost identified by '$db_pass';"
Q4="FLUSH PRIVILEGES;"
SQL="${Q1}${Q2}${Q3}${Q4}"
mysql -uroot -p$mysqlpass -e "$SQL"
else
echo "database $db_name does exist already"
fi
}
function run_freedns {
print_info "run freedns (dynamic IP)..."
if [ -z "$freedns_key" ]
then
print_info "freedns was not started because 'freedns_key' is empty in $configfile"
else
if [ -n "$selfhost_user" ]
then
die "You can not use freeDNS AND selfHOST for dynamic IP updates ('freedns_key' AND 'selfhost_user' set in $configfile)"
fi
wget --no-check-certificate -O - http://freedns.afraid.org/dynamic/update.php?$freedns_key
fi
}
function install_run_selfhost {
print_info "install and start selfhost (dynamic IP)..."
if [ -z "$selfhost_user" ]
then
print_info "selfHOST was not started because 'selfhost_user' is empty in $configfile"
else
if [ -n "$freedns_key" ]
then
die "You can not use freeDNS AND selfHOST for dynamic IP updates ('freedns_key' AND 'selfhost_user' set in $configfile)"
fi
if [ -z "$selfhost_pass" ]
then
die "selfHOST was not started because 'selfhost_pass' is empty in $configfile"
fi
if [ ! -d $selfhostdir ]
then
mkdir $selfhostdir
fi
# the old way
# https://carol.selfhost.de/update?username=123456&password=supersafe
#
# the prefered way
wget --output-document=$selfhostdir/$selfhostscript http://jonaspasche.de/selfhost-updater
echo "router" > $selfhostdir/device
echo "$selfhost_user" > $selfhostdir/user
echo "$selfhost_pass" > $selfhostdir/pass
bash $selfhostdir/$selfhostscript update
fi
}
function ping_domain {
print_info "ping domain $domain..."
# Is the domain resolved? Try to ping 6 times à 10 seconds
COUNTER=0
for i in {1..6}
do
print_info "loop $i for ping -c 1 $domain ..."
if ping -c 4 -W 1 $le_domain
then
print_info "$le_domain resolved"
break
else
if [ $i -gt 5 ]
then
die "Failed to: ping -c 1 $domain not resolved"
fi
fi
sleep 10
done
sleep 5
}
function configure_cron_freedns {
print_info "configure cron for freedns..."
if [ -z "$freedns_key" ]
then
print_info "freedns is not configured because freedns_key is empty in $configfile"
else
# Use cron for dynamich ip update
# - at reboot
# - every 30 minutes
if [ -z "`grep 'freedns.afraid.org' /etc/crontab`" ]
then
echo "@reboot root http://freedns.afraid.org/dynamic/update.php?$freedns_key > /dev/null 2>&1" >> /etc/crontab
echo "*/30 * * * * root wget --no-check-certificate -O - http://freedns.afraid.org/dynamic/update.php?$freedns_key > /dev/null 2>&1" >> /etc/crontab
else
print_info "cron for freedns was configured already"
fi
fi
}
function configure_cron_selfhost {
print_info "configure cron for selfhost..."
if [ -z "$selfhost_user" ]
then
print_info "selfhost is not configured because selfhost_key is empty in $configfile"
else
# Use cron for dynamich ip update
# - at reboot
# - every 5 minutes
if [ -z "`grep 'selfhost-updater.sh' /etc/crontab`" ]
then
echo "@reboot root bash /etc/selfhost/selfhost-updater.sh update > /dev/null 2>&1" >> /etc/crontab
echo "*/5 * * * * root /bin/bash /etc/selfhost/selfhost-updater.sh update > /dev/null 2>&1" >> /etc/crontab
else
print_info "cron for selfhost was configured already"
fi
fi
}
function install_letsencrypt {
print_info "installing let's encrypt ..."
# check if user gave domain
if [ -z "$le_domain" ]
then
die "Failed to install let's encrypt: 'le_domain' is empty in $configfile"
fi
if [ -z "$le_email" ]
then
die "Failed to install let's encrypt: 'le_email' is empty in $configfile"
fi
nocheck_install "certbot python-certbot-apache"
print_info "run certbot ..."
certbot --apache -w $install_path -d $le_domain -m $le_email --agree-tos --non-interactive --redirect --hsts --uir
service apache2 restart
}
function check_https {
print_info "checking httpS > testing ..."
url_https=https://$le_domain
wget_output=$(wget -nv --spider --max-redirect 0 $url_https)
if [ $? -ne 0 ]
then
print_warn "check not ok"
else
print_info "check ok"
fi
}
function install_zotserver {
print_info "installing addons..."
cd $install_path
util/add_addon_repo https://framagit.org/hubzilla/addons hzaddons
mkdir -p "store/[data]/smarty3"
# chmod -R 777 store
touch .htconfig.php
# The next run of $cron_job (daily-update script) will correct the permissions of the next line
chmod ou+w .htconfig.php
cd /var/www/
chown -R www-data:www-data $install_path
chown root:www-data $install_path/
chown root:www-data $install_path/.htaccess
chmod 0644 $install_path/.htaccess
print_info "installed addons"
}
function configure_cron_daily {
print_info "configuring cron..."
# every 10 min for poller.php
if [ -z "`grep 'php Zotlabs/Daemon/Master.php' /etc/crontab`" ]
then
echo "*/10 * * * * www-data cd $install_path; php Zotlabs/Daemon/Master.php Cron >> /dev/null 2>&1" >> /etc/crontab
fi
# Run external script daily at 05:30
# - stop apache/nginx and mysql-server
# - renew the certificate of letsencrypt
# - update repository core and addon
# - update and upgrade linux
# - reboot is done by "shutdown -h now" because "reboot" hangs sometimes depending on the system
echo "#!/bin/sh" > /var/www/$cron_job
echo "#" >> /var/www/$cron_job
echo "echo \" \"" >> /var/www/$cron_job
echo "echo \"+++ \$(date) +++\"" >> /var/www/$cron_job
echo "echo \" \"" >> /var/www/$cron_job
echo "echo \"\$(date) - stopping apache and mysql...\"" >> /var/www/$cron_job
echo "service apache2 stop" >> /var/www/$cron_job
echo "/etc/init.d/mysql stop # to avoid inconsistencies" >> /var/www/$cron_job
echo "#" >> /var/www/$cron_job
echo "echo \"\$(date) - renew certificate...\"" >> /var/www/$cron_job
echo "certbot renew --noninteractive" >> /var/www/$cron_job
echo "#" >> /var/www/$cron_job
echo "echo \"\$(date) - db size...\"" >> /var/www/$cron_job
echo "du -h /var/lib/mysql/ | grep mysql/" >> /var/www/$cron_job
echo "#" >> /var/www/$cron_job
echo "# update of $le_domain Zot hub/instance" >> /var/www/$cron_job
echo "echo \"\$(date) - updating core and addons...\"" >> /var/www/$cron_job
echo "echo \"reaching git repository for $le_domain $zotserver hub/instance...\"" >> /var/www/$cron_job
echo "(cd $install_path ; util/udall)" >> /var/www/$cron_job
echo "chown -R www-data:www-data $install_path # make all accessible for the webserver" >> /var/www/$cron_job
echo "chown root:www-data $install_path/.htaccess" >> /var/www/$cron_job
echo "chmod 0644 $install_path/.htaccess # www-data can read but not write it" >> /var/www/$cron_job
echo "echo \"\$(date) - updating linux...\"" >> /var/www/$cron_job
echo "apt-get -q -y update && apt-get -q -y dist-upgrade && apt-get -q -y autoremove # update linux and upgrade" >> /var/www/$cron_job
echo "echo \"\$(date) - Update finished. Rebooting...\"" >> /var/www/$cron_job
echo "#" >> /var/www/$cron_job
echo "shutdown -r now" >> /var/www/$cron_job
chmod a+x /var/www/$cron_job
# If global cron job does not exist we add it to /etc/crontab
if grep -q $cron_job /etc/crontab
then
echo "cron job already in /etc/crontab"
else
echo "30 05 * * * root /bin/bash /var/www/$cron_job >> /var/www/daily-updates.log 2>&1" >> /etc/crontab
echo "0 0 1 * * root rm /var/www/daily-updates.log" >> /etc/crontab
fi
# This is active after either "reboot" or cron reload"
systemctl restart cron
print_info "configured cron for updates/upgrades"
}
########################################################################
# START OF PROGRAM
########################################################################
export PATH=/bin:/usr/bin:/sbin:/usr/sbin
check_sanity
print_info "We're installing a $zotserver instance"
install_path="$(dirname "$(pwd)")"
# Read config file edited by user
configfile=config.txt
source $configfile
selfhostdir=/etc/selfhost
selfhostscript=selfhost-updater.sh
cron_job="cron_job.sh"
#set -x # activate debugging from here
zotserver=hubzilla
check_config
stop_zotserver
update_upgrade
install_curl
install_wget
install_sendmail
install_apache
install_imagemagick
install_php
install_composer
install_mysql
install_adminer
create_zotserver_db
run_freedns
install_run_selfhost
ping_domain
configure_cron_freedns
configure_cron_selfhost
if [ "$le_domain" != "localhost" ]
then
install_letsencrypt
check_https
else
print_info "is localhost - skipped installation of letsencrypt and configuration of apache for https"
fi
install_zotserver
configure_cron_daily
#set +x # stop debugging from here

View File

@@ -42,7 +42,6 @@ before_script:
- docker-php-ext-enable xdebug
- docker-php-ext-install gd
# Install composer
- curl -sS https://getcomposer.org/installer | php
# Install dev libraries from composer

200
CHANGELOG
View File

@@ -1,3 +1,203 @@
Hubzilla 8.8 (2023-11-25)
- Add additional observer and channel info for nav templates
- Do not provide confidential channel info for templates
- Add link to profile to vcard
- Improved switch colors for better visibility
- Raise cache.v column from text to mediumtext for MYSQL
- Implement low level support for native repeats
- Color mode related code moved to theme_init.php in redbasic
- Do not overrule default list style when parsing bbcode
- Introduce Activity::get_actor() which will check for the cache record in xconfig before fetching
- Refactor Activity::actor_store()
- Use new language detect library which supports many more languages
- Use Activity::encode_person() instead of plain xchan_url to set attributedTo
- Update composer libraries
- Move right aside into bottom of left aside if screen width is < 1200px in redbasic
- When parsing events, use event object in first place and use the body bbcode as backup
- Make OWA compatible with mastodon style keyId
- Add sourced item events to the channel calendar
- Make activity filter widget portable to other modules
- Deprecate remains of the unused $a variable which has been replaced by the App class ages ago
- Return object instead of json string in the custom jsonld document loader
- Only show theme switch icon if switching is supported by the theme
- Store the actor cache date with the actor record so we can easily invalidate it after a period of time
- Allow themes to manipulate app icons (photos) via hook
- Also look for widgets in view/theme/themename/widget
- Cache seen pubstream item mids so that they can be hidden from notifications
- Theme fixes to make barebones bootstrap themes work slightly better
- Update Norwegian Bokmål strings
- Update Spanish strings
- Transparent background for colorbox controls icons
- Use body background color for colorboxes in redbasic
Bugfixes
- Remove fragment from actor urls
- HTTPsig case insensitive digest algorithm
- Fix possible privacy mismatch when processing zot requests
- Fix @someone in URL turned into mention in some situations - issue #1816
- Fix fatal error in simplepie with PHP8.2
- Fix tools visible allthough permission has been revoked for observer in files app
- Fix updates entry not removed if a channel was removed
- Fix form reset button not visible in mod rpost
- Fix missing columns for updates table in install script
- Fix for item widget not respecting ACL if added by title - issue #1799
- Fix sabre/dav caldav php warnings
- Fix public stream comments/reactions not allowed if item_fetched is set
Addons
- Superblock: fix php warnings
- Pubcrawl: restrict mod ap_probe to admin and add checkbox for signed requests
- Wiki: fix wiki_list widget not registered
- Deprecate remains of the unused $a variable which has been replaced by the App class ages ago
- Pubcrawl: reflect core delivery changes for repeated items
- Cart fix regression
- Logger_stats: new addon for admins to track hub activities
- Pubcrawl: check if we have the record in the short term cache before actually fetching it
- Pubcrawl: reflect core changes to Activity::actor_store()
- Gallery: update to photoswipe 5
- Pubcrawl: some platforms are sending activities without an object - return error 400
- HSSE: update sce-editor to latest version
- SSE: sse: do not process items that are older than last login date or in case we are not logged in older than 10 minutes
- Faces: new addon for face recognision in uploaded photos
Hubzilla 8.6.3 (2023-09-16)
- Fix regression in jsonld_document_loader()
- Improve type checking for announce activities
- Improve query in drop_item() to prevent possible memory exhaustion
- Addon gallery: only add gallery code if the module is supported
- Addon hsse: port to bootstrap 5 namespaces - core issue #1793
Hubzilla 8.6.2 (2023-08-27)
- Fix public stream comments/reactions fetching
- Fix notification text for likes in cases where obj.actor is not set
- Fix missing pdl file for mod cover_photo
- Fix unable to create folders with name 0
- Fix index name mixup in mysql schema file
- Fix missing semicolon in mysql schema file
- Removed unused variable
- Fix typo in manifest
- Fix cached jsonld files fetched via network
- Page rendering performance improvements
- Fix internal follow activity possibly creating notification items
- Fix admin table highlight color for dark mode
- Pubcrawl: do not handle not implemented listen activity
- Diaspora: fix unshare not implemented
Hubzilla 8.6.1 (2023-07-18)
- Fix diaspora discovery
Hubzilla 8.6 (2023-07-11)
- Update fullcalendar library
- Improve and unify selection of deliverable abook xchans
- Remove unused pseudo_abook()
- Implement optional moderation for unsolicited items
- Hardened comment permission handling for unsolicited items
- Remove unused templates
- Deprecate ActivityStreams::fetch() and provide the possibility to fetch local items directly
- Add simplified version of automated install script
- Shuffle queue deliveries for more randomness
- Update composer libraries
- Add new 2-column templates
- Implement optional OCAP for items to allow access to restricted media without OWA
Bugfixes
- Fix content in nobb and noparse text linkified - issue #1776
- Fix editing an event changes the set time - issue #1771
- Fix person object with mixed up hubloc info - issue #1770
- Fix $escape variable not passed on to stringify_array_elms()
- Fix relaying and syncing in Activity::drop()
- Fix allow code not sticking after channel sync - issue #1769
- Fix channel oembed regressions
Addons
- Diaspora: fix signature check for likes
- Diaspora: fix relaying retractions
- Diaspora: port to core unsolicited comments option
- Gallery: add an exception for streams reshares
- Pubcrawl: dismiss comments that are expected to arrive via owner relay
- Pubcrawl: improved inbox handling
- Pubcrawl: catch gup.pe updates to followers collection
- Pubcrawl: fix follow allow hook
- Diaspora: fix follow allow hook
- Content_import: fix crash in post handler
- Pubcrawl: store follow url when fetching webfinger
- Diaspora: store follow url when fetching webfinger
- Pubcrawl: move addressing to separate function
Hubzilla 8.4.2 (2023-06-02)
- Update bootstrap to stable version 5.3.0
- Fix hubloc confusion in mod rmagic
- Improved unseen forums notification
- Add workaround for friendica accept header bug for nginx
- Fix acl not set correctly in attach_store()
- Fix attachment name parsing
- Fix display issue in oembed video template
- content_import: fix crash in post handler
- pubcrawl: move addressing to separate function
Hubzilla 8.4.1 (2023-05-20)
- Fix issue where accepting AP contacts would reset send stream permission
- Fix link to release page in upgrade info addon
Hubzilla 8.4 (2023-05-17)
- Slightly rewrite Activity::store() to save a query
- Use act->objprop() in decode_note() to get activity values
- Make sure to re-discover a channel upon connecting if we have just an xchan but no hubloc
- Updated ES translations
- Updated RU translations
- Redesigned profile vcard to implement cover images
- Slightly improved discovery of AP quoted messages
- Updated bootstrap library
- Changed hashtag encoding to match mastodons expectations (issue #1750)
- Implement fedearted directory flags from trusted directory servers
- Use Activity::get_actor_hublocs() in Libzot::fetch_conversation() instead of custom queries
- Add the conversation endpoint
- Implement paginated fetch for zot requests in mod item
- Implement Zotconvo daemon to fetch conversations in the background
- Expose deleted channels to webfinger (otherwise we can not mark them deleted locally)
- Expire items in batches to prevent memory exhaustion
- Remove legacy zot compatibility tweaks
- Rewrite and simplify directory sync
- Improve potentially long running sql query finding the thread parent
- Implement option to override permissions for posts with mentions
Bugfixes
- Fix parent_mid and thr_parent not set correctly for response activities
- Fix query for postgres in attach_list_files()
- Fix item_url_replace() failing on arrays
- Fix OWA compatibility with friendica
- Fix regression in decoding the object type
- Fix xss vulnerability in justified gallery library
- Fix permissions not initialized after accepted follow request from AP
- Fix empty path passed to fopen()
- Fix % value in format_poll() not rounded
- Fix remove_all_xchan_resources() executed for local channels
- Fix likes not synced via libsync between clones
Addons
- Pubcrawl: fix xchan_url used as follow object instead of xchan_hash
- Channelreputation: moved to unmaintained repo due to duplication issues when storing data in pconfig
- Pubcrawl: add lemmy accept/reject follow quirks
- Diaspora: handle 4xx return codes in queue management
- Diaspora: fix fatal error in the case where parent_guid is set but empty
- Pubcrawl: if shared inbox delivery fails deliver to contacts instead of everybody we know from that site
- Articles: fix PHP error
- Diaspora: rewrite synced (from a clone) item author to primary
- Diaspora: improve reshare detection
- Diaspora: fix contact role not sets
- Pubcrawl: rewrite synced (from a clone) item author to primary
- Pubcrawl: if we receive a public message to the shared inbox deliver to following *and* directly addressed
Hubzilla 8.2 (2023-03-19)
- Remove redundant untranslated htconfig templates
- Implement workaround for friendica image/attachment construct

View File

@@ -2,6 +2,7 @@
namespace Zotlabs\Access;
/**
* @brief AccessList class which represents individual content ACLs.
*
@@ -17,29 +18,48 @@ class AccessList {
* @brief Allow contacts
* @var string
*/
private $allow_cid;
private ?string $allow_cid;
/**
* @brief Allow groups
* @var string
*/
private $allow_gid;
private ?string $allow_gid;
/**
* @brief Deny contacts
* @var string
*/
private $deny_cid;
private ?string $deny_cid;
/**
* @brief Deny groups
* @var string
*/
private $deny_gid;
private ?string $deny_gid;
/**
* @brief Indicates if we are using the default constructor values or
* values that have been set explicitly.
* @var boolean
*/
private $explicit;
private bool $explicit;
/**
* @brief Keys required by the constructor if the channel array is given.
*/
private const REQUIRED_KEYS_CONSTRUCTOR = [
'channel_allow_cid',
'channel_allow_gid',
'channel_deny_cid',
'channel_deny_gid'
];
/**
* @brief Keys required by the set method.
*/
private const REQUIRED_KEYS_SET = [
'allow_cid',
'allow_gid',
'deny_cid',
'deny_gid'
];
/**
* @brief Constructor for AccessList class.
@@ -53,8 +73,9 @@ class AccessList {
* * \e string \b channel_deny_cid => string of denied cids
* * \e string \b channel_deny_gid => string of denied gids
*/
function __construct($channel) {
function __construct(array $channel) {
if ($channel) {
$this->validate_input_array($channel, self::REQUIRED_KEYS_CONSTRUCTOR);
$this->allow_cid = $channel['channel_allow_cid'];
$this->allow_gid = $channel['channel_allow_gid'];
$this->deny_cid = $channel['channel_deny_cid'];
@@ -70,13 +91,24 @@ class AccessList {
$this->explicit = false;
}
private function validate_input_array(array $arr, array $required_keys) : void {
$missing_keys = array_diff($required_keys, array_keys($arr));
if (!empty($missing_keys)) {
throw new \Exception(
'Invalid AccessList object: Expected array with keys: '
. implode(', ', $missing_keys)
);
}
}
/**
* @brief Get if we are using the default constructor values
* or values that have been set explicitly.
*
* @return boolean
*/
function get_explicit() {
function get_explicit() : bool {
return $this->explicit;
}
@@ -94,7 +126,9 @@ class AccessList {
* * \e string \b deny_gid => string of denied gids
* @param boolean $explicit (optional) default true
*/
function set($arr, $explicit = true) {
function set(array $arr, bool $explicit = true) : void {
$this->validate_input_array($arr, self::REQUIRED_KEYS_SET);
$this->allow_cid = $arr['allow_cid'];
$this->allow_gid = $arr['allow_gid'];
$this->deny_cid = $arr['deny_cid'];
@@ -112,7 +146,7 @@ class AccessList {
* * \e string \b deny_cid => string of denied cids
* * \e string \b deny_gid => string of denied gids
*/
function get() {
function get() : array {
return [
'allow_cid' => $this->allow_cid,
'allow_gid' => $this->allow_gid,
@@ -138,7 +172,7 @@ class AccessList {
* * \e array|string \b group_deny => array with gids or comma-seperated string
* @param boolean $explicit (optional) default true
*/
function set_from_array($arr, $explicit = true) {
function set_from_array(array $arr, bool $explicit = true) : void {
$arr['contact_allow'] = $arr['contact_allow'] ?? [];
$arr['group_allow'] = $arr['group_allow'] ?? [];
$arr['contact_deny'] = $arr['contact_deny'] ?? [];
@@ -161,7 +195,7 @@ class AccessList {
*
* @return boolean Return true if any of allow_* deny_* values is set.
*/
function is_private() {
function is_private() : bool {
return (($this->allow_cid || $this->allow_gid || $this->deny_cid || $this->deny_gid) ? true : false);
}

View File

@@ -3,6 +3,7 @@
namespace Zotlabs\Daemon;
use Zotlabs\Lib\Libsync;
use Zotlabs\Lib\Libzotdir;
class Cron {
@@ -35,6 +36,17 @@ class Cron {
logger('cron: start');
// If this is a directory server, request a sync with an upstream
// directory at least once a day, up to once every poll interval.
// Pull remote changes and push local changes.
// potential issue: how do we keep from creating an endless update loop?
$dirmode = get_config('system', 'directory_mode');
if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
Libzotdir::sync_directories($dirmode);
}
// run queue delivery process in the background
Master::Summon(array('Queue'));

View File

@@ -94,17 +94,6 @@ class Cron_daily {
// expire any expired accounts
downgrade_accounts();
// If this is a directory server, request a sync with an upstream
// directory at least once a day, up to once every poll interval.
// Pull remote changes and push local changes.
// potential issue: how do we keep from creating an endless update loop?
$dirmode = get_config('system', 'directory_mode');
if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
Libzotdir::sync_directories($dirmode);
}
Master::Summon(array('Expire'));
Master::Summon(array('Cli_suggest'));

View File

@@ -32,7 +32,6 @@ class Expire {
}
// physically remove anything that has been deleted for more than two months
/** @FIXME - this is a wretchedly inefficient query */
q("delete from item where item_pending_remove = 1 and changed < %s - INTERVAL %s",
db_utcnow(),
@@ -59,8 +58,8 @@ class Expire {
continue;
// service class default (if non-zero) over-rides the site default
$service_class_expire = service_class_fetch($rr['channel_id'], 'expire_days');
if (intval($service_class_expire))
$channel_expire = $service_class_expire;
else
@@ -85,7 +84,6 @@ class Expire {
// this should probably just fetch the channel_expire_days from the sys channel,
// but there's no convenient way to set it.
$expire_days = get_config('system', 'sys_expire_days');
if ($expire_days === false)
$expire_days = 30;
@@ -96,8 +94,9 @@ class Expire {
logger('Expire: sys interval: ' . $expire_days, LOGGER_DEBUG);
if ($expire_days)
if ($expire_days) {
item_expire($x['channel_id'], $expire_days, $commented_days);
}
logger('Expire: sys: done', LOGGER_DEBUG);
}

View File

@@ -300,6 +300,11 @@ class Notifier {
return;
}
if ($target_item['verb'] === ACTIVITY_SHARE) {
// Provide correct representation across the wire. Internally this is treated as a comment.
$target_item['parent_mid'] = $target_item['thr_parent'] = $target_item['mid'];
}
if ($target_item['mid'] === $target_item['parent_mid']) {
$parent_item = $target_item;
$top_level_post = true;
@@ -377,7 +382,7 @@ class Notifier {
if (($relay_to_owner || $uplink) && ($cmd !== 'relay')) {
logger('notifier: followup relay', LOGGER_DEBUG);
$sendto = (($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan']);
$sendto = (($uplink) ? $parent_item['source_xchan'] : (($parent_item['verb'] === ACTIVITY_SHARE) ? $parent_item['author_xchan'] : $parent_item['owner_xchan']));
self::$recipients = [$sendto];
self::$private = true;
$upstream = true;
@@ -409,9 +414,7 @@ class Notifier {
self::$private = false;
self::$recipients = collect_recipients($parent_item, self::$private);
// FIXME add any additional recipients such as mentions, etc.
if ($top_level_post) {
if ($top_level_post && intval($target_item['item_wall'])) {
// remove clones who will receive the post via sync
self::$recipients = array_values(array_diff(self::$recipients, [$target_item['owner_xchan']]));
}

View File

@@ -15,61 +15,45 @@ class Onedirsync {
$update_id = intval($argv[1]);
if (!$update_id) {
logger('onedirsync: no update');
logger('onedirsync: no update id');
return;
}
$r = q("select * from updates where ud_id = %d limit 1",
$r = q("select * from updates where ud_id = %d",
intval($update_id)
);
if (!$r)
return;
if (($r[0]['ud_flags'] & UPDATE_FLAGS_UPDATED) || (!$r[0]['ud_addr']))
return;
// Have we probed this channel more recently than the other directory server
// (where we received this update from) ?
// If we have, we don't need to do anything except mark any older entries updated
$x = q("select * from updates where ud_addr = '%s' and ud_date > '%s' and ( ud_flags & %d )>0 order by ud_date desc limit 1",
dbesc($r[0]['ud_addr']),
dbesc($r[0]['ud_date']),
intval(UPDATE_FLAGS_UPDATED)
);
if ($x) {
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 and ud_date != '%s'",
intval(UPDATE_FLAGS_UPDATED),
dbesc($r[0]['ud_addr']),
intval(UPDATE_FLAGS_UPDATED),
dbesc($x[0]['ud_date'])
);
if (!$r) {
logger('onedirsync: update id not found');
return;
}
// ignore doing an update if this ud_addr refers to a known dead hubloc
$h = q("select * from hubloc where hubloc_addr = '%s'",
$h = q("select * from hubloc where hubloc_id_url = '%s' order by hubloc_id desc",
dbesc($r[0]['ud_addr']),
);
$h = Libzot::zot_record_preferred($h);
if (($h) && (($h['hubloc_status'] & HUBLOC_OFFLINE) || $h['hubloc_deleted'] || $h['hubloc_error'])) {
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and ( ud_flags & %d ) = 0 ",
intval(UPDATE_FLAGS_DELETED),
dbesc($r[0]['ud_addr']),
intval(UPDATE_FLAGS_UPDATED)
);
return;
// 2023-04-12: Try to update anyway since the info is not always correct
// This might change after all directory servers run the new code.
// q("update updates set ud_flags = 9 where ud_hash = '%s' and ud_flags != 9",
// dbesc($r[0]['ud_hash'])
//);
// return;
}
// we might have to pull this out some day, but for now update_directory_entry()
// runs zot_finger() and is kind of zot specific
if ($h && $h['hubloc_network'] !== 'zot6')
if ($h && $h['hubloc_network'] !== 'zot6') {
return;
}
Libzotdir::update_directory_entry($r[0]);

View File

@@ -30,14 +30,10 @@ class Onepoll {
$sql_extra = ' and abook_feed = 0 ';
}
$contacts = q("SELECT abook.*, xchan.*, account.*
FROM abook LEFT JOIN account on abook_account = account_id left join xchan on xchan_hash = abook_xchan
where abook_id = %d $sql_extra
and abook_pending = 0 and abook_archived = 0 and abook_blocked = 0 and abook_ignored = 0
AND (( account_flags = %d ) OR ( account_flags = %d )) limit 1",
intval($contact_id),
intval(ACCOUNT_OK),
intval(ACCOUNT_UNVERIFIED)
$contacts = q("SELECT abook.*, xchan.* FROM abook
LEFT JOIN xchan ON xchan_hash = abook_xchan
WHERE abook_id = %d",
intval($contact_id)
);
if (!$contacts) {

View File

@@ -19,24 +19,6 @@ class Poller {
$interval = get_config('queueworker', 'queue_interval', 500000);
/*
if (!$interval) {
$interval = ((get_config('system', 'delivery_interval') === false) ? 3 : intval(get_config('system', 'delivery_interval')));
}
// Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
$lockfile = 'store/[data]/poller';
if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
&& (!get_config('system', 'override_poll_lockfile'))) {
logger("poller: Already running");
return;
}
// Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
$x = '';
file_put_contents($lockfile, $x);
*/
logger('poller: start');
$manual_id = 0;
@@ -67,6 +49,11 @@ class Poller {
: ''
);
$allow_feeds = get_config('system', 'feed_contacts');
if(!$allow_feeds) {
$sql_extra .= ' and abook_feed = 0 ';
}
$randfunc = db_getfunc('RAND');
$contacts = q("SELECT abook.abook_updated, abook.abook_connected, abook.abook_feed,
@@ -76,7 +63,7 @@ class Poller {
account.account_lastlog, account.account_flags
FROM abook LEFT JOIN xchan on abook_xchan = xchan_hash
LEFT JOIN account on abook_account = account_id
where abook_self = 0
where abook_self = 0 and abook_pending = 0 and abook_archived = 0 and abook_blocked = 0 and abook_ignored = 0
$sql_extra
AND (( account_flags = %d ) OR ( account_flags = %d )) $abandon_sql ORDER BY $randfunc",
intval(ACCOUNT_OK),
@@ -183,11 +170,12 @@ class Poller {
$dirmode = intval(get_config('system', 'directory_mode'));
if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
$r = q("SELECT u.ud_addr, u.ud_id, u.ud_last FROM updates AS u INNER JOIN (SELECT ud_addr, max(ud_id) AS ud_id FROM updates WHERE ( ud_flags & %d ) = 0 AND ud_addr != '' AND ( ud_last <= '%s' OR ud_last > %s - INTERVAL %s ) GROUP BY ud_addr) AS s ON s.ud_id = u.ud_id ",
intval(UPDATE_FLAGS_UPDATED),
$r = q("SELECT * FROM updates WHERE ud_update = 1 AND (ud_last = '%s' OR ud_last > %s - INTERVAL %s)",
dbesc(NULL_DATE),
db_utcnow(), db_quoteinterval('7 DAY')
db_utcnow(),
db_quoteinterval('7 DAY')
);
if ($r) {
foreach ($r as $rr) {
@@ -209,10 +197,6 @@ class Poller {
set_config('system', 'lastpoll', datetime_convert());
//All done - clear the lockfile
/*
@unlink($lockfile);
*/
return;
}
}

View File

@@ -14,7 +14,7 @@ class Queue {
// delete all queue items more than 3 days old
// but first mark these sites dead if we haven't heard from them in a month
$oldqItems = q("select outq_posturl from outq where outq_created < %s - INTERVAL %s",
$oldqItems = q("select outq_posturl, outq_hash from outq where outq_created < %s - INTERVAL %s",
db_utcnow(),
db_quoteinterval('3 DAY')
);
@@ -29,13 +29,13 @@ class Queue {
db_quoteinterval('1 MONTH')
);
}
}
logger('Removing ' . count($oldqItems) . ' old queue entries');
q("DELETE FROM outq WHERE outq_created < %s - INTERVAL %s",
db_utcnow(),
db_quoteinterval('3 DAY')
);
$old_hashes = ids_to_querystr($oldqItems, 'outq_hash', true);
logger('Removing ' . count($oldqItems) . ' old queue entries');
dbq("DELETE FROM outq WHERE outq_hash IN ($old_hashes)");
}
$deliveries = [];
@@ -47,13 +47,16 @@ class Queue {
LibQueue::deliver($qItems[0]);
}
else {
$qItems = q("SELECT * FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s ",
$qItems = q("SELECT outq_hash FROM outq WHERE outq_scheduled < %s ",
db_utcnow()
);
if ($qItems) {
foreach ($qItems as $qItem) {
$deliveries[] = $qItem['outq_hash'];
}
shuffle($deliveries);
do_delivery($deliveries, true);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/** @file */
namespace Zotlabs\Daemon;
class Xchan_photo {
static public function run($argc, $argv) {
if ($argc != 3) {
return;
}
$url = hex2bin($argv[1]);
$xchan = hex2bin($argv[2]);
$photos = import_xchan_photo($url, $xchan);
if ($photos) {
$result = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
dbescdate(datetime_convert()),
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
dbesc($photos[3]),
dbesc($xchan)
);
if (! $result) {
logger("xchan update failed for $url");
}
}
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Zotlabs\Daemon;
use Zotlabs\Lib\Libzot;
class Zotconvo {
static public function run($argc, $argv) {
logger('Zotconvo invoked: ' . print_r($argv, true));
if ($argc != 3) {
return;
}
$mid = $argv[2];
if (!$mid) {
return;
}
$channel = channelx_by_n(intval($argv[1]));
if (!$channel) {
return;
}
Libzot::fetch_conversation($channel, $mid);
return;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,7 @@ class ActivityStreams {
public $meta = null;
public $valid = false;
public $deleted = false;
public $portable_id = null;
public $id = '';
public $parent_id = '';
public $type = '';
@@ -35,12 +36,13 @@ class ActivityStreams {
*
* @param string $string
*/
function __construct($string) {
function __construct($string, $portable_id = null) {
if(!$string)
return;
$this->raw = $string;
$this->portable_id = $portable_id;
if (is_array($string)) {
$this->data = $string;
@@ -123,12 +125,14 @@ class ActivityStreams {
$this->parent_id = $this->get_property_obj('inReplyTo');
if ((!$this->parent_id) && is_array($this->obj) && isset($this->obj['inReplyTo'])) {
if (!$this->parent_id && is_array($this->obj) && isset($this->obj['inReplyTo'])) {
$this->parent_id = $this->obj['inReplyTo'];
}
if ((!$this->parent_id) && is_array($this->obj) && isset($this->obj['id'])) {
if (!$this->parent_id && is_array($this->obj) && isset($this->obj['id'])) {
$this->parent_id = $this->obj['id'];
}
}
}
@@ -154,7 +158,7 @@ class ActivityStreams {
* @return mixed
*/
public function objprop(string $property, mixed $default = false): mixed {
$x = $this->get_property_obj($property,$this->obj);
$x = $this->get_property_obj($property, $this->obj);
return (isset($x)) ? $x : $default;
}
@@ -301,12 +305,26 @@ class ActivityStreams {
* @return NULL|mixed
*/
function fetch_property($url) {
return self::fetch($url);
}
function fetch_property($url, $channel = null) {
$x = null;
static function fetch($url, $channel = null) {
return Activity::fetch($url, $channel);
if (str_starts_with($url, z_root() . '/item/')) {
$x = Activity::fetch_local($url, $this->portable_id ?? '');
logger('local: ' . print_r($x,true));
}
if (!$x) {
$x = Activity::fetch($url, $channel);
if ($x === null && strpos($url, '/channel/')) {
// look for other nomadic channels which might be alive
$zf = Zotfinger::exec($url, $channel);
$url = $zf['signature']['signer'];
$x = Activity::fetch($url, $channel);
}
}
return $x;
}
static function is_an_actor($s) {
@@ -333,7 +351,7 @@ class ActivityStreams {
$x = $this->get_property_obj($property, $base, $namespace);
if ($this->is_url($x)) {
$y = Activity::get_cached_actor($x);
$y = Activity::get_actor($x);
if ($y) {
return $y;
}

View File

@@ -419,11 +419,28 @@ class Apps {
static public function app_render($papp, $mode = 'view') {
$installed = false;
if(! $papp)
if(!$papp) {
return;
}
if(! $papp['photo'])
/**
* @hooks app_render_before
* Hook to manipulate the papp array before rendering
*/
$hookinfo = [
'name' => $papp['name'],
'photo' => $papp['photo']
];
call_hooks('app_render_manipulate_photo', $hookinfo);
// We will only allow to manipulate the photo
$papp['photo'] = $hookinfo['photo'];
if(!$papp['photo']) {
$papp['photo'] = 'icon:gear';
}
self::translate_system_apps($papp);

View File

@@ -5,17 +5,17 @@ namespace Zotlabs\Lib;
/**
* cache api
*/
class Cache {
/**
* @brief Returns cached content
*
*
* @param string $key
* @param string $age in SQL format, default is '30 DAY'
* @return string
*/
public static function get($key, $age = '') {
$hash = hash('whirlpool',$key);
@@ -25,12 +25,12 @@ class Cache {
db_utcnow(),
db_quoteinterval(($age ? $age : get_config('system','object_cache_days', '30') . ' DAY'))
);
if ($r)
return $r[0]['v'];
return null;
}
public static function set($key,$value) {
$hash = hash('whirlpool',$key);
@@ -45,7 +45,7 @@ class Cache {
dbesc($hash));
}
else {
q("INSERT INTO cache ( k, v, updated) VALUES ('%s','%s','%s')",
q("INSERT INTO cache (k, v, updated) VALUES ('%s', '%s', '%s')",
dbesc($hash),
dbesc($value),
dbesc(datetime_convert()));

View File

@@ -69,7 +69,8 @@ class Connect {
$xchan_hash = '';
$sql_options = (($protocol) ? " and xchan_network = '" . dbesc($protocol) . "' " : '');
$r = q("SELECT * FROM xchan LEFT JOIN hubloc ON xchan_hash = hubloc_hash WHERE ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s') $sql_options ORDER BY hubloc_id DESC",
// We need both, the xchan and the hubloc here hence use JOIN instead of LEFT JOIN
$r = q("SELECT * FROM xchan JOIN hubloc ON xchan_hash = hubloc_hash WHERE ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s') $sql_options ORDER BY hubloc_id DESC",
dbesc($url),
dbesc($url),
dbesc($url)

View File

@@ -145,7 +145,7 @@ class Enotify {
$itemlink = $params['link'];
$action = t('commented on');
$action = (($moderated) ? t('requested to comment on') : t('commented on'));
if(array_key_exists('item',$params)) {
@@ -158,10 +158,10 @@ class Enotify {
}
if(activity_match($params['verb'], ACTIVITY_LIKE))
$action = t('liked');
$action = (($moderated) ? t('requested to like') : t('liked'));
if(activity_match($params['verb'], ACTIVITY_DISLIKE))
$action = t('disliked');
$action = (($moderated) ? t('requested to dislike') : t('disliked'));
}
@@ -307,7 +307,14 @@ class Enotify {
$parent_item = $p[0];
$verb = ((activity_match($params['item']['verb'], ACTIVITY_DISLIKE)) ? t('disliked') : t('liked'));
//$verb = ((activity_match($params['item']['verb'], ACTIVITY_DISLIKE)) ? t('disliked') : t('liked'));
$moderated = (($params['item']['item_blocked'] == ITEM_MODERATED) ? true : false);
if(activity_match($params['item']['verb'], ACTIVITY_LIKE))
$verb = (($moderated) ? t('requested to like') : t('liked'));
if(activity_match($params['item']['verb'], ACTIVITY_DISLIKE))
$verb = (($moderated) ? t('requested to dislike') : t('disliked'));
// "your post"
if($p[0]['owner']['xchan_name'] === $p[0]['author']['xchan_name'] && intval($p[0]['item_wall']))

View File

@@ -13,7 +13,7 @@ class IConfig {
static public function Get(&$item, $family, $key, $default = false) {
$is_item = false;
if(is_array($item)) {
$is_item = true;
if((! array_key_exists('iconfig',$item)) || (! is_array($item['iconfig'])))
@@ -22,7 +22,7 @@ class IConfig {
if(array_key_exists('item_id',$item))
$iid = $item['item_id'];
else
$iid = $item['id'];
$iid = $item['id'] ?? 0;
}
elseif(intval($item))
$iid = $item;
@@ -36,7 +36,7 @@ class IConfig {
return $c['v'];
}
}
$r = q("select * from iconfig where iid = %d and cat = '%s' and k = '%s' limit 1",
intval($iid),
dbesc($family),
@@ -63,11 +63,11 @@ class IConfig {
* $value - value of meta variable
* $sharing - boolean (default false); if true the meta information is propagated with the item
* to other sites/channels, mostly useful when $item is an array and has not yet been stored/delivered.
* If the meta information is added after delivery and you wish it to be shared, it may be necessary to
* alter the item edited timestamp and invoke the delivery process on the updated item. The edited
* If the meta information is added after delivery and you wish it to be shared, it may be necessary to
* alter the item edited timestamp and invoke the delivery process on the updated item. The edited
* timestamp needs to be altered in order to trigger an item_store_update() at the receiving end.
*/
static public function Set(&$item, $family, $key, $value, $sharing = false) {
@@ -162,4 +162,4 @@ class IConfig {
}
}
}

View File

@@ -52,7 +52,7 @@ class JSalmon {
. base64url_encode($x['alg'],true);
$key = HTTPSig::get_key(EMPTY_STR,'zot6',base64url_decode($x['sigs']['key_id']));
logger('key: ' . print_r($key,true));
logger('key: ' . print_r($key,true), LOGGER_DATA);
if($key['portable_id'] && $key['public_key']) {
if(Crypto::verify($signed_data,base64url_decode($x['sigs']['value']),$key['public_key'])) {
logger('verified');

View File

@@ -141,7 +141,7 @@ class Libsync {
$total = count($synchubs);
foreach ($synchubs as $hub) {
$hash = random_string();
$hash = new_uuid();
$n = Libzot::build_packet($channel, 'sync', $env_recips, json_encode($info), 'hz', $hub['hubloc_sitekey'], $hub['site_crypto']);
Queue::insert([
'hash' => $hash,
@@ -328,7 +328,7 @@ class Libsync {
$remote_channel = $arr['channel'];
$remote_channel['channel_id'] = $channel['channel_id'];
if (array_key_exists('channel_pageflags', $arr['channel']) && intval($arr['channel']['channel_pageflags'])) {
if (array_key_exists('channel_pageflags', $arr['channel'])) {
// Several pageflags are site-specific and cannot be sync'd.
// Only allow those bits which are shareable from the remote and then
@@ -771,7 +771,12 @@ class Libsync {
static function sync_locations($sender, $arr) {
$ret = [];
$ret = [
'change_message' => '',
'changed' => false,
'message' => ''
];
$what = '';
$changed = false;
@@ -786,7 +791,7 @@ class Libsync {
if (isset($arr['locations']) && $arr['locations']) {
$xisting = q("select * from hubloc where hubloc_hash = '%s'",
$xisting = q("select * from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0",
dbesc($sender['hash'])
);

View File

@@ -328,7 +328,7 @@ class Libzot {
logger('zot-info: ' . print_r($record, true), LOGGER_DATA, LOG_DEBUG);
$x = self::import_xchan($record['data'], (($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
$x = self::import_xchan($record['data']);
if (!$x['success']) {
return false;
@@ -635,23 +635,18 @@ class Libzot {
* all internal data structures which need to be updated as a result.
*
* @param array $arr => json_decoded discovery packet
* @param int $ud_flags
* Determines whether to create a directory update record if any changes occur, default is UPDATE_FLAGS_UPDATED
* $ud_flags = UPDATE_FLAGS_FORCED indicates a forced refresh where we unconditionally create a directory update record
* this typically occurs once a month for each channel as part of a scheduled ping to notify the directory
* that the channel still exists
* @param array $ud_arr
* If set [typically by update_directory_entry()] indicates a specific update table row and more particularly
* contains a particular address (ud_addr) which needs to be updated in that table.
*
* @return array An associative array with:
* * \e boolean \b success boolean true or false
* * \e string \b message (optional) error string only if success is false
*/
static function import_xchan($arr, $ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
static function import_xchan($arr) {
$ret = ['success' => false];
$ret = [
'success' => false,
'message' => ''
];
if (!is_array($arr)) {
logger('Not an array: ' . print_r($arr, true), LOGGER_DEBUG);
@@ -665,7 +660,7 @@ class Libzot {
*/
call_hooks('import_xchan', $arr);
$dirmode = intval(get_config('system', 'directory_mode'));
$dirmode = intval(get_config('system', 'directory_mode', DIRECTORY_MODE_NORMAL));
$changed = false;
$what = '';
@@ -683,15 +678,11 @@ class Libzot {
$sig_methods = ((array_key_exists('signing', $arr) && is_array($arr['signing'])) ? $arr['signing'] : ['sha256']);
$verified = false;
if (!self::verify($arr['id'], $arr['id_sig'], $arr['public_key'])) {
logger('Unable to verify channel signature for ' . $arr['primary_location']['address']);
return $ret;
}
else {
if (self::verify($arr['id'], $arr['id_sig'], $arr['public_key'])) {
$verified = true;
}
if (!$verified) {
else {
logger('Unable to verify channel signature for ' . $xchan_hash . ' (' . $arr['primary_location']['address']) . ')';
$ret['message'] = t('Unable to verify channel signature');
return $ret;
}
@@ -714,6 +705,7 @@ class Libzot {
if ($arr['photo'] && array_key_exists('updated', $arr['photo']) && $arr['photo']['updated'] > $r[0]['xchan_photo_date'])
$import_photos = true;
// if we import an entry from a site that's not ours and either or both of us is off the grid - hide the entry.
/** @TODO: check if we're the same directory realm, which would mean we are allowed to see it */
@@ -730,7 +722,7 @@ class Libzot {
$hidden_changed = 1;
if (isset($arr['adult_content']) && intval($r[0]['xchan_selfcensored']) != intval($arr['adult_content']))
$adult_changed = 1;
if (isset($arr['xchan_deleted']) && intval($r[0]['xchan_deleted']) != intval($arr['deleted']))
if (isset($arr['deleted']) && intval($r[0]['xchan_deleted']) != intval($arr['deleted']))
$deleted_changed = 1;
// new style 6-MAR-2019
@@ -920,30 +912,26 @@ class Libzot {
$s = Libsync::sync_locations($arr, $arr);
if ($s) {
if (isset($s['change_message']))
if (!empty($s['change_message']))
$what .= $s['change_message'];
if (isset($s['changed']))
$changed = $s['changed'];
if (isset($s['message']))
if (!empty($s['changed']))
$changed .= $s['changed'];
if (!empty($s['message']))
$ret['message'] .= $s['message'];
}
// Which entries in the update table are we interested in updating?
$address = (($ud_arr && $ud_arr['ud_addr']) ? $ud_arr['ud_addr'] : $arr['primary_location']['address']);
// Are we a directory server of some kind?
$other_realm = false;
$realm = get_directory_realm();
if (array_key_exists('site', $arr)
&& array_key_exists('realm', $arr['site'])
&& (strpos($arr['site']['realm'], $realm) === false))
if (array_key_exists('site', $arr) && array_key_exists('realm', $arr['site']) && (strpos($arr['site']['realm'], $realm) === false)) {
$other_realm = true;
}
$address = $arr['primary_location']['url'];
if ($dirmode != DIRECTORY_MODE_NORMAL) {
// Are we a directory server of some kind?
if ($dirmode !== DIRECTORY_MODE_NORMAL) {
// We're some kind of directory server. However we can only add directory information
// if the entry is in the same realm (or is a sub-realm). Sub-realms are denoted by
@@ -951,7 +939,7 @@ class Libzot {
// be in directories for the local realm (foo) and also the RED_GLOBAL realm.
if (array_key_exists('profile', $arr) && is_array($arr['profile']) && (!$other_realm)) {
$profile_changed = Libzotdir::import_directory_profile($xchan_hash, $arr['profile'], $address, $ud_flags, 1);
$profile_changed = Libzotdir::import_directory_profile($xchan_hash, $arr['profile']);
if ($profile_changed) {
$what .= 'profile ';
$changed = true;
@@ -977,21 +965,10 @@ class Libzot {
}
}
if (($changed) || ($ud_flags == UPDATE_FLAGS_FORCED)) {
$guid = random_string() . '@' . \App::get_hostname();
Libzotdir::update_modtime($xchan_hash, $guid, $address, $ud_flags);
logger('Changed: ' . $what, LOGGER_DEBUG);
}
elseif (!$ud_flags) {
// nothing changed but we still need to update the updates record
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and not (ud_flags & %d) > 0 ",
intval(UPDATE_FLAGS_UPDATED),
dbesc($address),
intval(UPDATE_FLAGS_UPDATED)
);
}
// update updates if anything changed bump the ud_date
Libzotdir::update($xchan_hash, $address, $changed);
if (!x($ret, 'message')) {
if (empty($ret['message'])) {
$ret['success'] = true;
$ret['hash'] = $xchan_hash;
}
@@ -1137,6 +1114,7 @@ class Libzot {
*/
static function import($arr) {
$env = $arr;
$private = false;
$return = [];
@@ -1233,7 +1211,6 @@ class Libzot {
return;
}
if ($has_data) {
if (in_array($env['type'], ['activity', 'response'])) {
@@ -1243,17 +1220,19 @@ class Libzot {
return;
}
$r = q("select hubloc_hash, hubloc_network, hubloc_url from hubloc where hubloc_id_url = '%s' and hubloc_deleted = 0 order by hubloc_id desc",
dbesc($AS->actor['id'])
);
$author_url = $AS->actor['id'];
if (! $r) {
if ($AS->type === 'Announce') {
$author_url = Activity::get_attributed_to_actor_url($AS);
}
$r = Activity::get_actor_hublocs($author_url);
if (!$r) {
// Author is unknown to this site. Perform channel discovery and try again.
$z = discover_by_webbie($AS->actor['id']);
$z = discover_by_webbie($author_url);
if ($z) {
$r = q("select hubloc_hash, hubloc_network, hubloc_url from hubloc where hubloc_id_url = '%s' and hubloc_deleted = 0 order by hubloc_id desc",
dbesc($AS->actor['id'])
);
$r = Activity::get_actor_hublocs($author_url);
}
}
@@ -1386,6 +1365,31 @@ class Libzot {
return false;
}
static function find_parent_owner_hashes($env, $act) {
$r = [];
$thread_parent = self::find_parent($env, $act);
if ($thread_parent) {
$uids = q("SELECT uid FROM item WHERE thr_parent = '%s' OR parent_mid = '%s'",
dbesc($thread_parent),
dbesc($thread_parent)
);
if ($uids) {
$uids = ids_to_querystr($uids, 'uid');
$z = q("SELECT channel_hash FROM channel WHERE channel_hash != '%s' AND channel_id IN ($uids)",
dbesc($env['sender'])
);
if ($z) {
foreach ($z as $zv) {
$r[] = $zv['channel_hash'];
}
}
}
}
return $r;
}
/**
* @brief
@@ -1451,7 +1455,7 @@ class Libzot {
if ($act && $act->obj) {
if (isset($act->obj['tag']) && is_array($act->obj['tag']) && $act->obj['tag']) {
foreach ($act->obj['tag'] as $tag) {
if ($tag['type'] === 'Mention' && (strpos($tag['href'], z_root()) !== false)) {
if (isset($tag['type'], $tag['href']) && $tag['type'] === 'Mention' && (strpos($tag['href'], z_root()) !== false)) {
$address = basename($tag['href']);
if ($address) {
$z = q("select channel_hash as hash from channel where channel_address = '%s' and channel_hash != '%s'
@@ -1466,26 +1470,23 @@ class Libzot {
}
}
}
if ($act->obj['type'] === 'Tombstone') {
// This is a delete. There are no tags to look at - add anyone owning the item.
$parent_owners = self::find_parent_owner_hashes($msg, $act);
if ($parent_owners) {
$r = array_merge($r, $parent_owners);
}
}
}
}
else {
// This is a comment. We need to find any parent with ITEM_UPLINK set. But in fact, let's just return
// everybody that stored a copy of the parent. This way we know we're covered. We'll check the
// comment permissions when we deliver them.
$thread_parent = self::find_parent($msg, $act);
if ($thread_parent) {
$z = q("select channel_hash as hash from channel left join item on channel.channel_id = item.uid where ( item.thr_parent = '%s' OR item.parent_mid = '%s' ) and channel_hash != '%s'",
dbesc($thread_parent),
dbesc($thread_parent),
dbesc($msg['sender'])
);
if ($z) {
foreach ($z as $zv) {
$r[] = $zv['hash'];
}
}
$parent_owners = self::find_parent_owner_hashes($msg, $act);
if ($parent_owners) {
$r = array_merge($r, $parent_owners);
}
}
@@ -1515,11 +1516,9 @@ class Libzot {
*/
static function process_delivery($sender, $act, $arr, $deliveries, $relay, $public = false, $request = false, $force = false) {
$result = [];
// We've validated the sender. Now make sure that the sender is the owner or author
if (!$public) {
if ($sender != $arr['owner_xchan'] && $sender != $arr['author_xchan']) {
logger("Sender $sender is not owner {$arr['owner_xchan']} or author {$arr['author_xchan']} - mid {$arr['mid']}");
@@ -1570,9 +1569,14 @@ class Libzot {
* There's a chance the current delivery could take place before the cloned copy arrives
* hence the item could have the wrong ACL and *could* be used in subsequent deliveries or
* access checks.
*
* 30.3.23: block all incoming items from ourselves except if the origin is local.
* This is to prevent multiple relay delivery of items that arrive via sync.
* They have already been relayed at the origin location.
*
*/
if ($sender === $channel['channel_hash'] && $arr['author_xchan'] === $channel['channel_hash'] && $arr['mid'] === $arr['parent_mid']) {
if ($sender === $channel['channel_hash'] && $arr['author_xchan'] === $channel['channel_hash'] && !str_starts_with($arr['mid'], z_root())) {
$DR->update('self delivery ignored');
$result[] = $DR->get();
continue;
@@ -1622,18 +1626,34 @@ class Libzot {
if ((!$tag_delivery) && (!$local_public)) {
$allowed = (perm_is_allowed($channel['channel_id'], $sender, $perm));
if ((!$allowed) && $perm === 'post_comments') {
$parent = q("select * from item where mid = '%s' and uid = %d limit 1",
dbesc($arr['parent_mid']),
intval($channel['channel_id'])
);
if ($parent) {
$allowed = can_comment_on_post($sender, $parent[0]);
$permit_mentions = intval(PConfig::Get($channel['channel_id'], 'system', 'permit_all_mentions') && i_am_mentioned($channel, $arr));
if (!$allowed) {
if ($perm === 'post_comments') {
$parent = q("select * from item where mid = '%s' and uid = %d limit 1",
dbesc($arr['parent_mid']),
intval($channel['channel_id'])
);
if ($parent) {
$allowed = can_comment_on_post($sender, $parent[0]);
if (!$allowed && $permit_mentions) {
$allowed = true;
}
if (!$allowed) {
if (PConfig::Get($channel['channel_id'], 'system', 'moderate_unsolicited_comments') && $arr['obj_type'] !== 'Answer') {
$arr['item_blocked'] = ITEM_MODERATED;
$allowed = true;
}
}
}
} elseif ($permit_mentions) {
$allowed = true;
}
}
if ($request) {
// Conversation fetches (e.g. $request == true) take place for
// a) new comments on expired posts
// b) hyperdrive (friend-of-friend) conversations
@@ -1710,7 +1730,7 @@ class Libzot {
// this is just an exercise in futility.
if (perm_is_allowed($channel['channel_id'], $sender, 'send_stream')) {
self::fetch_conversation($channel, $arr['parent_mid']);
Master::Summon(['Zotconvo', $channel['channel_id'], $arr['parent_mid']]);
}
continue;
@@ -1820,13 +1840,19 @@ class Libzot {
if ($r) {
// We already have this post.
// Dismiss its announce
if ($act->type === 'Announce') {
$DR->update('update ignored');
$result[] = $DR->get();
continue;
}
$item_id = $r[0]['id'];
if (intval($r[0]['item_deleted'])) {
// It was deleted locally.
$DR->update('update ignored');
$result[] = $DR->get();
continue;
}
// Maybe it has been edited?
@@ -1834,17 +1860,17 @@ class Libzot {
$arr['id'] = $r[0]['id'];
$arr['uid'] = $channel['channel_id'];
if (post_is_importable($channel['channel_id'], $arr, $abook)) {
$item_result = self::update_imported_item($sender, $arr, $r[0], $channel['channel_id'], $tag_delivery);
$DR->update('updated');
$result[] = $DR->get();
if (!$relay) {
add_source_route($item_id, $sender);
}
} else {
$DR->update('update ignored');
$result[] = $DR->get();
}
if (post_is_importable($channel['channel_id'], $arr, $abook)) {
$item_result = self::update_imported_item($sender, $arr, $r[0], $channel['channel_id'], $tag_delivery);
$DR->update('updated');
$result[] = $DR->get();
if (!$relay) {
add_source_route($item_id, $sender);
}
} else {
$DR->update('update ignored');
$result[] = $DR->get();
}
}
else {
$DR->update('update ignored');
@@ -1862,8 +1888,9 @@ class Libzot {
// if it's a sourced post, call the post_local hooks as if it were
// posted locally so that crosspost connectors will be triggered.
$item_source = check_item_source($arr['uid'], $arr);
if (check_item_source($arr['uid'], $arr) || ($channel['xchan_pubforum'] == 1)) {
if ($item_source || ($channel['xchan_pubforum'] == 1)) {
/**
* @hooks post_local
* Called when an item has been posted on this machine via mod/item.php (also via API).
@@ -1889,7 +1916,13 @@ class Libzot {
if (post_is_importable($arr['uid'], $arr, $abook)) {
$item_result = item_store($arr);
if ($item_result['success']) {
$item_id = $item_result['item_id'];
if ($item_source && in_array($item_result['item']['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
event_addtocal($item_id, $channel['channel_id']);
}
$parr = [
'item_id' => $item_id,
'item' => $arr,
@@ -1912,7 +1945,8 @@ class Libzot {
add_source_route($item_id, $sender);
}
}
$DR->update(($item_id) ? 'posted' : 'storage failed: ' . $item_result['message']);
$DR->update(($item_id) ? (($item_result['item']['item_blocked'] === ITEM_MODERATED) ? 'accepted for moderation' : 'posted') : 'storage failed: ' . $item_result['message']);
$result[] = $DR->get();
} else {
$DR->update('post ignored');
@@ -1929,7 +1963,7 @@ class Libzot {
retain_item($stored['item']['parent']);
}
if ($relay && $item_id) {
if ($relay && $item_id && $stored['item_blocked'] !== ITEM_MODERATED) {
logger('Invoking relay');
Master::Summon(['Notifier', 'relay', intval($item_id)]);
$DR->addto_update('relayed');
@@ -1997,22 +2031,16 @@ class Libzot {
// logger($AS->debug());
if(empty($AS->actor['id'])) {
logger('No actor id!');
logger('No actor id: ' . print_r($AS, true));
continue;
}
$r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s' order by hubloc_id desc",
dbesc($AS->actor['id'])
);
$r = Activity::get_actor_hublocs($AS->actor['id']);
$r = self::zot_record_preferred($r);
if (!$r) {
$y = import_author_xchan(['url' => $AS->actor['id']]);
if ($y) {
$r = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s'",
dbesc($AS->actor['id'])
);
$r = Activity::get_actor_hublocs($AS->actor['id']);
$r = self::zot_record_preferred($r);
}
if (!$r) {
@@ -2022,22 +2050,29 @@ class Libzot {
}
if (isset($AS->obj['actor']['id']) && $AS->obj['actor']['id'] !== $AS->actor['id']) {
$y = import_author_xchan(['url' => $AS->obj['actor']['id']]);
if (!$y) {
logger('FOF Activity: no object actor');
continue;
$ro = Activity::get_actor_hublocs($AS->obj['actor']['id']);
$ro = self::zot_record_preferred($ro);
if (!$ro) {
$y = import_author_xchan(['url' => $AS->obj['actor']['id']]);
if ($y) {
$ro = Activity::get_actor_hublocs($AS->obj['actor']['id']);
$ro = self::zot_record_preferred($ro);
}
if (!$ro) {
logger('FOF Activity: no obj actor');
continue;
}
}
}
$arr = Activity::decode_note($AS);
if (!$arr) {
logger('FOF Activity: could not decode');
continue;
}
if ($r) {
$arr['author_xchan'] = $r['hubloc_hash'];
}
$arr['author_xchan'] = $r['hubloc_hash'];
if ($signer) {
$arr['owner_xchan'] = $signer[0]['hubloc_hash'];
@@ -2341,19 +2376,6 @@ class Libzot {
'deleted' => (intval($hub['hubloc_deleted']) ? true : false)
];
// version compatibility tweaks
if (!strpos($z['url_sig'], '.')) {
$z['url_sig'] = 'sha256.' . $z['url_sig'];
}
if (!$z['id_url']) {
$z['id_url'] = $z['url'] . '/channel/' . substr($z['address'], 0, strpos($z['address'], '@'));
}
if (!$z['site_id']) {
$z['site_id'] = Libzot::make_xchan_hash($z['url'], $z['sitekey']);
}
$ret[] = $z;
}
}
@@ -2725,12 +2747,12 @@ class Libzot {
$e = $r[0];
$id = $e['channel_id'];
$sys_channel = (intval($e['channel_system']) ? true : false);
$sys_channel = ((empty($e['channel_system'])) ? false : true);
$special_channel = (($e['channel_pageflags'] & PAGE_PREMIUM) ? true : false);
$adult_channel = (($e['channel_pageflags'] & PAGE_ADULT) ? true : false);
$censored = (($e['channel_pageflags'] & PAGE_CENSORED) ? true : false);
$searchable = (($e['channel_pageflags'] & PAGE_HIDDEN) ? false : true);
$deleted = (intval($e['xchan_deleted']) ? true : false);
$deleted = ((empty($e['xchan_deleted'])) ? false : true);
if ($deleted || $censored || $sys_channel)
$searchable = false;
@@ -2782,8 +2804,8 @@ class Libzot {
// Communication details
$ret['id'] = $e['xchan_guid'];
$ret['id_sig'] = self::sign($e['xchan_guid'], $e['channel_prvkey']);
$ret['id'] = $e['channel_guid'];
$ret['id_sig'] = self::sign($e['channel_guid'], $e['channel_prvkey']);
$ret['primary_location'] = [
'address' => $e['xchan_addr'],
@@ -2792,10 +2814,10 @@ class Libzot {
'follow_url' => $e['xchan_follow'],
];
$ret['public_key'] = $e['xchan_pubkey'];
$ret['public_key'] = $e['channel_pubkey'];
$ret['signing_algorithm'] = 'rsa-sha256';
$ret['username'] = $e['channel_address'];
$ret['name'] = $e['xchan_name'];
$ret['name'] = $e['channel_name'];
$ret['name_updated'] = $e['xchan_name_date'];
$ret['photo'] = [
'url' => $e['xchan_photo_l'],

View File

@@ -172,13 +172,12 @@ class Libzotdir {
}
/**
* @brief Checks the directory mode of this hub.
* @brief fetches updates from known directories
*
* Checks the directory mode of this hub to see if it is some form of directory server. If it is,
* get the directory realm of this hub. Fetch a list of all other directory servers in this realm and request
* a directory sync packet. This will contain both directory updates and new ratings. Store these all in the DB.
* In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored
* directly if the rater's signature matches.
* a directory sync packet. Store these all in the DB.
* In the case of updates, we will query each of them asynchronously from a poller task.
*
* @param int $dirmode;
*/
@@ -233,6 +232,8 @@ class Libzotdir {
if (! $r)
return;
$dir_trusted_hosts = array_merge(get_directory_fallback_servers(), get_config('system', 'trusted_directory_servers', []));
foreach ($r as $rr) {
if (! $rr['site_directory'])
continue;
@@ -264,31 +265,65 @@ class Libzotdir {
if (is_array($j['transactions']) && count($j['transactions'])) {
foreach ($j['transactions'] as $t) {
if (empty($t['hash']) || empty($t['transaction_id']) || empty($t['address'])) {
if (empty($t['hash']) || empty($t['host']) || empty($t['address'])) {
continue;
}
$r = q("select * from updates where ud_guid = '%s' limit 1",
dbesc($t['transaction_id'])
$r = q("select * from updates where ud_hash = '%s' limit 1",
dbesc($t['hash'])
);
if($r)
continue;
$ud_flags = 0;
if (is_array($t['flags']) && in_array('deleted',$t['flags']))
$ud_flags |= UPDATE_FLAGS_DELETED;
if (is_array($t['flags']) && in_array('forced',$t['flags']))
$ud_flags |= UPDATE_FLAGS_FORCED;
if ($r) {
$update = 0;
$z = q("insert into updates ( ud_hash, ud_guid, ud_date, ud_flags, ud_addr )
values ( '%s', '%s', '%s', %d, '%s' ) ",
dbesc($t['hash']),
dbesc($t['transaction_id']),
dbesc($t['timestamp']),
intval($ud_flags),
dbesc($t['address'])
);
// no need to look at updates that originated from our own site
if ($t['host'] === z_root()) {
continue;
}
// there is more recent xchan information
if ($r[0]['ud_date'] <= $t['timestamp']) {
$update = 1;
}
// the host is trusted and flags have changed - update flags immediately
if (in_array($t['host'], $dir_trusted_hosts) &&
$rr['site_url'] === $t['host'] &&
intval($r[0]['ud_flags']) !== intval($t['flags'])) {
q("UPDATE updates SET ud_update = %d, ud_flags = %d WHERE ud_id = %d",
intval($update),
intval($t['flags']),
dbesc($r[0]['ud_id'])
);
q("UPDATE xchan SET xchan_censored = %d WHERE xchan_hash = '%s'",
intval($t['flags']),
dbesc($r[0]['ud_hash'])
);
continue;
}
if (!$update) {
continue;
}
q("UPDATE updates SET ud_update = %d WHERE ud_id = %d",
intval($update),
dbesc($r[0]['ud_id'])
);
}
else {
q("insert into updates ( ud_hash, ud_host, ud_date, ud_addr, ud_update, ud_flags )
values ( '%s', '%s', '%s', '%s', 1, %d) ",
dbesc($t['hash']),
dbesc($t['host']),
dbesc($t['timestamp']),
dbesc($t['address']),
dbesc(in_array($t['host'], $dir_trusted_hosts) ? $t['flags'] : 0)
);
}
}
}
}
@@ -303,8 +338,9 @@ class Libzotdir {
*
* Ignore updating records marked as deleted.
*
* If successful, sets ud_last in the DB to the current datetime for this
* If successful, sets ud_updated in the DB to the current datetime for this
* reddress/webbie.
* Else update ud_last so we can stop trying after 7 days (Daemon/Poller.php)
*
* @param array $ud Entry from update table
*/
@@ -313,32 +349,44 @@ class Libzotdir {
logger('update_directory_entry: ' . print_r($ud,true), LOGGER_DATA);
if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
$success = false;
$zf = [];
// TODO: remove this check after all directory servers have version > 8.4
// ud_addr will always be the channel url at that time
$href = ((strpos($ud['ud_addr'], '://') === false) ? Webfinger::zot_url(punify($ud['ud_addr'])) : punify($ud['ud_addr']));
if($href) {
$zf = Zotfinger::exec($href);
if($zf && array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
$xc = Libzot::import_xchan($zf['data']);
// xchan_hash mismatch - this can happen after a site re-install at the same url
if ($xc['success'] && $xc['hash'] !== $ud['ud_hash']) {
self::delete_by_hash($ud['ud_hash']);
}
// if the channel was deleted - delete the entry in updates
if (!empty($zf['data']['deleted_locally'])) {
self::delete_by_hash($ud['ud_hash']);
}
$href = Webfinger::zot_url(punify($ud['ud_addr']));
if($href) {
$zf = Zotfinger::exec($href);
}
if(array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
$xc = Libzot::import_xchan($zf['data'], 0, $ud);
// This is a workaround for a missing xchan_updated column
// TODO: implement xchan_updated in the xchan table and update this column instead
if($zf['data']['primary_location']['address'] && $zf['data']['primary_location']['url']) {
if(!empty($zf['data']['primary_location']['url'])) {
q("UPDATE hubloc SET hubloc_updated = '%s' WHERE hubloc_id_url = '%s' AND hubloc_primary = 1",
dbesc(datetime_convert()),
dbesc($zf['data']['primary_location']['url'])
);
}
}
else {
q("update updates set ud_last = '%s' where ud_addr = '%s'",
dbesc(datetime_convert()),
dbesc($ud['ud_addr'])
);
return true;
}
}
q("UPDATE updates SET ud_addr = '%s', ud_last = '%s' WHERE ud_hash = '%s'",
dbesc($href ? $href : $ud['ud_addr']),
dbesc(datetime_convert()),
dbesc($ud['ud_hash'])
);
return false;
}
@@ -353,85 +401,78 @@ class Libzotdir {
*/
static function local_dir_update($uid, $force) {
logger('local_dir_update uid: ' . $uid, LOGGER_DEBUG);
logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG);
$p = q("select channel.channel_hash, channel_address, channel_timezone, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1",
$p = q("select channel.channel_hash, channel_address, channel_timezone, profile.*, xchan.xchan_hidden, xchan.xchan_url from profile left join channel on channel_id = uid left join xchan on channel_hash = xchan_hash where profile.uid = %d and profile.is_default = 1",
intval($uid)
);
$profile = array();
$profile['encoding'] = 'zot';
if ($p) {
$hash = $p[0]['channel_hash'];
$profile['description'] = $p[0]['pdesc'];
$profile['birthday'] = $p[0]['dob'];
if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
$profile['age'] = $age;
$profile['gender'] = $p[0]['gender'];
$profile['marital'] = $p[0]['marital'];
$profile['sexual'] = $p[0]['sexual'];
$profile['locale'] = $p[0]['locality'];
$profile['region'] = $p[0]['region'];
$profile['postcode'] = $p[0]['postal_code'];
$profile['country'] = $p[0]['country_name'];
$profile['about'] = $p[0]['about'];
$profile['homepage'] = $p[0]['homepage'];
$profile['hometown'] = $p[0]['hometown'];
if ($p[0]['keywords']) {
$tags = array();
$k = explode(' ', $p[0]['keywords']);
if ($k)
foreach ($k as $kk)
if (trim($kk))
$tags[] = trim($kk);
if ($tags)
$profile['keywords'] = $tags;
}
$hidden = (1 - intval($p[0]['publish']));
logger('hidden: ' . $hidden);
$r = q("select xchan_hidden from xchan where xchan_hash = '%s'",
dbesc($p[0]['channel_hash'])
);
if(intval($r[0]['xchan_hidden']) != $hidden) {
$r = q("update xchan set xchan_hidden = %d where xchan_hash = '%s'",
intval($hidden),
dbesc($hash)
);
}
$arr = [ 'channel_id' => $uid, 'hash' => $hash, 'profile' => $profile ];
call_hooks('local_dir_update', $arr);
$address = channel_reddress($p[0]);
if (perm_is_allowed($uid, '', 'view_profile')) {
self::import_directory_profile($hash, $arr['profile'], $address, 0);
}
else {
// they may have made it private
q("delete from xprof where xprof_hash = '%s'",
dbesc($hash)
);
q("delete from xtag where xtag_hash = '%s'",
dbesc($hash)
);
}
if (!$p) {
logger('profile not found');
return;
}
$ud_hash = random_string() . '@' . \App::get_hostname();
self::update_modtime($hash, $ud_hash, channel_reddress($p[0]),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
$profile = [];
$profile['encoding'] = 'zot';
$hash = $p[0]['channel_hash'];
$profile['description'] = $p[0]['pdesc'];
$profile['birthday'] = $p[0]['dob'];
if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
$profile['age'] = $age;
$profile['gender'] = $p[0]['gender'];
$profile['marital'] = $p[0]['marital'];
$profile['sexual'] = $p[0]['sexual'];
$profile['locale'] = $p[0]['locality'];
$profile['region'] = $p[0]['region'];
$profile['postcode'] = $p[0]['postal_code'];
$profile['country'] = $p[0]['country_name'];
$profile['about'] = $p[0]['about'];
$profile['homepage'] = $p[0]['homepage'];
$profile['hometown'] = $p[0]['hometown'];
if ($p[0]['keywords']) {
$tags = array();
$k = explode(' ', $p[0]['keywords']);
if ($k)
foreach ($k as $kk)
if (trim($kk))
$tags[] = trim($kk);
if ($tags)
$profile['keywords'] = $tags;
}
$hidden = (1 - intval($p[0]['publish']));
logger('hidden: ' . $hidden);
if(intval($p[0]['xchan_hidden']) !== $hidden) {
q("update xchan set xchan_hidden = %d where xchan_hash = '%s'",
intval($hidden),
dbesc($hash)
);
}
$arr = [ 'channel_id' => $uid, 'hash' => $hash, 'profile' => $profile ];
call_hooks('local_dir_update', $arr);
if (perm_is_allowed($uid, '', 'view_profile')) {
self::import_directory_profile($hash, $arr['profile']);
}
else {
// they may have made it private
q("delete from xprof where xprof_hash = '%s'",
dbesc($hash)
);
q("delete from xtag where xtag_hash = '%s'",
dbesc($hash)
);
}
self::update($hash, $p[0]['xchan_url']);
}
@@ -441,13 +482,10 @@ class Libzotdir {
*
* @param string $hash
* @param array $profile
* @param string $addr
* @param number $ud_flags (optional) UPDATE_FLAGS_UPDATED
* @param number $suppress_update (optional) default 0
* @return boolean $updated if something changed
*/
static function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLAGS_UPDATED, $suppress_update = 0) {
static function import_directory_profile($hash, $profile) {
logger('import_directory_profile', LOGGER_DEBUG);
if (! $hash)
@@ -480,7 +518,12 @@ class Libzotdir {
$clean = array();
if (array_key_exists('keywords', $profile) and is_array($profile['keywords'])) {
self::import_directory_keywords($hash,$profile['keywords']);
foreach ($profile['keywords'] as $kw) {
if (in_array($kw, $clean)) {
continue;
}
$kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false));
$kw = trim($kw, ',');
$clean[] = $kw;
@@ -587,9 +630,6 @@ class Libzotdir {
*/
call_hooks('import_directory_profile', $d);
if (($d['update']) && (! $suppress_update))
self::update_modtime($arr['xprof_hash'],random_string() . '@' . \App::get_hostname(), $addr, $ud_flags);
return $d['update'];
}
@@ -607,6 +647,10 @@ class Libzotdir {
dbesc($hash)
);
$xchan = q("select xchan_censored from xchan where xchan_hash = '%s'",
dbesc($hash)
);
if($r) {
foreach($r as $rr)
$existing[] = $rr['xtag_term'];
@@ -614,6 +658,10 @@ class Libzotdir {
$clean = array();
foreach($keywords as $kw) {
if (in_array($kw, $clean)) {
continue;
}
$kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false));
$kw = trim($kw, ',');
$clean[] = $kw;
@@ -628,9 +676,10 @@ class Libzotdir {
}
foreach($clean as $x) {
if(! in_array($x, $existing)) {
$r = q("insert into xtag ( xtag_hash, xtag_term, xtag_flags) values ( '%s' ,'%s', 0 )",
$r = q("insert into xtag ( xtag_hash, xtag_term, xtag_flags) values ( '%s' ,'%s', %d )",
dbesc($hash),
dbesc($x)
dbesc($x),
intval($xchan[0]['xchan_censored'])
);
}
}
@@ -640,13 +689,12 @@ class Libzotdir {
/**
* @brief
*
* @param string $hash
* @param string $guid
* @param string $addr
* @param int $flags (optional) default 0
* @param string $hash the channel hash
* @param string $addr the channel url
* @param bool $bump_date (optional) default true
*/
static function update_modtime($hash, $guid, $addr, $flags = 0) {
static function update($hash, $addr, $bump_date = true, $flag = null) {
$dirmode = intval(get_config('system', 'directory_mode'));
@@ -654,26 +702,70 @@ class Libzotdir {
return;
}
if (empty($hash) || empty($guid) || empty($addr)) {
if (empty($hash) || empty($addr)) {
return;
}
if($flags) {
q("insert into updates (ud_hash, ud_guid, ud_date, ud_flags, ud_addr ) values ( '%s', '%s', '%s', %d, '%s' )",
dbesc($hash),
dbesc($guid),
dbesc(datetime_convert()),
intval($flags),
dbesc($addr)
);
$u = q("SELECT * FROM updates WHERE ud_hash = '%s' LIMIT 1",
dbesc($hash)
);
$date_sql = '';
if ($bump_date) {
$date_sql = "ud_date = '" . dbesc(datetime_convert()) . "',";
}
else {
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and not (ud_flags & %d)>0 ",
intval(UPDATE_FLAGS_UPDATED),
$flag_sql = '';
if ($flag !== null) {
$flag_sql = "ud_flags = '" . intval($flag) . "',";
}
if ($u) {
$x = q("UPDATE updates SET $date_sql $flag_sql ud_last = '%s', ud_host = '%s', ud_addr = '%s', ud_update = 0 WHERE ud_id = %d",
dbesc(NULL_DATE),
dbesc(z_root()),
dbesc($addr),
intval(UPDATE_FLAGS_UPDATED)
intval($u[0]['ud_id'])
);
return;
}
q("INSERT INTO updates (ud_hash, ud_host, ud_date, ud_addr, ud_flags) VALUES ( '%s', '%s', '%s', '%s', %d )",
dbesc($hash),
dbesc(z_root()),
dbesc(datetime_convert()),
dbesc($addr),
intval($flag)
);
return;
}
/**
* @brief deletes a entry in updates by hash
*
* @param string $hash the channel hash
* @return boolean
*/
static function delete_by_hash($hash) {
if (!$hash) {
return false;
}
$x = q("DELETE FROM updates WHERE ud_hash = '%s'",
dbesc($hash)
);
if ($x) {
return true;
}
return false;
}
}

View File

@@ -57,7 +57,6 @@ class Queue {
outq_priority = outq_priority + %d,
outq_scheduled = '%s'
WHERE outq_hash = '%s'",
dbesc(datetime_convert()),
intval($add_priority),
dbesc($next),
@@ -85,29 +84,16 @@ class Queue {
// entries still exist for it. This fixes an issue where one immediate delivery left everything
// else for that site undeliverable since all the other entries had been pushed far into the future.
$x = null;
$sql_quirks = ((get_config('system', 'db_skip_locked_supported')) ? 'SKIP LOCKED' : 'NOWAIT');
q("START TRANSACTION");
$r = q("SELECT outq_hash FROM outq WHERE outq_posturl = '%s' LIMIT 1 FOR UPDATE $sql_quirks",
$r = q("SELECT outq_hash, outq_posturl FROM outq WHERE outq_posturl = '%s' LIMIT 1",
dbesc($record[0]['outq_posturl'])
);
if ($r) {
$x = q("UPDATE outq SET outq_scheduled = '%s' WHERE outq_hash = '%s'",
dbesc(datetime_convert()),
dbesc($r[0]['outq_hash'])
$hashes = ids_to_querystr($r, 'outq_hash', true);
$x = q("UPDATE outq SET outq_scheduled = '%s' WHERE outq_hash IN ($hashes)",
dbesc(datetime_convert())
);
}
if ($x) {
q("COMMIT");
}
else {
q("ROLLBACK");
}
}
}
@@ -260,7 +246,7 @@ class Queue {
if($result['success']) {
logger('deliver: remote zot delivery succeeded to ' . $outq['outq_posturl']);
Libzot::process_response($outq['outq_posturl'],$result, $outq);
Libzot::process_response($outq['outq_posturl'], $result, $outq);
}
else {
logger('deliver: remote zot delivery failed to ' . $outq['outq_posturl']);

View File

@@ -24,7 +24,8 @@ class QueueWorker {
// Exceptions for processtimeout ($workermaxage) value.
// Currently the value is overriden with 3600 seconds (1h).
public static $long_running_cmd = [
'Queue'
'Queue',
'Expire'
];
private static function qstart() {
@@ -62,6 +63,8 @@ class QueueWorker {
return;
}
logger('queueworker_stats_summon: cmd:' . $argv[0] . ' ' . 'timestamp:' . time());
self::qstart();
$r = q("INSERT INTO workerq (workerq_priority, workerq_data, workerq_uuid, workerq_cmd) VALUES (%d, '%s', '%s', '%s')",
intval($priority),
@@ -147,6 +150,10 @@ class QueueWorker {
);
if ($r) {
// TODO: some long running services store their pid in config.procid.daemon
// we could possibly check if a pid exist and check if the process is still alive
// prior to reseting workerq_reservationid
$ids = ids_to_querystr($r, 'workerq_id');
$u = dbq("update workerq set workerq_reservationid = null where workerq_id in ($ids)");
}
@@ -159,7 +166,7 @@ class QueueWorker {
//usleep(self::$workersleep);
$workers = dbq("select count(distinct workerq_reservationid) as total from workerq where workerq_reservationid is not null");
$workers = dbq("select count(*) as total from workerq where workerq_reservationid is not null");
logger("WORKERCOUNT: " . $workers[0]['total'], LOGGER_DEBUG);
return intval($workers[0]['total']);
@@ -172,7 +179,7 @@ class QueueWorker {
$wid = uniqid('', true);
usleep(mt_rand(300000, 1000000)); //Sleep .3 - 1 seconds before creating a new worker.
//usleep(mt_rand(300000, 1000000)); //Sleep .3 - 1 seconds before creating a new worker.
$workers = self::GetWorkerCount();
@@ -197,7 +204,7 @@ class QueueWorker {
$work = dbq("SELECT workerq_id, workerq_cmd FROM workerq WHERE workerq_reservationid IS NULL ORDER BY workerq_priority DESC, workerq_id ASC LIMIT 1 FOR UPDATE $sql_quirks");
if (!$work) {
self::qcommit();
self::qrollback();
return false;
}
@@ -294,12 +301,16 @@ class QueueWorker {
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
$argv = flatten_array_recursive($argv);
$argc = count($argv);
$rnd = random_string();
$rnd = random_string(16);
logger('PROCESSING: ' . $rnd . ' ' . print_r($argv[0], true));
$start_timestamp = microtime(true);
$cls::run($argc, $argv);
logger('logger_stats_data cmd:' . $argv[0] . ' start:' . $start_timestamp . ' ' . 'end:' . microtime(true) . ' meta:' . $rnd);
logger('COMPLETED: ' . $rnd);
// @FIXME: Right now we assume that if we get a return, everything is OK.

View File

@@ -101,7 +101,7 @@ class ThreadItem {
$conv = $this->get_conversation();
$observer = $conv->get_observer();
$acl = new AccessList(false);
$acl = new AccessList([]);
$acl->set($item);
$lock = ((intval($item['item_private']) || ($item['uid'] == local_channel() && $acl->is_private()))
@@ -185,7 +185,7 @@ class ThreadItem {
$filer = ((($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) ? t("Save to Folder") : false);
$profile_avatar = $item['author']['xchan_photo_m'];
$profile_avatar = $item['author']['xchan_photo_s'];
$profile_link = chanlink_hash($item['author_xchan']);
$profile_name = $item['author']['xchan_name'];
@@ -197,7 +197,7 @@ class ThreadItem {
$response_verbs = array('like');
if(feature_enabled($conv->get_profile_owner(),'dislike'))
$response_verbs[] = 'dislike';
if($item['obj_type'] === ACTIVITY_OBJ_EVENT) {
if(in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
$response_verbs[] = 'attendyes';
$response_verbs[] = 'attendno';
$response_verbs[] = 'attendmaybe';
@@ -299,7 +299,7 @@ class ThreadItem {
}
$has_event = false;
if(($item['obj_type'] === ACTIVITY_OBJ_EVENT) && $conv->get_profile_owner() == local_channel())
if((in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) && $conv->get_profile_owner() == local_channel())
$has_event = true;
$like = [];
@@ -503,7 +503,11 @@ class ThreadItem {
'thread_level' => $thread_level,
'settings' => $settings,
'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? gen_link_id($item['thr_parent']) : ''),
'contact_id' => (($contact) ? $contact['abook_id'] : '')
'contact_id' => (($contact) ? $contact['abook_id'] : ''),
'moderate' => ($item['item_blocked'] == ITEM_MODERATED),
'moderate_approve' => t('Approve'),
'moderate_delete' => t('Delete'),
'rtl' => in_array($item['lang'], rtl_languages())
);
@@ -870,7 +874,7 @@ class ThreadItem {
if($this->is_toplevel() && ($this->get_data_value('author_xchan') != $this->get_data_value('owner_xchan'))) {
$this->owner_url = chanlink_hash($this->data['owner']['xchan_hash']);
$this->owner_photo = $this->data['owner']['xchan_photo_m'];
$this->owner_photo = $this->data['owner']['xchan_photo_s'];
$this->owner_name = $this->data['owner']['xchan_name'];
$this->wall_to_wall = true;
}

View File

@@ -4,18 +4,30 @@ namespace Zotlabs\Lib;
class ThreadListener {
public static function isEnabled() {
return Config::Get('system','enable_thread_listener');
}
static public function store($target_id,$portable_id,$ltype = 0) {
if (!self::isEnabled()) {
return true;
}
$x = self::fetch($target_id,$portable_id,$ltype = 0);
if(! $x) {
if(! $x) {
$r = q("insert into listeners ( target_id, portable_id, ltype ) values ( '%s', '%s' , %d ) ",
dbesc($target_id),
dbesc($portable_id),
intval($ltype)
);
}
}
}
static public function fetch($target_id,$portable_id,$ltype = 0) {
if (!self::isEnabled()) {
return false;
}
$x = q("select * from listeners where target_id = '%s' and portable_id = '%s' and ltype = %d limit 1",
dbesc($target_id),
dbesc($portable_id),
@@ -28,6 +40,10 @@ class ThreadListener {
}
static public function fetch_by_target($target_id,$ltype = 0) {
if (!self::isEnabled()) {
return [];
}
$x = q("select * from listeners where target_id = '%s' and ltype = %d",
dbesc($target_id),
intval($ltype)

View File

@@ -35,9 +35,13 @@ class Zotfinger {
$result = [];
$redirects = 0;
$x = z_post_url($resource,$data,$redirects, [ 'headers' => $h ] );
logger('fetch: ' . print_r($x,true));
$start_timestamp = microtime(true);
$x = z_post_url($resource,$data,$redirects, [ 'headers' => $h ] );
logger('logger_stats_data cmd:Zotfinger' . ' start:' . $start_timestamp . ' ' . 'end:' . microtime(true) . ' meta:' . $resource . '#' . random_string(16));
btlogger('Zotfinger');
logger('fetch: ' . print_r($x,true), LOGGER_DATA);
if (in_array(intval($x['return_code']), [ 404, 410 ]) && $recurse) {
@@ -74,7 +78,7 @@ class Zotfinger {
$result['data'] = json_decode(Crypto::unencapsulate($result['data'],get_config('system','prvkey')),true);
}
logger('decrypted: ' . print_r($result,true));
logger('decrypted: ' . print_r($result,true), LOGGER_DATA);
return $result;
}

View File

@@ -346,7 +346,7 @@ class Accounts {
'$users' => $users,
'$msg' => t('Message')
));
$o .= paginate($a);
$o .= paginate();
return $o;
}

View File

@@ -168,7 +168,7 @@ class Channels {
'$baseurl' => z_root(),
'$channels' => $channels,
));
$o .= paginate($a);
$o .= paginate();
return $o;
}

View File

@@ -41,7 +41,7 @@ class Queueworker extends Controller {
$content .= "<H4>There are " . $r[0]['total'] . " queue items to be processed.</H4>";
$r = dbq("select count(distinct workerq_reservationid) as qworkers from workerq where workerq_reservationid is not null");
$r = dbq("select count(*) as qworkers from workerq where workerq_reservationid is not null");
$content .= "<H4>Active workers: " . $r[0]['qworkers'] . "</H4>";

View File

@@ -7,12 +7,12 @@ class Security {
function post() {
check_form_security_token_redirectOnErr('/admin/security', 'admin_security');
$allowed_email = ((x($_POST,'allowed_email')) ? notags(trim($_POST['allowed_email'])) : '');
$not_allowed_email = ((x($_POST,'not_allowed_email')) ? notags(trim($_POST['not_allowed_email'])) : '');
set_config('system','allowed_email', $allowed_email);
set_config('system','not_allowed_email', $not_allowed_email);
set_config('system','not_allowed_email', $not_allowed_email);
$block_public = ((x($_POST,'block_public')) ? True : False);
set_config('system','block_public',$block_public);
@@ -25,22 +25,22 @@ class Security {
$ws = $this->trim_array_elems(explode("\n",$_POST['whitelisted_sites']));
set_config('system','whitelisted_sites',$ws);
$bs = $this->trim_array_elems(explode("\n",$_POST['blacklisted_sites']));
set_config('system','blacklisted_sites',$bs);
$wc = $this->trim_array_elems(explode("\n",$_POST['whitelisted_channels']));
set_config('system','whitelisted_channels',$wc);
$bc = $this->trim_array_elems(explode("\n",$_POST['blacklisted_channels']));
set_config('system','blacklisted_channels',$bc);
$embed_sslonly = ((x($_POST,'embed_sslonly')) ? True : False);
set_config('system','embed_sslonly',$embed_sslonly);
$we = $this->trim_array_elems(explode("\n",$_POST['embed_allow']));
set_config('system','embed_allow',$we);
$be = $this->trim_array_elems(explode("\n",$_POST['embed_deny']));
set_config('system','embed_deny',$be);
@@ -49,47 +49,54 @@ class Security {
$inline_pdf = ((x($_POST,'inline_pdf')) ? intval($_POST['inline_pdf']) : 0);
set_config('system', 'inline_pdf' , $inline_pdf);
$ts = ((x($_POST,'transport_security')) ? True : False);
set_config('system','transport_security_header',$ts);
$cs = ((x($_POST,'content_security')) ? True : False);
set_config('system','content_security_policy',$cs);
$trusted_directory_servers = $this->trim_array_elems(explode("\n", $_POST['trusted_directory_servers']));
set_config('system', 'trusted_directory_servers', $trusted_directory_servers);
goaway(z_root() . '/admin/security');
}
function get() {
$whitesites = get_config('system','whitelisted_sites');
$whitesites_str = ((is_array($whitesites)) ? implode("\n",$whitesites) : '');
$blacksites = get_config('system','blacklisted_sites');
$blacksites_str = ((is_array($blacksites)) ? implode("\n",$blacksites) : '');
$whitechannels = get_config('system','whitelisted_channels');
$whitechannels_str = ((is_array($whitechannels)) ? implode("\n",$whitechannels) : '');
$blackchannels = get_config('system','blacklisted_channels');
$blackchannels_str = ((is_array($blackchannels)) ? implode("\n",$blackchannels) : '');
$whiteembeds = get_config('system','embed_allow');
$whiteembeds_str = ((is_array($whiteembeds)) ? implode("\n",$whiteembeds) : '');
$blackembeds = get_config('system','embed_deny');
$blackembeds_str = ((is_array($blackembeds)) ? implode("\n",$blackembeds) : '');
$trusted_directory_servers = get_config('system', 'trusted_directory_servers');
$trusted_directory_servers_str = ((is_array($trusted_directory_servers)) ? implode("\n", $trusted_directory_servers) : '');
$is_dir = (intval(get_config('system', 'directory_mode', DIRECTORY_MODE_NORMAL)) !== DIRECTORY_MODE_NORMAL);
$embed_coop = intval(get_config('system','embed_coop'));
if((! $whiteembeds) && (! $blackembeds)) {
$embedhelp1 = t("By default, unfiltered HTML is allowed in embedded media. This is inherently insecure.");
}
$embedhelp2 = t("The recommended setting is to only allow unfiltered HTML from the following sites:");
$embedhelp2 = t("The recommended setting is to only allow unfiltered HTML from the following sites:");
$embedhelp3 = t("https://youtube.com/<br />https://www.youtube.com/<br />https://youtu.be/<br />https://vimeo.com/<br />https://soundcloud.com/<br />");
$embedhelp4 = t("All other embedded content will be filtered, <strong>unless</strong> embedded content from that site is explicitly blocked.");
@@ -99,7 +106,7 @@ class Security {
'$page' => t('Security'),
'$form_security_token' => get_form_security_token('admin_security'),
'$block_public' => array('block_public', t("Block public"), get_config('system','block_public'), t("Check to block public access to all otherwise public personal pages on this site unless you are currently authenticated.")),
'$cloud_noroot' => [ 'cloud_noroot', t('Provide a cloud root directory'), 1 - intval(get_config('system','cloud_disable_siteroot')), t('The cloud root directory lists all channel names which provide public files') ],
'$cloud_noroot' => [ 'cloud_noroot', t('Provide a cloud root directory'), 1 - intval(get_config('system','cloud_disable_siteroot')), t('The cloud root directory lists all channel names which provide public files') ],
'$cloud_disksize' => [ 'cloud_disksize', t('Show total disk space available to cloud uploads'), intval(get_config('system','cloud_report_disksize')), '' ],
'$transport_security' => array('transport_security', t('Set "Transport Security" HTTP header'),intval(get_config('system','transport_security_header')),''),
'$content_security' => array('content_security', t('Set "Content Security Policy" HTTP header'),intval(get_config('system','content_security_policy')),''),
@@ -115,6 +122,8 @@ class Security {
'$thumbnail_security' => [ 'thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system','thumbnail_security',0), t("WARNING: SVG images may contain malicious code.") ],
'$inline_pdf' => [ 'inline_pdf', t("Allow embedded (inline) PDF files"), get_config('system','inline_pdf',0), '' ],
'$trusted_directory_servers' => (($is_dir) ? ['trusted_directory_servers', t('Additional trusted directory server URLs'), $trusted_directory_servers_str, t('Accept directory flags (spam, nsfw) from those servers. One per line like https://example.tld')] : ''),
// '$embed_coop' => array('embed_coop', t('Cooperative embed security'), $embed_coop, t('Enable to share embed security with other compatible sites/hubs')),
'$submit' => t('Submit')
@@ -124,7 +133,7 @@ class Security {
function trim_array_elems($arr) {
$narr = array();
if($arr && is_array($arr)) {
for($x = 0; $x < count($arr); $x ++) {
$y = trim($arr[$x]);
@@ -134,6 +143,6 @@ class Security {
}
return $narr;
}
}

View File

@@ -67,7 +67,6 @@ class Site {
$open_pubstream = ((x($_POST,'open_pubstream')) ? True : False);
$login_on_homepage = ((x($_POST,'login_on_homepage')) ? True : False);
$enable_context_help = ((x($_POST,'enable_context_help')) ? True : False);
$global_directory = ((x($_POST,'directory_submit_url')) ? notags(trim($_POST['directory_submit_url'])) : '');
$no_community_page = !((x($_POST,'no_community_page')) ? True : False);
$default_expire_days = ((array_key_exists('default_expire_days',$_POST)) ? intval($_POST['default_expire_days']) : 0);
$active_expire_days = ((array_key_exists('active_expire_days',$_POST)) ? intval($_POST['active_expire_days']) : 7);
@@ -181,7 +180,7 @@ class Site {
set_config('system', 'admininfo', $admininfo);
}
set_config('system','siteinfo',$siteinfo);
set_config('system', 'language', $language);
//set_config('system', 'language', $language);
set_config('system', 'theme', $theme);
// if ( $theme_mobile === '---' ) {
// del_config('system', 'mobile_theme');
@@ -206,11 +205,6 @@ class Site {
set_config('system','site_firehose', $site_firehose);
set_config('system','open_pubstream', $open_pubstream);
//set_config('system','force_queue_threshold', $force_queue);
if ($global_directory == '') {
del_config('system', 'directory_submit_url');
} else {
set_config('system', 'directory_submit_url', $global_directory);
}
set_config('system','no_community_page', $no_community_page);
set_config('system','no_utf', $no_utf);
@@ -283,7 +277,7 @@ class Site {
}
$dir_choices = null;
$dirmode = get_config('system','directory_mode');
$dirmode = get_config('system', 'directory_mode', DIRECTORY_MODE_NORMAL);
$realm = get_directory_realm();
// directory server should not be set or settable unless we are a directory client
@@ -301,6 +295,12 @@ class Site {
$dir_choices[$xx['site_url']] = $xx['site_url'];
}
}
if ($realm === DIRECTORY_REALM) {
$fallback_servers = get_directory_fallback_servers();
foreach ($fallback_servers as $fallback_server) {
$dir_choices[$fallback_server] = $fallback_server;
}
}
}
/* Banner */
@@ -425,7 +425,7 @@ class Site {
'$banner' => array('banner', t("Banner/Logo"), $banner, t('Unfiltered HTML/CSS/JS is allowed')),
'$admininfo' => array('admininfo', t("Administrator Information"), $admininfo, t("Contact information for site administrators. Displayed on siteinfo page. BBCode can be used here")),
'$siteinfo' => array('siteinfo', t('Site Information'), get_config('system','siteinfo'), t("Publicly visible description of this site. Displayed on siteinfo page. BBCode can be used here")),
'$language' => array('language', t("System language"), get_config('system','language'), "", $lang_choices),
//'$language' => array('language', t("System language"), get_config('system','language'), "", $lang_choices),
'$theme' => array('theme', t("System theme"), get_config('system','theme'), t("Default system theme - may be over-ridden by user profiles - <a href='#' id='cnftheme'>change theme settings</a>"), $theme_choices),
// '$theme_mobile' => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile_theme'), t("Theme for mobile devices"), $theme_choices_mobile),
// '$site_channel' => array('site_channel', t("Channel to use for this website's static pages"), get_config('system','site_channel'), t("Site Channel")),

View File

@@ -80,10 +80,25 @@ class Themes {
$this->toggle_theme($themes, $theme, $result);
$s = $this->rebuild_theme_table($themes);
if($result)
info( sprintf('Theme %s enabled.', $theme));
else
info( sprintf('Theme %s disabled.', $theme));
if($result) {
if (is_file("view/theme/$theme/php/config.php")){
require_once("view/theme/$theme/php/config.php");
if (function_exists($theme . '_theme_admin_enable')){
call_user_func($theme . '_theme_admin_enable');
}
}
info(sprintf('Theme %s enabled.', $theme));
}
else {
if (is_file("view/theme/$theme/php/config.php")){
require_once("view/theme/$theme/php/config.php");
if (function_exists($theme . '_theme_admin_disable')){
call_user_func($theme . '_theme_admin_disable');
}
}
info(sprintf('Theme %s disabled.', $theme));
}
set_config('system', 'allowed_themes', $s);
goaway(z_root() . '/admin/themes' );

View File

@@ -95,7 +95,7 @@ class Attach extends Controller {
killme();
}
$r = attach_by_hash(argv(1), get_observer_hash(), ((argc() > 2) ? intval(argv(2)) : 0));
$r = attach_by_hash(argv(1), get_observer_hash(), ((argc() > 2) ? intval(argv(2)) : 0), $token);
if (!$r['success']) {
notice($r['message'] . EOL);

View File

@@ -107,7 +107,7 @@ class Blocks extends \Zotlabs\Web\Controller {
$x['pagetitle'] = $_REQUEST['pagetitle'] ?? '';
$a = '';
$editor = status_editor($a,$x,false,'Blocks');
$editor = status_editor($x, false, 'Blocks');
$r = q("select iconfig.iid, iconfig.k, iconfig.v, mid, title, body, mimetype, created, edited from iconfig

View File

@@ -1087,7 +1087,11 @@ class Cdav extends Controller {
$filters['name'] = 'VCALENDAR';
$filters['prop-filters'][0]['name'] = 'VEVENT';
$filters['prop-filters'][0]['is-not-defined'] = null;
$filters['prop-filters'][0]['param-filters'] = null;
$filters['prop-filters'][0]['text-match'] = null;
$filters['comp-filters'][0]['name'] = 'VEVENT';
$filters['comp-filters'][0]['is-not-defined'] = null;
$filters['comp-filters'][0]['time-range']['start'] = $start;
$filters['comp-filters'][0]['time-range']['end'] = $end;

View File

@@ -268,7 +268,7 @@ class Channel extends Controller {
];
$a = '';
$o .= status_editor($a, $x, false, 'Channel');
$o .= status_editor($x, false, 'Channel');
}
// Add pinned content
@@ -284,13 +284,9 @@ class Channel extends Controller {
* Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups
*/
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_deleted = 0
and item.item_unpublished = 0 and item.item_pending_remove = 0
and item.item_blocked = 0 ";
if (!$is_owner)
$item_normal .= "and item.item_delayed = 0 ";
$item_normal = item_normal();
$item_normal_update = item_normal_update();
$sql_extra = item_permissions_sql(App::$profile['profile_uid']);
$sql_extra = item_permissions_sql(App::$profile['profile_uid']);
if (feature_enabled(App::$profile['profile_uid'], 'channel_list_mode') && (!$mid))
$page_mode = 'list';

View File

@@ -181,7 +181,7 @@ class Chat extends Controller {
);
if($x) {
$acl = new AccessList(false);
$acl = new AccessList([]);
$acl->set($x[0]);
$private = $acl->is_private();
@@ -212,7 +212,7 @@ class Chat extends Controller {
'$online' => t('I am online'),
'$bookmark_link' => $bookmark_link,
'$bookmark' => t('Bookmark this room'),
'$feature_encrypt' => ((feature_enabled(local_channel(),'content_encrypt')) ? true : false),
'$feature_encrypt' => ((feature_enabled(App::$profile['profile_uid'], 'content_encrypt')) ? true : false),
'$cipher' => $cipher,
'$linkurl' => t('Please enter a link URL:'),
'$encrypt' => t('Encrypt text'),
@@ -225,7 +225,7 @@ class Chat extends Controller {
$o = '';
$acl = new AccessList($channel);
$acl = new AccessList($channel ?? []);
$channel_acl = $acl->get();
$lockstate = (($channel_acl['allow_cid'] || $channel_acl['allow_gid'] || $channel_acl['deny_cid'] || $channel_acl['deny_gid']) ? 'lock' : 'unlock');

View File

@@ -409,7 +409,6 @@ class Connections extends \Zotlabs\Web\Controller {
'$approve' => t('Approve'),
'$cmd' => App::$cmd,
'$contacts' => $contacts,
'$paginate' => paginate($a),
'$abook_usage_message' => $abook_usage_message,
'$group_label' => t('This is a group/forum channel')
]);

View File

@@ -0,0 +1,188 @@
<?php
namespace Zotlabs\Module;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\Libzot;
use Zotlabs\Web\HTTPSig;
use Zotlabs\Lib\LDSignatures;
use Zotlabs\Lib\ThreadListener;
use Zotlabs\Lib\Config;
use App;
class Conversation extends Controller {
public function init() {
if (ActivityStreams::is_as_request()) {
$item_id = argv(1);
if (!$item_id) {
http_status_exit(404, 'Not found');
}
$portable_id = EMPTY_STR;
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
dbesc(ACTIVITY_FOLLOW),
dbesc(ACTIVITY_UNFOLLOW)
);
$item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
$i = null;
// do we have the item (at all)?
$r = q("select parent_mid from item where mid = '%s' or uuid = '%s' $item_normal order by item_wall desc limit 1",
dbesc(z_root() . '/item/' . $item_id),
dbesc($item_id)
);
if (!$r) {
http_status_exit(404, 'Not found');
}
// process an authenticated fetch
$sigdata = HTTPSig::verify(EMPTY_STR);
if ($sigdata['portable_id'] && $sigdata['header_valid']) {
$portable_id = $sigdata['portable_id'];
observer_auth($portable_id);
// first see if we have a copy of this item's parent owned by the current signer
// include xchans for all zot-like networks - these will have the same guid and public key
$x = q(
"select * from xchan where xchan_hash = '%s'",
dbesc($sigdata['portable_id'])
);
if ($x) {
$xchans = q(
"select xchan_hash from xchan where xchan_hash = '%s' OR ( xchan_guid = '%s' AND xchan_pubkey = '%s' ) ",
dbesc($sigdata['portable_id']),
dbesc($x[0]['xchan_guid']),
dbesc($x[0]['xchan_pubkey'])
);
if ($xchans) {
$hashes = ids_to_querystr($xchans, 'xchan_hash', true);
$i = q(
"select id as item_id from item where mid = '%s' $item_normal and owner_xchan in ( " . protect_sprintf($hashes) . " ) limit 1",
dbesc($r[0]['parent_mid'])
);
}
}
}
elseif (Config::get('system', 'require_authenticated_fetch', false)) {
http_status_exit(403, 'Permission denied');
}
// if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access
// with a bias towards those items owned by channels on this site (item_wall = 1)
$sql_extra = item_permissions_sql(0);
if (!$i) {
$i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
dbesc($r[0]['parent_mid'])
);
}
if (!$i) {
http_status_exit(403, 'Forbidden');
}
$parents_str = ids_to_querystr($i, 'item_id');
$itemspage = 30;
$page = $_REQUEST['page'] ?? 1;
$offset = (intval($page) - 1) * $itemspage;
$items = dbq("SELECT item.*,
item.id AS item_id,
(SELECT count(*) FROM item WHERE item.parent IN ( $parents_str ) $item_normal) AS total
FROM item WHERE item.parent IN ( $parents_str ) $item_normal order by item.id LIMIT $itemspage OFFSET $offset"
);
if (!$items) {
http_status_exit(404, 'Not found');
}
xchan_query($items, true);
$items = fetch_post_tags($items);
$observer = App::get_observer();
$parent = $items[0];
$recips = (($parent['owner']['xchan_network'] === 'activitypub') ? get_iconfig($parent['id'], 'activitypub', 'recips', []) : []);
$to = (($recips && array_key_exists('to', $recips) && is_array($recips['to'])) ? $recips['to'] : null);
$nitems = [];
foreach ($items as $i) {
$mids = [];
if (intval($i['item_private'])) {
if (!$observer) {
continue;
}
/*
// ignore private reshare, possibly from hubzilla
if ($i['verb'] === 'Announce') {
if (!in_array($i['thr_parent'], $mids)) {
$mids[] = $i['thr_parent'];
}
continue;
}
// also ignore any children of the private reshares
if (in_array($i['thr_parent'], $mids)) {
continue;
}
*/
if ((!$to) || (!in_array($observer['xchan_url'], $to))) {
continue;
}
}
$nitems[] = $i;
}
if (!$nitems) {
http_status_exit(404, 'Not found');
}
App::set_pager_total($nitems[0]['total']);
App::set_pager_itemspage($itemspage);
$channel = channelx_by_n($nitems[0]['uid']);
if (!$channel) {
http_status_exit(404, 'Not found');
}
if (!perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_stream')) {
http_status_exit(403, 'Forbidden');
}
$i = Activity::encode_item_collection($nitems, App::$query_string, 'OrderedCollection', $nitems[0]['total']);
if (!$i) {
http_status_exit(404, 'Not found');
}
if ($portable_id && (!intval($nitems[0]['item_private']))) {
$c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
intval($nitems[0]['uid']),
dbesc($portable_id)
);
if (!$c) {
ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
}
}
as_return_and_die($i, $channel);
}
goaway(z_root() . '/item/' . argv(1));
}
}

View File

@@ -4,6 +4,7 @@ namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Libzotdir;
class Dircensor extends Controller {
@@ -15,11 +16,12 @@ class Dircensor extends Controller {
$dirmode = intval(get_config('system','directory_mode'));
if (! ($dirmode == DIRECTORY_MODE_PRIMARY || $dirmode == DIRECTORY_MODE_STANDALONE)) {
if(!in_array($dirmode, [DIRECTORY_MODE_PRIMARY, DIRECTORY_MODE_SECONDARY, DIRECTORY_MODE_STANDALONE])) {
return;
}
$xchan = argv(1);
if(! $xchan) {
return;
}
@@ -32,19 +34,43 @@ class Dircensor extends Controller {
return;
}
$val = (($r[0]['xchan_censored']) ? 0 : 1);
$severity = intval($_REQUEST['severity'] ?? 0);
$flag = DIRECTORY_FLAG_OK;
q("update xchan set xchan_censored = $val where xchan_hash = '%s'",
if ($severity === 1) {
$flag = DIRECTORY_FLAG_UNSAFE;
}
if ($severity === 2) {
$flag = DIRECTORY_FLAG_HIDDEN;
}
Libzotdir::update($xchan, $r[0]['xchan_url'], true, $flag);
q("UPDATE xchan SET xchan_censored = %d WHERE xchan_hash = '%s'",
intval($flag),
dbesc($xchan)
);
if($val) {
q("UPDATE xtag SET xtag_flags = %d WHERE xtag_hash = '%s'",
intval($flag),
dbesc($xchan)
);
if($flag) {
info( t('Entry censored') . EOL);
}
else {
info( t('Entry uncensored') . EOL);
info( t('Entry OK') . EOL);
}
if (isset($_REQUEST['aj'])) {
json_return_and_die([
'success' => 1,
'flag' => $flag
]);
}
goaway(z_root() . '/directory');
}

View File

@@ -151,7 +151,7 @@ class Directory extends Controller {
$url = '';
if(($dirmode == DIRECTORY_MODE_PRIMARY) || ($dirmode == DIRECTORY_MODE_STANDALONE)) {
if(in_array($dirmode, [DIRECTORY_MODE_PRIMARY, DIRECTORY_MODE_SECONDARY, DIRECTORY_MODE_STANDALONE])) {
$url = z_root() . '/dirsearch';
if (is_site_admin()) {
$directory_admin = true;
@@ -191,7 +191,10 @@ class Directory extends Controller {
if(get_config('system','disable_directory_keywords'))
$kw = 0;
$query = $url . '?f=&kw=' . $kw . (($safe_mode != 1) ? '&safe=' . $safe_mode : '');
if (intval($safe_mode) === 0 && $directory_admin)
$safe_mode = -1;
$query = $url . '?f=&kw=' . $kw . (($safe_mode < 1) ? '&safe=' . $safe_mode : '');
if($token)
$query .= '&t=' . $token;
@@ -296,10 +299,11 @@ class Directory extends Controller {
$hometown = ((x($profile,'hometown') == 1) ? html2plain($profile['hometown']) : False);
$about = ((x($profile,'about') == 1) ? zidify_links(bbcode($profile['about'], ['tryoembed' => false])) : False);
if ($about && $safe_mode) {
$about = html2plain($about);
if ($about && $safe_mode > 0) {
$about = strip_tags($about, '<br>');
}
$keywords = ((x($profile,'keywords')) ? $profile['keywords'] : '');
@@ -351,11 +355,15 @@ class Directory extends Controller {
'gender' => $gender,
'pdesc' => $pdesc,
'pdesc_label' => t('Description:'),
'censor' => (($directory_admin) ? 'dircensor/' . $rr['hash'] : ''),
'censor_label' => (($rr['censored']) ? t('Uncensor') : t('Censor')),
'censor' => (($directory_admin) ? 'dircensor/' . $rr['hash'] . '?severity=' . ((intval($rr['censored']) > 0) ? 0 : 1) : ''),
'censor_label' => t('Unsafe'),
'censor_class' => ((intval($rr['censored']) === 1) ? 'active' : ''),
'censor_2' => (($directory_admin) ? 'dircensor/' . $rr['hash'] . '?severity=' . ((intval($rr['censored']) > 1) ? 0 : 2) : ''),
'censor_2_label' => t('Spam'),
'censor_2_class' => ((intval($rr['censored']) > 1) ? 'active' : ''),
'marital' => $marital,
'homepage' => $homepage,
'homepageurl' => (($safe_mode) ? $homepageurl : linkify($homepageurl)),
'homepageurl' => (($safe_mode > 0) ? $homepageurl : linkify($homepageurl)),
'hometown' => $hometown,
'hometown_label' => t('Hometown:'),
'about' => $about,
@@ -436,7 +444,8 @@ class Directory extends Controller {
'$reverse' => t('Reverse Alphabetic'),
'$date' => t('Newest to Oldest'),
'$reversedate' => t('Oldest to Newest'),
'$suggest' => $suggest ? '&suggest=1' : ''
'$suggest' => $suggest ? '&suggest=1' : '',
'$directory_admin' => $directory_admin
));

View File

@@ -15,8 +15,7 @@ class Dirsearch extends Controller {
$ret = array('success' => false);
// logger('request: ' . print_r($_REQUEST,true));
// logger('request: ' . print_r($_REQUEST,true));
$dirmode = intval(get_config('system','directory_mode'));
@@ -25,7 +24,6 @@ class Dirsearch extends Controller {
json_return_and_die($ret);
}
$access_token = $_REQUEST['t'] ?? '';
$token = get_config('system','realm_token');
@@ -41,7 +39,8 @@ class Dirsearch extends Controller {
}
$sql_extra = '';
$keywords_query = '';
$hub_query = '';
$tables = array('name','address','locale','region','postcode','country','gender','marital','sexual','keywords');
@@ -85,9 +84,7 @@ class Dirsearch extends Controller {
// by default use a safe search
$safe = ((x($_REQUEST,'safe'))); // ? intval($_REQUEST['safe']) : 1 );
if ($safe === false)
$safe = 1;
$safe = $_REQUEST['safe'] ?? 1;
if(array_key_exists('sync',$_REQUEST)) {
if($_REQUEST['sync'])
@@ -102,10 +99,10 @@ class Dirsearch extends Controller {
$hub = \App::get_hostname();
}
if($hub)
$hub_query = " and xchan_hash in (select hubloc_hash from hubloc where hubloc_host = '" . protect_sprintf(dbesc($hub)) . "') ";
else
$hub_query = '';
if($hub) {
$hub_query = " and xchan_hash in (select hubloc_hash from hubloc where hubloc_deleted = 0 and hubloc_host = '" . protect_sprintf(dbesc($hub)) . "') ";
}
$sort_order = ((x($_REQUEST,'order')) ? $_REQUEST['order'] : '');
@@ -131,9 +128,16 @@ class Dirsearch extends Controller {
$sql_extra .= $this->dir_query_build($joiner,'xprof_marital',$marital);
if($sexual)
$sql_extra .= $this->dir_query_build($joiner,'xprof_sexual',$sexual);
if($keywords)
if($keywords && $name) {
// this is a general search
$sql_extra .= $this->dir_query_build($joiner,'xprof_keywords',$keywords);
}
if($keywords && !$name) {
// this is a search for keywords only
$keywords_arr = explode(',', $keywords);
stringify_array_elms($keywords_arr, true);
$keywords_query = " AND xchan_hash IN (SELECT xtag_hash FROM xtag WHERE xtag_term IN (" . protect_sprintf(implode(',', $keywords_arr)) . ")) ";
}
// we only support an age range currently. You must set both agege
// (greater than or equal) and agele (less than or equal)
@@ -177,9 +181,15 @@ class Dirsearch extends Controller {
$sql_extra .= " and xchan_addr like '%%" . \App::get_hostname() . "' ";
}
$safesql = (($safe > 0) ? " and xchan_censored = 0 and xchan_selfcensored = 0 " : '');
$safesql = '';
if($safe > 0)
$safesql = " and xchan_censored = 0 and xchan_selfcensored = 0 ";
if($safe < 1)
$safesql = " and xchan_censored < 2 and xchan_selfcensored < 2 ";
if($safe < 0)
$safesql = " and ( xchan_censored = 1 OR xchan_selfcensored = 1 ) ";
$safesql = " and xchan_censored < 3 and xchan_selfcensored < 2 ";
if($forums)
$safesql .= " and xchan_pubforum = " . ((intval($forums)) ? '1 ' : '0 ');
@@ -215,26 +225,25 @@ class Dirsearch extends Controller {
if($sync) {
$spkt = array('transactions' => array());
$r = q("select * from updates where ud_date >= '%s' and ud_guid != '' and ud_addr != '' order by ud_date desc",
$r = q("SELECT * FROM updates WHERE ud_update = 0 AND ud_last = '%s' AND ud_date >= '%s' ORDER BY ud_date DESC",
dbesc(NULL_DATE),
dbesc($sync)
);
if($r) {
foreach($r as $rr) {
$flags = array();
if($rr['ud_flags'] & UPDATE_FLAGS_DELETED)
$flags[] = 'deleted';
if($rr['ud_flags'] & UPDATE_FLAGS_FORCED)
$flags[] = 'forced';
$spkt['transactions'][] = array(
$spkt['transactions'][] = [
'hash' => $rr['ud_hash'],
'address' => $rr['ud_addr'],
'transaction_id' => $rr['ud_guid'],
'host' => $rr['ud_host'],
'transaction_id' => $rr['ud_host'], // deprecated 2023-04-12 - can be removed after dir servers at version >= 8.4
'timestamp' => $rr['ud_date'],
'flags' => $flags
);
'flags' => $rr['ud_flags']
];
}
}
json_return_and_die($spkt);
}
else {
@@ -264,7 +273,7 @@ class Dirsearch extends Controller {
xprof.xprof_hometown as hometown,
xprof.xprof_keywords as keywords
from xchan left join xprof on xchan_hash = xprof_hash left join hubloc on (hubloc_id_url = xchan_url and hubloc_hash = xchan_hash)
where hubloc_primary = 1 and hubloc_updated > %s - INTERVAL %s and ( $logic $sql_extra ) $hub_query and xchan_network = 'zot6' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0
where hubloc_primary = 1 and hubloc_updated > %s - INTERVAL %s and ( $logic $sql_extra ) $hub_query $keywords_query and xchan_network = 'zot6' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 and hubloc_deleted = 0
$safesql $order $qlimit",
db_utcnow(),
db_quoteinterval('30 DAY')

View File

@@ -2,15 +2,13 @@
namespace Zotlabs\Module;
use App;
use Zotlabs\Web\Controller;
require_once("include/bbcode.php");
require_once('include/security.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
require_once('include/items.php');
class Display extends Controller {
function init() {
class Display extends \Zotlabs\Web\Controller {
}
function get($update = 0, $load = false) {
@@ -91,7 +89,7 @@ class Display extends \Zotlabs\Web\Controller {
$o .= '<div id="jot-popup">';
$a = '';
$o .= status_editor($a,$x,false,'Display');
$o .= status_editor($x, false, 'Display');
$o .= '</div>';
}

View File

@@ -132,7 +132,7 @@ class Editblock extends \Zotlabs\Web\Controller {
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
);
$editor = status_editor($a, $x, false, 'Editblock');
$editor = status_editor($x, false, 'Editblock');
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit Block'),

View File

@@ -131,7 +131,7 @@ class Editlayout extends \Zotlabs\Web\Controller {
'profile_uid' => intval($owner),
);
$editor = status_editor($a, $x, false, 'Editlayout');
$editor = status_editor($x, false, 'Editlayout');
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit Layout'),

View File

@@ -107,7 +107,7 @@ class Editpost extends \Zotlabs\Web\Controller {
);
$a = '';
$editor = status_editor($a, $x, false, 'Editpost');
$editor = status_editor($x, false, 'Editpost');
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit post'),

View File

@@ -75,7 +75,7 @@ class Editwebpage extends \Zotlabs\Web\Controller {
// Figure out which post we're editing
$post_id = ((argc() > 2) ? intval(argv(2)) : 0);
if(! $post_id) {
notice( t('Item not found') . EOL);
return;
@@ -90,7 +90,7 @@ class Editwebpage extends \Zotlabs\Web\Controller {
return;
}
// We've already figured out which item we want and whose copy we need,
// We've already figured out which item we want and whose copy we need,
// so we don't need anything fancy here
$sql_extra = item_permissions_sql($owner);
@@ -122,13 +122,13 @@ class Editwebpage extends \Zotlabs\Web\Controller {
return;
}
}
$layout = $itm[0]['layout_mid'];
$content = $itm[0]['body'];
if($itm[0]['mimetype'] === 'text/markdown')
$content = \Zotlabs\Lib\MarkdownSoap::unescape($itm[0]['body']);
$rp = 'webpages/' . $which;
$x = array(
@@ -160,7 +160,7 @@ class Editwebpage extends \Zotlabs\Web\Controller {
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
);
$editor = status_editor($a, $x, false, 'Editwebpage');
$editor = status_editor($x, false, 'Editwebpage');
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit Webpage'),

View File

@@ -35,7 +35,7 @@ class File_upload extends \Zotlabs\Web\Controller {
$_REQUEST['deny_cid'] = ((isset($_REQUEST['contact_deny'])) ? perms2str($_REQUEST['contact_deny']) : '');
$_REQUEST['deny_gid'] = ((isset($_REQUEST['group_deny'])) ? perms2str($_REQUEST['group_deny']) : '');
if(isset($_REQUEST['filename']) && $_REQUEST['filename']) {
if(isset($_REQUEST['filename']) && strlen($_REQUEST['filename'])) {
$r = attach_mkdir($channel, get_observer_hash(), $_REQUEST);
if($r['success']) {
$hash = $r['data']['hash'];

View File

@@ -17,8 +17,6 @@ class Hq extends \Zotlabs\Web\Controller {
function init() {
if(! local_channel())
return;
App::$profile_uid = local_channel();
}
function get($update = 0, $load = false) {
@@ -27,6 +25,8 @@ class Hq extends \Zotlabs\Web\Controller {
return;
}
App::$profile_uid = local_channel();
$item_hash = '';
if(argc() > 1 && argv(1) !== 'load') {
@@ -67,11 +67,6 @@ class Hq extends \Zotlabs\Web\Controller {
}
}
//if the item is to be moderated redirect to /moderate
if($target_item['item_blocked'] == ITEM_MODERATED) {
goaway(z_root() . '/moderate/' . $target_item['id']);
}
$simple_update = '';
if($update && $_SESSION['loadtime'])
$simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) ";
@@ -90,6 +85,7 @@ class Hq extends \Zotlabs\Web\Controller {
$x = [
'is_owner' => true,
'profile_uid' => $channel['channel_id'],
'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''),
'default_location' => $channel['channel_location'],
'nickname' => $channel['channel_address'],
@@ -109,7 +105,7 @@ class Hq extends \Zotlabs\Web\Controller {
];
$a = '';
$o .= status_editor($a, $x, true);
$o .= status_editor($x, true, 'Hq');
}

View File

@@ -63,8 +63,8 @@ class Item extends Controller {
// do we have the item (at all)?
$r = q("select * from item where mid = '%s' $item_normal limit 1",
dbesc(z_root() . '/item/' . $item_id)
$r = q("select parent_mid from item where uuid = '%s' $item_normal limit 1",
dbesc($item_id)
);
if (!$r) {
@@ -84,7 +84,7 @@ class Item extends Controller {
}
observer_auth($portable_id);
$i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1",
$i = q("select id as item_id, uid from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1",
dbesc($r[0]['parent_mid']),
dbesc($portable_id)
);
@@ -99,7 +99,7 @@ class Item extends Controller {
$sql_extra = item_permissions_sql(0);
if (!$i) {
$i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
$i = q("select id as item_id, uid, item_private from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
dbesc($r[0]['parent_mid'])
);
}
@@ -108,57 +108,56 @@ class Item extends Controller {
http_status_exit(403, 'Forbidden');
}
$chan = channelx_by_n($i[0]['uid']);
if (!$chan) {
http_status_exit(404, 'Not found');
}
if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream')) {
http_status_exit(403, 'Forbidden');
}
$parents_str = ids_to_querystr($i, 'item_id');
$items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent IN ( %s ) $item_normal order by item.id asc",
dbesc($parents_str)
// We won't need to check for privacy mismatches if the verified observer is also owner
$parent_item_private = ((isset($i[0]['item_private'])) ? " and item_private = " . intval($i[0]['item_private']) . " " : '');
$total = q("SELECT count(*) AS count FROM item WHERE parent = %d $parent_item_private $item_normal ",
intval($parents_str)
);
if (!$items) {
http_status_exit(404, 'Not found');
App::set_pager_total($total[0]['count']);
App::set_pager_itemspage(30);
if (App::$pager['total'] > App::$pager['itemspage']) {
// let mod conversation handle this request
App::$query_string = str_replace('item', 'conversation', App::$query_string);
$i = Activity::paged_collection_init(App::$pager['total'], App::$query_string);
as_return_and_die($i ,$chan);
}
else {
$items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent = %d $parent_item_private $item_normal ORDER BY item.id",
intval($parents_str)
);
xchan_query($items, true);
$items = fetch_post_tags($items, true);
xchan_query($items, true);
$items = fetch_post_tags($items, true);
if (!$items)
http_status_exit(404, 'Not found');
$chan = channelx_by_n($items[0]['uid']);
if (!$chan)
http_status_exit(404, 'Not found');
if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream'))
http_status_exit(403, 'Forbidden');
$i = Activity::encode_item_collection($items, 'conversation/' . $item_id, 'OrderedCollection');
if (!$i)
http_status_exit(404, 'Not found');
$i = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection', App::$pager['total']);
}
if ($portable_id && (!intval($items[0]['item_private']))) {
ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
$c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
intval($items[0]['uid']),
dbesc($portable_id)
);
if (!$c) {
ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
}
}
$x = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
]], $i);
$headers = [];
$headers['Content-Type'] = 'application/x-zot+json';
$x['signature'] = LDSignatures::sign($x, $chan);
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
$h = HTTPSig::create_sig($headers, $chan['channel_prvkey'], channel_url($chan));
HTTPSig::set_headers($h);
echo $ret;
killme();
as_return_and_die($i ,$chan);
}
if (ActivityStreams::is_as_request()) {
@@ -181,8 +180,7 @@ class Item extends Controller {
// do we have the item (at all)?
// add preferential bias to item owners (item_wall = 1)
$r = q("select * from item where mid = '%s' or uuid = '%s' $item_normal order by item_wall desc limit 1",
dbesc(z_root() . '/item/' . $item_id),
$r = q("select * from item where uuid = '%s' $item_normal order by item_wall desc limit 1",
dbesc($item_id)
);
@@ -223,6 +221,22 @@ class Item extends Controller {
);
}
$bear = Activity::token_from_request();
if ($bear) {
logger('bear: ' . $bear, LOGGER_DEBUG);
if (!$i) {
$t = q("select * from iconfig where cat = 'ocap' and k = 'relay' and v = '%s'",
dbesc($bear)
);
if ($t) {
$i = q("select id as item_id from item where uuid = '%s' and id = %d $item_normal limit 1",
dbesc($item_id),
intval($t[0]['iid'])
);
}
}
}
if (!$i) {
http_status_exit(403, 'Forbidden');
}
@@ -255,23 +269,7 @@ class Item extends Controller {
}
}
$x = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
]], $i);
$headers = [];
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
$x['signature'] = LDSignatures::sign($x, $chan);
$ret = json_encode($x, JSON_UNESCAPED_SLASHES);
$headers['Date'] = datetime_convert('UTC', 'UTC', 'now', 'D, d M Y H:i:s \\G\\M\\T');
$headers['Digest'] = HTTPSig::generate_digest_header($ret);
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
$h = HTTPSig::create_sig($headers, $chan['channel_prvkey'], channel_url($chan));
HTTPSig::set_headers($h);
echo $ret;
killme();
as_return_and_die($i ,$chan);
}
@@ -307,7 +305,9 @@ class Item extends Controller {
if ((!local_channel()) && (!remote_channel()) && (!x($_REQUEST, 'anonname')))
return;
$uid = local_channel();
$uid = local_channel();
$token = '';
$channel = null;
$observer = null;
$datarray = [];
@@ -830,7 +830,6 @@ class Item extends Controller {
require_once('include/text.php');
// BBCODE alert: the following functions assume bbcode input
// and will require alternatives for alternative content-types (text/html, text/markdown, text/plain, etc.)
// we may need virtual or template classes to implement the possible alternatives
@@ -866,6 +865,21 @@ class Item extends Controller {
$private = 2;
}
if ($private && get_pconfig($profile_uid, 'system', 'ocap_enabled')) {
// for edited posts, re-use any existing OCAP token (if found).
// Otherwise generate a new one.
if ($iconfig) {
foreach ($iconfig as $cfg) {
if ($cfg['cat'] === 'ocap' && $cfg['k'] === 'relay') {
$token = $cfg['v'];
}
}
}
if (!$token) {
$token = new_token();
}
}
/**
*
@@ -887,9 +901,9 @@ class Item extends Controller {
*/
if (!$preview) {
fix_attached_photo_permissions($profile_uid, $owner_xchan['xchan_hash'], ((strpos($body, '[/crypt]')) ? $_POST['media_str'] : $body), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
fix_attached_photo_permissions($profile_uid, $owner_xchan['xchan_hash'], ((strpos($summary, '[/crypt]')) ? $_POST['media_str'] : $summary), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
fix_attached_file_permissions($channel, $observer['xchan_hash'], ((strpos($body, '[/crypt]')) ? $_POST['media_str'] : $body), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
fix_attached_permissions($profile_uid, ((strpos($body, '[/crypt]')) ? $_POST['media_str'] : $body), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny, $token);
//fix_attached_photo_permissions($profile_uid, $owner_xchan['xchan_hash'], ((strpos($body, '[/crypt]')) ? $_POST['media_str'] : $body), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny, $token);
//fix_attached_file_permissions($channel, $observer['xchan_hash'], ((strpos($body, '[/crypt]')) ? $_POST['media_str'] : $body), $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny, $token);
}
$attachments = '';
@@ -972,14 +986,12 @@ class Item extends Controller {
}
}
$item_unseen = ((local_channel() != $profile_uid) ? 1 : 0);
$item_wall = ((isset($_REQUEST['type']) && ($_REQUEST['type'] === 'wall' || $_REQUEST['type'] === 'wall-comment')) ? 1 : 0);
$item_origin = (($origin) ? 1 : 0);
$item_consensus = (($consensus) ? 1 : 0);
$item_nocomment = (($nocomment) ? 1 : 0);
// determine if this is a wall post
if ($parent) {
@@ -1128,8 +1140,13 @@ class Item extends Controller {
if (!empty_acl($datarray))
$datarray['public_policy'] = '';
if ($iconfig)
if ($iconfig) {
$datarray['iconfig'] = $iconfig;
}
if ($token) {
IConfig::set($datarray, 'ocap', 'relay', $token);
}
// preview mode - prepare the body for display and send it via json
@@ -1194,12 +1211,15 @@ class Item extends Controller {
(($remote_id) ? $remote_id : basename($datarray['mid'])), true);
}
if ($orig_post) {
$datarray['id'] = $post_id;
$x = item_store_update($datarray, $execflag);
if ($x['success']) {
$this->add_listeners($datarray);
}
// We only need edit activities for other federated protocols
// which do not support edits natively. While this does federate
// edits, it presents a number of issues locally - such as #757 and #758.
@@ -1238,6 +1258,10 @@ class Item extends Controller {
$post = item_store($datarray, $execflag);
if ($post['success']) {
$this->add_listeners($datarray);
}
$post_id = $post['item_id'];
$datarray = $post['item'];
@@ -1603,4 +1627,33 @@ class Item extends Controller {
}
function add_listeners($item) {
// ONLY public items!
if ($item['item_thread_top'] && !$item['item_private'] && !empty($item['term'])) {
foreach($item['term'] as $t) {
if (empty($t['url']) || $t['ttype'] != TERM_MENTION || $t['otype'] != TERM_OBJ_POST) {
continue;
}
$listener = q("select hubloc_hash, hubloc_network from hubloc where hubloc_id_url = '%s' and hubloc_deleted = 0 order by hubloc_id desc",
dbesc($t['url'])
);
if ($listener) {
$listener = Libzot::zot_record_preferred($listener);
$c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
intval($profile_uid),
dbesc($listener['hubloc_hash'])
);
if (!$c) {
ThreadListener::store($item['mid'], $listener['hubloc_hash']);
}
}
}
}
}
}

View File

@@ -139,7 +139,7 @@ class Layouts extends \Zotlabs\Web\Controller {
$x['pagetitle'] = $_REQUEST['pagetitle'] ?? '';
$a = '';
$editor = status_editor($a,$x,false,'Layouts');
$editor = status_editor($x, false, 'Layouts');
$r = q("select iconfig.iid, iconfig.v, mid, title, body, mimetype, created, edited, item_type from iconfig
left join item on iconfig.iid = item.id

View File

@@ -407,12 +407,20 @@ class Like extends Controller {
if (activity_match($rr['verb'], $activity))
$multi_undo = false;
$d = q("select * from item where id = %d",
intval($rr['id'])
);
if ($d) {
xchan_query($d);
$sync_item = fetch_post_tags($d);
Libsync::build_sync_packet($profile_uid, ['item' => [encode_item($sync_item[0], true)]]);
}
// drop_item was not done interactively, so we need to invoke the notifier
// in order to push the changes to connections
Master::Summon(array('Notifier', 'drop', $rr['id']));
}
if ($interactive)
@@ -443,7 +451,7 @@ class Like extends Controller {
}
else {
$post_type = (($item['resource_type'] === 'photo') ? t('photo') : t('status'));
if ($item['obj_type'] === ACTIVITY_OBJ_EVENT)
if (in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT]))
$post_type = t('event');
$obj_type = (($item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE);
@@ -499,7 +507,7 @@ class Like extends Controller {
$private = (($public) ? 0 : 1);
}
else {
$arr['parent'] = $item['id'];
$arr['parent'] = $item['parent'];
$arr['thr_parent'] = $item['mid'];
$ulink = '[zrl=' . $item_author['xchan_url'] . '][bdi]' . $item_author['xchan_name'] . '[/bdi][/zrl]';
$alink = '[zrl=' . $observer['xchan_url'] . '][bdi]' . $observer['xchan_name'] . '[/bdi][/zrl]';
@@ -516,7 +524,7 @@ class Like extends Controller {
$arr['uid'] = $owner_uid;
$arr['item_flags'] = $item['item_flags'];
$arr['item_wall'] = $item['item_wall'];
$arr['parent_mid'] = (($extended_like) ? $arr['mid'] : $item['mid']);
$arr['parent_mid'] = (($extended_like) ? $arr['mid'] : $item['parent_mid']);
$arr['owner_xchan'] = (($extended_like) ? $ch[0]['xchan_hash'] : $thread_owner['xchan_hash']);
$arr['author_xchan'] = $observer['xchan_hash'];
$arr['body'] = sprintf($bodyverb, $alink, $ulink, $plink);
@@ -546,7 +554,14 @@ class Like extends Controller {
$arr['deny_cid'] = $deny_cid;
$arr['deny_gid'] = $deny_gid;
$arr['item_private'] = $private;
$arr['created'] = datetime_convert();
$created = datetime_convert();
$arr['created'] = $created;
$arr['edited'] = $created;
$arr['commented'] = $created;
$arr['received'] = $created;
$arr['changed'] = $created;
call_hooks('post_local', $arr);
@@ -562,6 +577,15 @@ class Like extends Controller {
call_hooks('post_local_end', $arr);
$r = q("select * from item where id = %d",
intval($post_id)
);
if ($r) {
xchan_query($r);
$sync_item = fetch_post_tags($r);
Libsync::build_sync_packet($profile_uid, ['item' => [encode_item($sync_item[0], true)]]);
}
if ($extended_like) {
$r = q("insert into likes (channel_id,liker,likee,iid,i_mid,verb,target_type,target_id,target) values (%d,'%s','%s',%d,'%s','%s','%s','%s','%s')",
intval($ch[0]['channel_id']),

View File

@@ -15,6 +15,7 @@ class Lockview extends Controller {
$atoken_xchans = [];
$access_list = [];
$guest_access_list = [];
$ocap_access_list = [];
if (local_channel()) {
$at = q("select * from atoken where atoken_uid = %d",
@@ -166,6 +167,24 @@ class Lockview extends Controller {
}
}
}
$ocap_tokens = [];
foreach ($allowed_users as $allowed_user) {
$allowed_user = trim($allowed_user, '\'');
if (str_starts_with($allowed_user, 'token:')) {
$ocap_tokens[] = str_replace('token:', '', $allowed_user);
}
}
if ($ocap_tokens) {
stringify_array_elms($ocap_tokens, true);
$ocap_mids = dbq("select id, mid from item where id in (select iid from iconfig where cat = 'ocap' and k = 'relay' and v in (" . implode(', ', $ocap_tokens) . "))");
foreach ($ocap_mids as $ocap) {
$ocap_access_list[] = '<a href="' . $ocap['mid'] . '" class="dropdown-item-text" target="_blank">' . t('Item') . ' ' . $ocap['id'] . '</a>';
}
}
}
$profile_groups = [];
@@ -205,9 +224,6 @@ class Lockview extends Controller {
}
if ($atokens && $allowed_xchans && $url) {
$guest_access_list = [];
$allowed_xchans = array_unique($allowed_xchans);
foreach ($atokens as $atoken) {
if (in_array($atoken['xchan_hash'], $allowed_xchans)) {
@@ -216,22 +232,25 @@ class Lockview extends Controller {
}
}
$access_list_header = '';
$access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('Access') . '</div>';
$guest_access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('Guest access') . '</div>';
$ocap_access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('OCAP access') . '</div>';
$divider = '<div class="dropdown-divider"></div>';
$str = '';
if ($access_list) {
$access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('Access') . '</div>';
$str .= $access_list_header . implode($access_list);
}
$guest_access_list_header = '';
if ($guest_access_list) {
$guest_access_list_header = '<div class="dropdown-header text-uppercase h6">' . t('Guest access') . '</div>';
$str .= $divider . $guest_access_list_header . implode($guest_access_list);
}
$divider = '';
if ($access_list && $guest_access_list) {
$divider = '<div class="dropdown-divider"></div>';
if ($ocap_access_list) {
$str .= $divider . $ocap_access_list_header . implode($ocap_access_list);
}
echo $access_list_header . implode($access_list) . $divider . $guest_access_list_header . implode($guest_access_list);
echo $str;
killme();
}

View File

@@ -105,13 +105,13 @@ class Magic extends Controller {
$headers['Accept'] = 'application/x-zot+json' ;
$headers['Content-Type'] = 'application/x-zot+json' ;
$headers['X-Open-Web-Auth'] = random_string();
$headers['Digest'] = HTTPSig::generate_digest_header($data);
$headers['Host'] = $parsed['host'];
$headers['(request-target)'] = 'post ' . '/owa';
$headers['(request-target)'] = 'get ' . '/owa';
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel),true,'sha512');
$redirects = 0;
$x = z_post_url($owapath,$data,$redirects,[ 'headers' => $headers ]);
$x = z_fetch_url($owapath, false, $redirects, ['headers' => $headers]);
logger('owa fetch returned: ' . print_r($x,true),LOGGER_DATA);
if ($x['success']) {
$j = json_decode($x['body'],true);

View File

@@ -23,7 +23,7 @@ class Manifest extends Controller {
[ 'src' => '/images/app/hz-144.png', 'sizes' => '144x144', 'type' => 'image/png' ],
[ 'src' => '/images/app/hz-152.png', 'sizes' => '152x152', 'type' => 'image/png' ],
[ 'src' => '/images/app/hz-192.png', 'sizes' => '192x192', 'type' => 'image/png', 'purpose' => 'any maskable' ],
[ 'src' => '/images/app/hz-348.png', 'sizes' => '384x384', 'type' => 'image/png' ],
[ 'src' => '/images/app/hz-384.png', 'sizes' => '384x384', 'type' => 'image/png' ],
[ 'src' => '/images/app/hz-512.png', 'sizes' => '512x512', 'type' => 'image/png' ],
[ 'src' => '/images/app/hz.svg', 'sizes' => '64x64', 'type' => 'image/xml+svg' ]
],

View File

@@ -17,7 +17,7 @@ class Moderate extends \Zotlabs\Web\Controller {
}
\App::set_pager_itemspage(30);
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
//show all items
if(argc() == 1) {
@@ -40,8 +40,13 @@ class Moderate extends \Zotlabs\Web\Controller {
if(argc() > 2) {
$post_id = intval(argv(1));
if(! $post_id)
if(! $post_id) {
if (is_ajax()) {
killme();
}
goaway(z_root() . '/moderate');
}
$action = argv(2);
@@ -61,18 +66,20 @@ class Moderate extends \Zotlabs\Web\Controller {
);
$item['item_blocked'] = 0;
item_update_parent_commented($item);
notice( t('Comment approved') . EOL);
notice( t('Item approved') . EOL);
}
elseif($action === 'drop') {
// TODO: not implemented
// let the sender know we received their comment but we don't permit spam here.
// Activity::send_rejection_activity(App::get_channel(), $item['author_xchan'], $item);
drop_item($post_id,false);
notice( t('Comment deleted') . EOL);
}
notice( t('Item deleted') . EOL);
}
// refetch the item after changes have been made
$r = q("select * from item where id = %d",
intval($post_id)
);
@@ -84,6 +91,11 @@ class Moderate extends \Zotlabs\Web\Controller {
if($action === 'approve') {
\Zotlabs\Daemon\Master::Summon(array('Notifier', 'comment-new', $post_id));
}
if (is_ajax()) {
killme();
}
goaway(z_root() . '/moderate');
}
}

View File

@@ -43,6 +43,8 @@ class Network extends \Zotlabs\Web\Controller {
return login(false);
}
App::$profile_uid = local_channel();
$o = '';
$arr = array('query' => App::$query_string);
@@ -212,7 +214,7 @@ class Network extends \Zotlabs\Web\Controller {
);
$a = '';
$status_editor = status_editor($a, $x, false, 'Network');
$status_editor = status_editor($x, false, 'Network');
$o .= $status_editor;
}

View File

@@ -28,7 +28,6 @@ class Oep extends \Zotlabs\Web\Controller {
$format = $_REQUEST['format'] ?? '';
if($format && $format !== 'json')
http_status_exit(501, 'Not implemented');
if(fnmatch('*/photos/*/album/*',$url))
$arr = $this->oep_album_reply($_REQUEST);
elseif(fnmatch('*/photos/*/image/*',$url))
@@ -95,12 +94,12 @@ class Oep extends \Zotlabs\Web\Controller {
$c = channelx_by_n($p[0]['uid']);
if(! ($c && $res))
return;
if(! perm_is_allowed($c[0]['channel_id'],get_observer_hash(),'view_stream'))
if(! perm_is_allowed($c['channel_id'], get_observer_hash(), 'view_stream')) {
return;
}
$sql_extra = item_permissions_sql($c['channel_id']);
@@ -336,32 +335,51 @@ class Oep extends \Zotlabs\Web\Controller {
$maxwidth = ((isset($args['maxwidth'])) ? $args['maxwidth'] : 0);
$maxheight = ((isset($args['maxheight'])) ? $args['maxheight'] : 0);
if(preg_match('#//(.*?)/(.*?)/(.*?)/(.*?)mid\=(.*?)(&|$)#',$url,$matches)) {
$chn = $matches[3];
$res = $matches[5];
$parsed = parse_url($url);
if (empty($parsed['path'])) {
return;
}
if(! ($chn && $res))
$nick = basename($parsed['path']);
if (!$nick) {
return;
}
$c = q("select * from channel where channel_address = '%s' limit 1",
dbesc($chn)
if (empty($parsed['query'])) {
return;
}
parse_str($parsed['query'], $query);
if (empty($query['mid'])) {
return;
}
$mid = unpack_link_id($query['mid']);
if (!$mid) {
return;
}
$c = channelx_by_nick($nick);
if(! $c) {
return;
}
if(! perm_is_allowed($c['channel_id'], get_observer_hash(), 'view_stream')) {
return;
}
$sql_extra = item_permissions_sql($c['channel_id']);
$item_normal = item_normal();
$p = q("select * from item where mid = '%s' and uid = %d $sql_extra $item_normal limit 1",
dbesc($mid),
intval($c['channel_id'])
);
if(! $c)
return;
if(! perm_is_allowed($c[0]['channel_id'],get_observer_hash(),'view_stream'))
return;
$sql_extra = item_permissions_sql($c[0]['channel_id']);
$p = q("select * from item where mid = '%s' and uid = %d $sql_extra limit 1",
dbesc($res),
intval($c[0]['channel_id'])
);
if(! $p)
if(! $p) {
return;
}
xchan_query($p,true);
$p = fetch_post_tags($p,true);

View File

@@ -30,22 +30,43 @@ class Owa extends Controller {
$sigblock = HTTPSig::parse_sigheader($_SERVER['HTTP_AUTHORIZATION']);
if ($sigblock) {
$keyId = $sigblock['keyId'];
$parsed = parse_url($keyId);
if (str_starts_with($parsed['scheme'],'http')) {
unset($parsed['fragment']);
unset($parsed['query']);
$keyId = unparse_url($parsed);
}
else {
$keyId = str_replace('acct:', '', $keyId);
}
if ($keyId) {
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
WHERE hubloc_id_url = '%s' AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC",
WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s')
AND hubloc_deleted = 0 AND xchan_pubkey != ''
ORDER BY hubloc_id DESC",
dbesc($keyId),
dbesc($keyId),
dbesc($keyId)
);
if (! $r) {
$found = discover_by_webbie($keyId);
logger('found = ' . print_r($found, true));
if ($found) {
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
WHERE hubloc_id_url = '%s' AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC ",
WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s' OR xchan_hash = '%s') AND hubloc_deleted = 0 AND xchan_pubkey != '' ORDER BY hubloc_id DESC ",
dbesc($keyId),
dbesc($keyId),
dbesc($keyId)
);
}
}
if ($r) {
foreach ($r as $hubloc) {
// fix friendica accept header for nginx
if (str_starts_with($keyId, 'acct:') && $_SERVER['HTTP_ACCEPT'] === 'application/x-zot+json')
$_SERVER['HTTP_ACCEPT'] = 'application/x-dfrn+json, application/x-zot+json';
$verified = HTTPSig::verify(file_get_contents('php://input'), $hubloc['xchan_pubkey']);
if ($verified && $verified['header_signed'] && $verified['header_valid'] && ($verified['content_valid'] || (! $verified['content_signed']))) {
logger('OWA header: ' . print_r($verified,true),LOGGER_DATA);
@@ -72,7 +93,8 @@ class Owa extends Controller {
if ($found) {
$r = q("SELECT * FROM hubloc LEFT JOIN xchan ON hubloc_hash = xchan_hash
WHERE hubloc_id_url = '%s' AND hubloc_deleted = 0 ORDER BY hubloc_id DESC LIMIT 1",
WHERE (hubloc_addr = '%s' OR hubloc_id_url = '%s') AND hubloc_deleted = 0 ORDER BY hubloc_id DESC LIMIT 1",
dbesc(str_replace('acct:', '', $keyId)),
dbesc($keyId)
);

View File

@@ -268,7 +268,8 @@ class Pdledit_gui extends Controller {
$checkpaths = [
'Zotlabs/Widget/*.php'
'Zotlabs/Widget/*.php',
'view/theme/' . lcfirst(App::$theme_info['name']) . '/widget/*.php'
];
$addons = plugins_installed_list();

View File

@@ -46,7 +46,7 @@ class Photo extends \Zotlabs\Web\Controller {
dbesc(argv(1))
);
if ($r) {
$allowed = attach_can_view($r[0]['uid'],$observer_xchan,argv(1)/*,$bear*/);
$allowed = attach_can_view($r[0]['uid'], $observer_xchan, argv(1), $bear);
}
if (! $allowed) {
http_status_exit(404,'Permission denied.');
@@ -154,6 +154,11 @@ class Photo extends \Zotlabs\Web\Controller {
}
else {
$bear = Activity::token_from_request();
if ($bear) {
logger('bear: ' . $bear, LOGGER_DEBUG);
}
/**
* Other photos
*/
@@ -223,7 +228,7 @@ class Photo extends \Zotlabs\Web\Controller {
}
if($allowed === (-1))
$allowed = attach_can_view($r[0]['uid'],$observer_xchan,$photo);
$allowed = attach_can_view($r[0]['uid'], $observer_xchan, $photo, $bear);
$channel = channelx_by_n($r[0]['uid']);
@@ -262,16 +267,15 @@ class Photo extends \Zotlabs\Web\Controller {
http_status_exit(404,'not found');
}
if(! $data)
killme();
if(! $data)
killme();
$etag = '"' . md5($data . $modified) . '"';
$etag = '"' . md5($data . $modified) . '"';
if($modified == 0)
$modified = time();
if($modified == 0)
$modified = time();
header_remove('Pragma');
if((isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] === $etag) || (!isset($_SERVER['HTTP_IF_NONE_MATCH']) && isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $_SERVER['HTTP_IF_MODIFIED_SINCE'] === gmdate("D, d M Y H:i:s", $modified) . " GMT")) {
header_remove('Expires');
header_remove('Cache-Control');
@@ -307,6 +311,8 @@ class Photo extends \Zotlabs\Web\Controller {
// This has performance considerations but we highly recommend you
// leave it alone.
$maxage = $cache_mode['age'];
if($cache_mode['exp'] || (! isset($expires)) || (isset($expires) && $expires - 60 < time()))

View File

@@ -851,6 +851,10 @@ class Photos extends \Zotlabs\Web\Controller {
dbesc($datum)
);
$tags = [];
$likebuttons = [];
$comments = '';
if(! ($ph && $x)) {
/* Check again - this time without specifying permissions */
@@ -981,7 +985,6 @@ class Photos extends \Zotlabs\Web\Controller {
$r = conv_sort($r,'commented');
}
$tags = array();
if(x($link_item, 'term')) {
$cnt = 0;
foreach($link_item['term'] as $t) {
@@ -1075,7 +1078,6 @@ class Photos extends \Zotlabs\Web\Controller {
];
}
$comments = '';
if(! $r) {
if($observer && ($can_post || $can_comment)) {
$commentbox = replace_macros($cmnt_tpl,array(
@@ -1209,13 +1211,12 @@ class Photos extends \Zotlabs\Web\Controller {
}
}
$paginate = paginate($a);
}
$album_e = array($album_link,$ph[0]['album']);
$like_e = $like;
$dislike_e = $dislike;
$paginate = paginate();
$response_verbs = array('like');
if(feature_enabled($owner_uid,'dislike'))

View File

@@ -217,7 +217,6 @@ class Profiles extends \Zotlabs\Web\Controller {
check_form_security_token_redirectOnErr('/profiles', 'profile_edit');
$is_default = (($orig[0]['is_default']) ? 1 : 0);
$profile_name = notags(trim($_POST['profile_name']));
@@ -579,12 +578,12 @@ class Profiles extends \Zotlabs\Web\Controller {
$channel = \App::get_channel();
if($namechanged && $is_default) {
// change name on all associated xchans by matching the url
q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_url = '%s'",
q("UPDATE xchan SET xchan_name = '%s', xchan_name_date = '%s' WHERE xchan_hash = '%s'",
dbesc($name),
dbesc(datetime_convert()),
dbesc(z_root() . '/channel/' . $channel['channel_address'])
dbesc($channel['xchan_hash'])
);
q("UPDATE channel SET channel_name = '%s' WHERE channel_hash = '%s'",
dbesc($name),
dbesc($channel['xchan_hash'])

View File

@@ -40,7 +40,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
$site_firehose = ((intval(get_config('system','site_firehose',0))) ? true : false);
$mid = (($_REQUEST['mid']) ? unpack_link_id($_REQUEST['mid']) : '');
$mid = ((isset($_REQUEST['mid'])) ? unpack_link_id($_REQUEST['mid']) : '');
if ($mid === false) {
notice(t('Malformed message id.') . EOL);
@@ -91,7 +91,7 @@ class Pubstream extends \Zotlabs\Web\Controller {
$o .= '<div id="jot-popup">';
$a = '';
$o .= status_editor($a,$x,false,'Pubstream');
$o .= status_editor($x, false, 'Pubstream');
$o .= '</div>';
}
@@ -99,9 +99,6 @@ class Pubstream extends \Zotlabs\Web\Controller {
nav_set_selected(t('Public Stream'));
if(!$mid)
$_SESSION['static_loadtime'] = datetime_convert();
$maxheight = get_config('system','home_divmore_height');
if(! $maxheight)
$maxheight = 400;

View File

@@ -12,13 +12,13 @@ class Rmagic extends \Zotlabs\Web\Controller {
$me = get_my_address();
if($me) {
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0",
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0 order by hubloc_id desc",
dbesc($me)
);
if(! $r) {
$w = discover_by_webbie($me);
if($w) {
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0",
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0 order by hubloc_id desc",
dbesc($me)
);
}
@@ -57,13 +57,13 @@ class Rmagic extends \Zotlabs\Web\Controller {
$r = null;
if($address) {
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0",
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0 order by hubloc_id desc",
dbesc($address)
);
if(! $r) {
$w = discover_by_webbie($address);
if($w) {
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0",
$r = q("select hubloc_url, hubloc_network from hubloc where hubloc_addr = '%s' and hubloc_deleted = 0 order by hubloc_id desc",
dbesc($address)
);
}

View File

@@ -1,7 +1,9 @@
<?php
namespace Zotlabs\Module; /** @file */
use App;
use Zotlabs\Lib\Libzot;
use Zotlabs\Access\AccessList;
require_once('include/acl_selectors.php');
require_once('include/crypto.php');
@@ -43,9 +45,9 @@ class Rpost extends \Zotlabs\Web\Controller {
// by the wretched beast called 'suhosin'. All the browsers now allow long GET requests, but suhosin
// blocks them.
$url = Libzot::get_rpost_path(\App::get_observer());
$url = Libzot::get_rpost_path(App::get_observer());
// make sure we're not looping to our own hub
if(($url) && (! stristr($url, \App::get_hostname()))) {
if(($url) && (! stristr($url, App::get_hostname()))) {
foreach($_GET as $key => $arg) {
if($key === 'q')
continue;
@@ -80,7 +82,10 @@ class Rpost extends \Zotlabs\Web\Controller {
'album' => $def_album,
'directory' => $def_attach,
'flags' => 1, // indicates temporary permissions are created
'allow_cid' => '<' . $channel['channel_hash'] . '>'
'allow_cid' => '<' . $channel['channel_hash'] . '>',
'allow_gid' => '',
'deny_cid' => '',
'deny_gid' => ''
]);
if (! $r['success']) {
@@ -167,18 +172,10 @@ class Rpost extends \Zotlabs\Web\Controller {
$_REQUEST['body'] = html2bbcode($_REQUEST['body']);
}
$channel = \App::get_channel();
if(isset($_REQUEST['acl']) && $_REQUEST['acl']) {
$acl = new \Zotlabs\Access\AccessList([]);
$acl->set($_REQUEST['acl']);
$channel_acl = $acl->get();
}
else {
$acl = new \Zotlabs\Access\AccessList($channel);
$channel_acl = $acl->get();
}
$channel = App::get_channel();
$acl = new AccessList($channel);
$channel_acl = $acl->get();
if(isset($_REQUEST['url']) && $_REQUEST['url']) {
$x = z_fetch_url(z_root() . '/linkinfo?f=&url=' . urlencode($_REQUEST['url']));
@@ -209,11 +206,12 @@ class Rpost extends \Zotlabs\Web\Controller {
'bbco_autocomplete' => 'bbcode',
'editor_autocomplete' => true,
'bbcode' => true,
'jotnets' => true
'jotnets' => true,
'reset' => t('Reset form')
);
$a = '';
$editor = status_editor($a,$x,false,'Rpost');
$editor = status_editor($x, false, 'Rpost');
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit post'),

View File

@@ -58,7 +58,7 @@ class Search extends Controller {
$o .= search($search, 'search-box', '/search', ((local_channel()) ? true : false));
if (local_channel() && strpos($search, 'https://') === 0 && !$update && !$load) {
if (local_channel() && str_starts_with($search, 'https://') && !$update && !$load) {
$url = htmlspecialchars_decode($search);
@@ -75,7 +75,7 @@ class Search extends Controller {
if ($f) {
$mid = $f[0]['message_id'];
foreach ($f as $m) {
if (strpos($search, $m['message_id']) === 0) {
if (str_starts_with($url, $m['message_id'])) {
$mid = $m['message_id'];
break;
}

View File

@@ -163,7 +163,8 @@ class Display {
$title_tosource = get_pconfig(local_channel(),'system','title_tosource');
$title_tosource = (($title_tosource===false)? '0': $title_tosource); // default if not set: 0
$theme_config = "";
$theme_config = null;
$schemas = null;
if(($themeconfigfile = $this->get_theme_config_file($theme)) != null){
require_once($themeconfigfile);
if(class_exists('\\Zotlabs\\Theme\\' . ucfirst($theme) . 'Config')) {
@@ -188,7 +189,7 @@ class Display {
'$uid' => local_channel(),
'$theme' => (($themes) ? array('theme', t('Display Theme:'), $theme_selected, '', $themes, 'preview') : false),
'$schema' => array('schema', t('Select scheme'), $existing_schema, '' , $schemas),
'$schema' => (($schemas) ? array('schema', t('Select scheme'), $existing_schema, '' , $schemas) : false),
'$preload_images' => array('preload_images', t("Preload images before rendering the page"), $preload_images, t("The subjective page load time will be longer but the page will be ready when displayed"), $yes_no),
'$user_scalable' => array('user_scalable', t("Enable user zoom on mobile devices"), $user_scalable, '', $yes_no),

View File

@@ -22,6 +22,15 @@ class Privacy {
$autoperms = (((x($_POST, 'autoperms')) && (intval($_POST['autoperms']) == 1)) ? 1 : 0);
set_pconfig(local_channel(), 'system', 'autoperms', $autoperms);
$permit_all_mentions = (((x($_POST, 'permit_all_mentions')) && (intval($_POST['permit_all_mentions']) == 1)) ? 1 : 0);
set_pconfig(local_channel(), 'system', 'permit_all_mentions', $permit_all_mentions);
$moderate_unsolicited_comments = (((x($_POST, 'moderate_unsolicited_comments')) && (intval($_POST['moderate_unsolicited_comments']) == 1)) ? 1 : 0);
set_pconfig(local_channel(), 'system', 'moderate_unsolicited_comments', $moderate_unsolicited_comments);
$ocap_enabled = (((x($_POST, 'ocap_enabled')) && (intval($_POST['ocap_enabled']) == 1)) ? 1 : 0);
set_pconfig(local_channel(), 'system', 'ocap_enabled', $ocap_enabled);
$role = get_pconfig(local_channel(), 'system', 'permissions_role');
if ($role === 'custom') {
@@ -99,6 +108,9 @@ class Privacy {
$autoperms = get_pconfig(local_channel(), 'system', 'autoperms');
$index_opt_out = get_pconfig(local_channel(), 'system', 'index_opt_out');
$group_actor = get_pconfig(local_channel(), 'system', 'group_actor');
$permit_all_mentions = get_pconfig(local_channel(), 'system', 'permit_all_mentions');
$moderate_unsolicited_comments = get_pconfig(local_channel(), 'system', 'moderate_unsolicited_comments');
$ocap_enabled = get_pconfig(local_channel(), 'system', 'ocap_enabled');
$permissions_role = get_pconfig(local_channel(), 'system', 'permissions_role', 'custom');
$permission_limits = ($permissions_role === 'custom');
@@ -119,7 +131,10 @@ class Privacy {
],
'$autoperms' => ['autoperms', t('Automatically approve new contacts'), $autoperms, '', [t('No'), t('Yes')]],
'$index_opt_out' => ['index_opt_out', t('Opt-out of search engine indexing'), $index_opt_out, '', [t('No'), t('Yes')]],
'$group_actor' => ['group_actor', t('Group actor'), $group_actor, t('Allow this channel to act as a forum'), [t('No'), t('Yes')]]
'$group_actor' => ['group_actor', t('Group actor'), $group_actor, t('Allow this channel to act as a forum'), [t('No'), t('Yes')]],
'$permit_all_mentions' => ['permit_all_mentions', t('Accept all messages which mention you'), $permit_all_mentions, t('This setting bypasses normal permissions'), [t('No'), t('Yes')]],
'$moderate_unsolicited_comments' => ['moderate_unsolicited_comments', t('Accept unsolicited comments for moderation'), $moderate_unsolicited_comments, t('Otherwise they will be silently dropped'), [t('No'), t('Yes')]],
'$ocap_enabled' => ['ocap_enabled', t('Enable OCAP access'), $ocap_enabled, t('Grant limited posts the right to access linked private media'), [t('No'), t('Yes')]],
]);
return $o;

View File

@@ -14,47 +14,53 @@ require_once('include/bbcode.php');
class Share extends \Zotlabs\Web\Controller {
function init() {
$post_id = ((argc() > 1) ? intval(argv(1)) : 0);
if(! $post_id)
killme();
if(! local_channel()) {
if (!intval(argv(1))) {
killme();
}
$observer = App::get_observer();
if (! local_channel()) {
killme();
}
$observer = App::get_observer();
$channel = App::get_channel();
$sys_channel = get_sys_channel();
$r = q("SELECT * from item left join xchan on author_xchan = xchan_hash WHERE id = %d LIMIT 1",
intval($post_id)
intval(argv(1))
);
if(! $r)
if ($r[0]['uid'] === $sys_channel['channel_id']) {
$r = [copy_of_pubitem($channel, $r[0]['mid'])];
}
if(! $r) {
killme();
}
$item_id = $r[0]['id'];
if(($r[0]['item_private']) && ($r[0]['xchan_network'] !== 'rss'))
if ($r[0]['item_private']) {
killme();
}
$sql_extra = item_permissions_sql($r[0]['uid']);
$r = q("select * from item where id = %d $sql_extra",
intval($post_id)
intval($item_id)
);
if(! $r)
killme();
/** @FIXME we only share bbcode */
if($r[0]['mimetype'] !== 'text/bbcode')
killme();
xchan_query($r);
xchan_query($r,true);
$arr = [];
$item = $r[0];
@@ -81,7 +87,7 @@ class Share extends \Zotlabs\Web\Controller {
$thread_owner = $r[0];
else
killme();
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($item['author_xchan'])
);
@@ -89,7 +95,7 @@ class Share extends \Zotlabs\Web\Controller {
$item_author = $r[0];
else
killme();
$arr['aid'] = $owner_aid;
$arr['uid'] = $owner_uid;
@@ -109,12 +115,12 @@ class Share extends \Zotlabs\Web\Controller {
$arr['obj_type'] = $item['obj_type'];
$arr['verb'] = ACTIVITY_SHARE;
$post = item_store($arr);
$post = item_store($arr);
$post_id = $post['item_id'];
$arr['id'] = $post_id;
call_hooks('post_local_end', $arr);
info( t('Post repeated') . EOL);
@@ -128,10 +134,10 @@ class Share extends \Zotlabs\Web\Controller {
Libsync::build_sync_packet($channel['channel_id'], [ 'item' => [ encode_item($sync_item[0],true) ] ]);
}
Master::Summon([ 'Notifier','like',$post_id ]);
Master::Summon([ 'Notifier', 'like', $post_id ]);
killme();
}
}

View File

@@ -7,6 +7,7 @@ use Zotlabs\Lib\Apps;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Enotify;
use Zotlabs\Lib\XConfig;
use Zotlabs\Lib\Cache;
class Sse_bs extends Controller {
@@ -117,14 +118,29 @@ class Sse_bs extends Controller {
function mark_read($arr) {
if(! self::$uid)
return;
$mids = [];
$str = '';
$mids_all_json = Cache::get('sse_mids_all_' . session_id());
if (!$mids_all_json)
$mids_all_json = '[]';
$mids_all = json_decode($mids_all_json, true);
foreach($arr as $a) {
$mids[] = '\'' . dbesc(unpack_link_id($a)) . '\'';
$mid_str = '\'' . dbesc(unpack_link_id($a)) . '\'';
$mids[] = $mid_str;
if (!in_array($mid_str, $mids_all)) {
$mids_all[] = $mid_str;
}
}
Cache::set('sse_mids_all_' . session_id(), json_encode($mids_all));
if(! self::$uid) {
return;
}
$str = implode(',', $mids);
@@ -169,12 +185,12 @@ class Sse_bs extends Controller {
$sql_extra2 = '';
if(self::$xchans)
$sql_extra2 = " AND CASE WHEN verb = '" . ACTIVITY_SHARE . "' THEN owner_xchan ELSE author_xchan END IN (" . self::$xchans . ") ";
$sql_extra2 = " AND CASE WHEN verb = '" . dbesc(ACTIVITY_SHARE) . "' THEN owner_xchan ELSE author_xchan END IN (" . self::$xchans . ") ";
$item_normal = item_normal();
// FEP-5624 filter approvals for comments
$approvals = " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject') ";
// Filter FEP-5624 approvals for comments and internal follow activities
$item_normal .= " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
if ($notifications) {
$items = q("SELECT * FROM item
@@ -184,7 +200,6 @@ class Sse_bs extends Controller {
AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image')
AND author_xchan != '%s'
$item_normal
$approvals
$sql_extra
$sql_extra2
ORDER BY created DESC LIMIT $limit OFFSET $offset",
@@ -214,7 +229,6 @@ class Sse_bs extends Controller {
AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image')
AND author_xchan != '%s'
$item_normal
$approvals
$sql_extra LIMIT 100",
intval(self::$uid),
dbesc(self::$ob_hash)
@@ -258,8 +272,8 @@ class Sse_bs extends Controller {
$item_normal = item_normal();
// FEP-5624 filter approvals for comments
$approvals = " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject') ";
// Filter FEP-5624 approvals for comments and internal follow activities
$item_normal .= " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
if ($notifications) {
$items = q("SELECT * FROM item
@@ -269,7 +283,6 @@ class Sse_bs extends Controller {
AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image')
AND author_xchan != '%s'
$item_normal
$approvals
$sql_extra
$sql_extra2
ORDER BY created DESC LIMIT $limit OFFSET $offset",
@@ -297,7 +310,6 @@ class Sse_bs extends Controller {
$r = q("SELECT id FROM item
WHERE uid = %d and item_unseen = 1 AND item_private = 2
$item_normal
$approvals
$sql_extra
AND author_xchan != '%s' LIMIT 100",
intval(self::$uid),
@@ -343,8 +355,8 @@ class Sse_bs extends Controller {
$item_normal = item_normal();
// FEP-5624 filter approvals for comments
$approvals = " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject') ";
// Filter FEP-5624 approvals for comments and internal follow activities
$item_normal .= " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
if ($notifications) {
$items = q("SELECT * FROM item
@@ -354,7 +366,6 @@ class Sse_bs extends Controller {
AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image')
AND author_xchan != '%s'
$item_normal
$approvals
$sql_extra
$sql_extra2
ORDER BY created DESC LIMIT $limit OFFSET $offset",
@@ -382,7 +393,6 @@ class Sse_bs extends Controller {
$r = q("SELECT id FROM item
WHERE uid = %d and item_unseen = 1 AND item_wall = 1 AND item_private IN (0, 1)
$item_normal
$approvals
$sql_extra
AND author_xchan != '%s' LIMIT 100",
intval(self::$uid),
@@ -417,8 +427,9 @@ class Sse_bs extends Controller {
}
}
if(! isset($_SESSION['static_loadtime']))
if(!isset($_SESSION['static_loadtime'])) {
$_SESSION['static_loadtime'] = datetime_convert();
}
$limit = intval(self::$limit);
$offset = self::$offset;
@@ -436,6 +447,13 @@ class Sse_bs extends Controller {
if(self::$xchans)
$sql_extra2 = " AND CASE WHEN verb = '" . ACTIVITY_SHARE . "' THEN owner_xchan ELSE author_xchan END IN (" . self::$xchans . ") ";
$sql_extra3 = '';
$sse_mids_all_json = Cache::get('sse_mids_all_' . session_id());
if ($sse_mids_all_json) {
$sse_mids_all = json_decode($sse_mids_all_json, true);
$sql_extra3 = " AND mid NOT IN (" . protect_sprintf(implode(',', $sse_mids_all)) . ") ";
}
$uids = " AND uid IN ( " . $sys['channel_id'] . " ) ";
$site_firehose = get_config('system', 'site_firehose', 0);
@@ -445,8 +463,8 @@ class Sse_bs extends Controller {
$item_normal = item_normal();
// FEP-5624 filter approvals for comments
$approvals = " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject') ";
// Filter FEP-5624 approvals for comments and internal follow activities
$item_normal .= " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
if ($notifications) {
$items = q("SELECT * FROM item
@@ -456,13 +474,13 @@ class Sse_bs extends Controller {
AND author_xchan != '%s'
AND created > '%s'
$item_normal
$approvals
$sql_extra
$sql_extra2
$sql_extra3
ORDER BY created DESC LIMIT $limit OFFSET $offset",
dbescdate($_SESSION['sse_loadtime']),
dbesc(self::$ob_hash),
dbescdate($_SESSION['static_loadtime'])
dbescdate($_SESSION['last_login_date'] ?? $_SESSION['static_loadtime'])
);
if($items) {
@@ -484,10 +502,10 @@ class Sse_bs extends Controller {
WHERE true $uids
AND created > '%s'
$item_normal
$approvals
$sql_extra
$sql_extra3
AND author_xchan != '%s' LIMIT 100",
dbescdate($_SESSION['static_loadtime']),
dbescdate($_SESSION['last_login_date'] ?? $_SESSION['static_loadtime']),
dbesc(self::$ob_hash)
);
@@ -586,29 +604,23 @@ class Sse_bs extends Controller {
$p_str = ids_to_querystr($p, 'parent');
$p_sql = (($p_str) ? "OR parent IN ( $p_str )" : '');
$r = q("select mid from item
$r = q("select count(*) as total from item
where uid = %d and ( owner_xchan = '%s' OR author_xchan = '%s' $p_sql ) and item_unseen = 1 $sql_extra $item_normal",
intval(self::$uid),
dbesc($forums[$x]['xchan_hash']),
dbesc($forums[$x]['xchan_hash'])
);
if($r) {
$mids = flatten_array_recursive($r);
$b64mids = [];
foreach($mids as $mid)
$b64mids[] = gen_link_id($mid);
if($r[0]['total']) {
$forums[$x]['notify_link'] = z_root() . '/network/?f=&pf=1&unseen=1&cid=' . $forums[$x]['abook_id'];
$forums[$x]['name'] = $forums[$x]['xchan_name'];
$forums[$x]['addr'] = $forums[$x]['xchan_addr'] ?? $forums[$x]['xchan_url'];
$forums[$x]['url'] = $forums[$x]['xchan_url'];
$forums[$x]['photo'] = $forums[$x]['xchan_photo_s'];
$forums[$x]['unseen'] = count($b64mids);
$forums[$x]['unseen'] = $r[0]['total'];
$forums[$x]['private_forum'] = ((isset($forums[$x]['private_forum']) && $forums[$x]['private_forum']) ? 'lock' : '');
$forums[$x]['message'] = ((isset($forums[$x]['private_forum']) && $forums[$x]['private_forum']) ? t('Private forum') : t('Public forum'));
$forums[$x]['mids'] = json_encode($b64mids);
unset($forums[$x]['abook_id']);
unset($forums[$x]['xchan_hash']);
@@ -616,7 +628,7 @@ class Sse_bs extends Controller {
unset($forums[$x]['xchan_url']);
unset($forums[$x]['xchan_photo_s']);
$i = $i + count($mids);
$i = $i + $r[0]['total'];
}
else {
@@ -647,6 +659,10 @@ class Sse_bs extends Controller {
$item_normal = item_normal();
// Filter FEP-5624 approvals for comments and internal follow activities
$item_normal .= " AND verb NOT IN ('" . dbesc(ACTIVITY_ATTEND) . "', 'Accept', '" . dbesc(ACTIVITY_ATTENDNO) . "', 'Reject', '" . dbesc(ACTIVITY_FOLLOW) . "') ";
$r = q("SELECT * FROM item
WHERE verb = '%s'
AND obj_type IN ('Document', 'Video', 'Audio', 'Image')

View File

@@ -18,10 +18,10 @@ class Wall_attach extends \Zotlabs\Web\Controller {
function post() {
$using_api = false;
$result = [];
$result = [];
if($_REQUEST['api_source'] && array_key_exists('media',$_FILES)) {
$using_api = true;
@@ -69,7 +69,7 @@ class Wall_attach extends \Zotlabs\Web\Controller {
];
}
}
else {
else {
if(! array_key_exists('userfile',$_FILES)) {
$_FILES['userfile'] = [
'name' => $_FILES['files']['name'],
@@ -81,19 +81,28 @@ class Wall_attach extends \Zotlabs\Web\Controller {
}
}
$observer = \App::get_observer();
$def_album = get_pconfig($channel['channel_id'],'system','photo_path');
$def_attach = get_pconfig($channel['channel_id'],'system','attach_path');
$r = attach_store($channel,(($observer) ? $observer['xchan_hash'] : ''),'', array('source' => 'editor', 'visible' => 0, 'album' => $def_album, 'directory' => $def_attach, 'allow_cid' => '<' . $channel['channel_hash'] . '>'));
$data = [
'source' => 'editor',
'visible' => 0,
'album' => $def_album,
'directory' => $def_attach,
'flags' => 1,
'allow_cid' => '<' . $channel['channel_hash'] . '>',
'allow_gid' => '',
'deny_cid' => '',
'deny_gid' => ''
];
$r = attach_store($channel, get_observer_hash(), '', $data);
if(! $r['success']) {
notice( $r['message'] . EOL);
killme();
}
if(intval($r['data']['is_photo'])) {
$s = "\n\n" . $r['body'] . "\n\n";
}
@@ -130,7 +139,7 @@ class Wall_attach extends \Zotlabs\Web\Controller {
logger('unable to read svg data file: ' . 'store/' . $channel['channel_address'] . '/' . $r['data']['os_path']);
}
}
$s .= "\n\n" . '[attachment]' . $r['data']['hash'] . ',' . $r['data']['revision'] . '[/attachment]' . "\n";
}
@@ -144,8 +153,8 @@ class Wall_attach extends \Zotlabs\Web\Controller {
$result['message'] = $s;
json_return_and_die($result);
}
}

View File

@@ -12,7 +12,6 @@ class Wall_upload extends \Zotlabs\Web\Controller {
function post() {
$using_api = ((x($_FILES,'media')) ? true : false);
if($using_api) {

View File

@@ -204,7 +204,7 @@ class Webpages extends Controller {
$x['pagetitle'] = 'home';
$a = '';
$editor = status_editor($a,$x,false,'Webpages');
$editor = status_editor($x, false, 'Webpages');
$pages = null;

View File

@@ -76,7 +76,10 @@ class Wfinger extends \Zotlabs\Web\Controller {
}
}
else {
$r = channelx_by_nick($channel);
// Also provide already deleted channels info here.
// This is required in the case where we need to verify keys
// of updates which we have got via directory sync.
$r = channelx_by_nick($channel, true);
}
}
@@ -94,10 +97,6 @@ class Wfinger extends \Zotlabs\Web\Controller {
'href' => z_root() . '/owa',
],
];
}
if($resource && $r) {

View File

@@ -209,7 +209,6 @@ class Browser extends DAV\Browser\Plugin {
// upload access. system.thumbnail_security should be set to 1 if you want to include these
// types
$is_creator = false;
$photo_icon = '';
$preview_style = intval(get_config('system','thumbnail_security',0));
@@ -369,6 +368,7 @@ class Browser extends DAV\Browser\Plugin {
'$upload' => t('Add Files'),
'$is_owner' => $is_owner,
'$is_admin' => is_site_admin(),
'$has_perms' => perm_is_allowed($channel_id, get_observer_hash(), 'write_storage'),
'$admin_delete_label' => t('Admin Delete'),
'$parentpath' => $parent_path,
'$folder_parent' => $folder_parent,

View File

@@ -30,9 +30,14 @@ class Epubthumb {
*/
function Thumb($attach, $preview_style, $height = 300, $width = 300) {
$file = dbunescbin($attach['content']);
if (!$file) {
return;
}
$photo = false;
$ep = new \EPub(dbunescbin($attach['content']));
$ep = new \EPub($file);
$data = $ep->Cover();
if($data['found']) {

View File

@@ -11,9 +11,16 @@ class Mp3audio {
}
function Thumb($attach,$preview_style,$height = 300, $width = 300) {
$file = dbunescbin($attach['content']);
if (!$file) {
return;
}
$photo = false;
$p = new ID3Parser();
$id = $p->analyze(dbunescbin($attach['content']));
$id = $p->analyze($file);
$photo = isset($id['id3v2']['APIC'][0]['data']) ? $id['id3v2']['APIC'][0]['data'] : null;
if(is_null($photo) && isset($id['id3v2']['PIC'][0]['data'])) {

View File

@@ -11,9 +11,13 @@ class Pdf {
function Thumb($attach,$preview_style,$height = 300, $width = 300) {
$file = dbunescbin($attach['content']);
if (!$file) {
return;
}
$photo = false;
$file = dbunescbin($attach['content']);
$tmpfile = $file . '.pdf';
$outfile = $file . '.jpg';

View File

@@ -11,7 +11,12 @@ class Text {
function Thumb($attach,$preview_style,$height = 300, $width = 300) {
$stream = @fopen(dbunescbin($attach['content']),'rb');
$file = dbunescbin($attach['content']);
if (!$file) {
return;
}
$stream = @fopen($file,'rb');
if($stream) {
$content = trim(stream_get_contents($stream,4096));
$content = str_replace("\r",'',$content);
@@ -25,13 +30,13 @@ class Text {
$colour = imagecolorallocate($image,0,0,0);
$border = imagecolorallocate($image,208,208,208);
$x1 = 0;
$y1 = 0;
$x2 = ImageSX($image) - 1;
$y2 = ImageSY($image) - 1;
$x1 = 0;
$y1 = 0;
$x2 = ImageSX($image) - 1;
$y2 = ImageSY($image) - 1;
for($i = 0; $i < 2; $i++) {
ImageRectangle($image, $x1++, $y1++, $x2--, $y2--, $border);
for($i = 0; $i < 2; $i++) {
ImageRectangle($image, $x1++, $y1++, $x2--, $y2--, $border);
}
foreach($content_a as $l => $t) {
@@ -46,4 +51,4 @@ class Text {
imagejpeg($image,dbunescbin($attach['content']) . '.thumb');
}
}
}
}

View File

@@ -11,16 +11,19 @@ class Video {
function Thumb($attach,$preview_style,$height = 300, $width = 300) {
$file = dbunescbin($attach['content']);
if (!$file) {
return;
}
$photo = false;
$t = explode('/',$attach['filetype']);
if($t[1])
$extension = '.' . $t[1];
else
return;
return;
$file = dbunescbin($attach['content']);
$tmpfile = $file . $extension;
$outfile = $file . '.jpg';
@@ -40,7 +43,7 @@ class Video {
$ffmpeg = trim(shell_exec('which ffmpeg'));
if($ffmpeg) {
if($ffmpeg) {
logger('ffmpeg not found in path. Video thumbnails may fail.');
}
@@ -59,7 +62,7 @@ class Video {
@rename($outfile,$file . '.thumb');
}
}
@unlink($tmpfile);
}
}

36
Zotlabs/Update/_1256.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
namespace Zotlabs\Update;
class _1256 {
function run() {
dbq("START TRANSACTION");
$r1 = dbq("TRUNCATE TABLE updates");
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
$r2a = dbq("ALTER TABLE updates add ud_update numeric(1) NOT NULL DEFAULT '0'");
$r2b = dbq("CREATE INDEX ud_update ON updates (ud_update)");
$r2 = ($r2a && $r2b);
}
if(ACTIVE_DBTYPE == DBTYPE_MYSQL) {
$r2 = dbq("ALTER TABLE updates add ud_update tinyint(1) NOT NULL DEFAULT '0',
ADD INDEX (ud_update);"
);
}
if($r1 && $r2) {
dbq("COMMIT");
return UPDATE_SUCCESS;
}
q("ROLLBACK");
return UPDATE_FAILED;
}
}

33
Zotlabs/Update/_1257.php Normal file
View File

@@ -0,0 +1,33 @@
<?php
namespace Zotlabs\Update;
class _1257 {
function run() {
dbq("START TRANSACTION");
$r1 = dbq("TRUNCATE TABLE updates");
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
$r2 = dbq("ALTER TABLE updates add ud_host text NOT NULL DEFAULT ''");
}
if(ACTIVE_DBTYPE == DBTYPE_MYSQL) {
$r2 = dbq("ALTER TABLE updates add ud_host varchar(191) NOT NULL DEFAULT ''");
}
$r3 = dbq("ALTER TABLE updates DROP COLUMN ud_guid");
if($r1 && $r2 && $r3) {
dbq("COMMIT");
return UPDATE_SUCCESS;
}
q("ROLLBACK");
return UPDATE_FAILED;
}
}

14
Zotlabs/Update/_1258.php Normal file
View File

@@ -0,0 +1,14 @@
<?php
namespace Zotlabs\Update;
class _1258 {
function run() {
dbq("DELETE FROM pconfig WHERE cat = 'channelreputation'");
dbq("DELETE FROM iconfig WHERE cat = 'channelreputation'");
}
}

30
Zotlabs/Update/_1259.php Normal file
View File

@@ -0,0 +1,30 @@
<?php
namespace Zotlabs\Update;
class _1259 {
function run() {
dbq("START TRANSACTION");
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
$r = true;
}
if(ACTIVE_DBTYPE == DBTYPE_MYSQL) {
$r = dbq("ALTER TABLE cache MODIFY COLUMN v MEDIUMTEXT NOT NULL");
}
if($r) {
dbq("COMMIT");
return UPDATE_SUCCESS;
}
q("ROLLBACK");
return UPDATE_FAILED;
}
}

View File

@@ -4,7 +4,7 @@ namespace Zotlabs\Web;
use DateTime;
use DateTimeZone;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\Crypto;
use Zotlabs\Lib\Keyutils;
use Zotlabs\Lib\Webfinger;
@@ -212,7 +212,8 @@ class HTTPSig {
if (in_array('digest', $signed_headers)) {
$result['content_signed'] = true;
$digest = explode('=', $headers['digest'], 2);
$digest = explode('=', $headers['digest'], 2);
$digest[0] = strtoupper($digest[0]);
if ($digest[0] === 'SHA-256')
$hashalg = 'sha256';
if ($digest[0] === 'SHA-512')
@@ -303,7 +304,8 @@ class HTTPSig {
// $force is used to ignore the local cache and only use the remote data; for instance the cached key might be stale
if (!$force) {
$x = q("select * from xchan join hubloc on xchan_hash = hubloc_hash where (hubloc_id_url = '%s' or hubloc_hash = '%s') and hubloc_network in ('zot6', 'activitypub') order by hubloc_id desc",
$x = q("select * from xchan join hubloc on xchan_hash = hubloc_hash where (hubloc_addr = '%s' or hubloc_id_url = '%s' or hubloc_hash = '%s') and hubloc_network in ('zot6', 'activitypub') order by hubloc_id desc",
dbesc(str_replace('acct:', '', $url)),
dbesc($url),
dbesc($url)
);
@@ -323,7 +325,7 @@ class HTTPSig {
}
// The record wasn't in cache. Fetch it now.
$r = ActivityStreams::fetch($id);
$r = Activity::get_actor($id);
$signatureAlgorithm = EMPTY_STR;
if ($r) {
@@ -378,7 +380,9 @@ class HTTPSig {
$best = [];
if (!$force) {
$x = q("select * from xchan join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' and hubloc_network in ('zot6', 'activitypub') order by hubloc_id desc",
$x = q("select * from xchan join hubloc on xchan_hash = hubloc_hash where (hubloc_addr = '%s' or hubloc_id_url = '%s' or hubloc_hash = '%s') and hubloc_network in ('zot6', 'activitypub') order by hubloc_id desc",
dbesc(str_replace('acct:', '', $id)),
dbesc($id),
dbesc($id)
);

View File

@@ -224,7 +224,7 @@ class Router {
}
elseif(function_exists(App::$module . '_init')) {
$func = App::$module . '_init';
$func($a);
$func();
}
}
@@ -257,13 +257,13 @@ class Router {
if(function_exists(str_replace('-', '_', $current_theme[0]) . '_init')) {
$func = str_replace('-', '_', $current_theme[0]) . '_init';
$func($a);
$func();
}
elseif (x(App::$theme_info, 'extends') && file_exists('view/theme/' . App::$theme_info['extends'] . '/php/theme.php')) {
require_once('view/theme/' . App::$theme_info['extends'] . '/php/theme.php');
if(function_exists(str_replace('-', '_', App::$theme_info['extends']) . '_init')) {
$func = str_replace('-', '_', App::$theme_info['extends']) . '_init';
$func($a);
$func();
}
}
@@ -275,7 +275,7 @@ class Router {
}
elseif(function_exists(App::$module . '_post')) {
$func = App::$module . '_post';
$func($a);
$func();
}
}
@@ -289,7 +289,7 @@ class Router {
}
elseif(function_exists(App::$module . '_content')) {
$func = App::$module . '_content';
$arr = array('content' => $func($a));
$arr = array('content' => $func());
}
}
call_hooks(App::$module . '_mod_aftercontent', $arr);

View File

@@ -26,7 +26,7 @@ class Activity_filter {
$starred_active = '';
$conv_active = '';
$tabs = [];
$cmd = \App::$cmd;
$cmd = 'network'; //\App::$cmd;
if(x($_GET,'dm')) {
$dm_active = (($_GET['dm'] == 1) ? 'active' : '');

View File

@@ -34,7 +34,7 @@ class Item {
if($arr['title']) {
$r = q("select item.* from item left join iconfig on item.id = iconfig.iid
where item.uid = %d and iconfig.cat = 'system' and iconfig.v = '%s'
and iconfig.k = 'WEBPAGE' and item_type = %d $sql_options $revision limit 1",
and iconfig.k = 'WEBPAGE' and item_type = %d $sql_extra $revision limit 1",
intval($channel_id),
dbesc($arr['title']),
intval(ITEM_TYPE_WEBPAGE)

View File

@@ -60,8 +60,10 @@ class Messages {
}
$channel = App::get_channel();
$item_normal_i = str_replace('item.', 'i.', item_normal());
$item_normal_c = str_replace('item.', 'c.', item_normal());
$item_normal = item_normal();
$item_normal .= " and item.verb != '" . ACTIVITY_FOLLOW . "'";
$item_normal_i = str_replace('item.', 'i.', $item_normal);
$item_normal_c = str_replace('item.', 'c.', $item_normal);
$entries = [];
$limit = 30;
$dummy_order_sql = '';

View File

@@ -157,9 +157,11 @@ class Notifications {
'url' => 'pubstream',
'label' => t('Public stream')
],
/*
'markall' => [
'label' => t('Mark all notifications seen')
],
*/
'filter' => [
'posts_label' => t('Show new posts only'),
'name_label' => t('Filter by name or address')

View File

@@ -67,7 +67,7 @@ class Pinned {
$conv_responses = [];
if($item['obj_type'] === ACTIVITY_OBJ_EVENT) {
if(in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
$conv_responses['attendyes'] = [ 'title' => t('Attending','title') ];
$conv_responses['attendno'] = [ 'title' => t('Not attending','title') ];
$conv_responses['attendmaybe'] = [ 'title' => t('Might attend','title') ];

View File

@@ -60,10 +60,10 @@ require_once('include/bbcode.php');
require_once('include/items.php');
define('PLATFORM_NAME', 'hubzilla');
define('STD_VERSION', '8.2');
define('STD_VERSION', '8.8');
define('ZOT_REVISION', '6.0');
define('DB_UPDATE_VERSION', 1255);
define('DB_UPDATE_VERSION', 1259);
define('PROJECT_BASE', __DIR__);
@@ -84,6 +84,10 @@ define('DIRECTORY_MODE_PRIMARY', 0x0001); // There can only be *one* primary dir
define('DIRECTORY_MODE_SECONDARY', 0x0002); // All other mirror directory servers
define('DIRECTORY_MODE_STANDALONE', 0x0100); // A detached (off the grid) hub with itself as directory server.
define('DIRECTORY_FLAG_OK', 0);
define('DIRECTORY_FLAG_UNSAFE', 1);
define('DIRECTORY_FLAG_HIDDEN', 2);
// We will look for upstream directories whenever me make contact
// with other sites, but if this is a new installation and isn't
// a standalone hub, we need to seed the service with a starting
@@ -96,8 +100,7 @@ define('DIRECTORY_FALLBACK_MASTER', 'https://hub.netzgemeinde.eu');
function get_directory_fallback_servers() {
$ret = [
'https://hub.netzgemeinde.eu',
'https://zotsite.net',
'https://hub.libranet.de'
'https://zotsite.net'
];
return $ret;
@@ -364,11 +367,6 @@ define('POLL_TENSCALE', 0x0002); // 1-10
define('POLL_MULTIPLE_CHOICE', 0x0004);
define('POLL_OVERWRITE', 0x8000); // If you vote twice remove the prior entry
define('UPDATE_FLAGS_UPDATED', 0x0001);
define('UPDATE_FLAGS_FORCED', 0x0002);
define('UPDATE_FLAGS_DELETED', 0x1000);
define('HUBLOC_OFFLINE', 0x0001);
define('DROPITEM_NORMAL', 0);
@@ -874,7 +872,8 @@ class App {
date_default_timezone_set('UTC');
self::$config = ['system' => []];
self::$page = [];
self::$page['htmlhead'] = '';
self::$pager = [];
self::$query_string = '';
@@ -944,14 +943,15 @@ class App {
'ttf' => 'font/ttf',
'woff' => 'font/woff',
'woff2' => 'font/woff2',
'svg' => 'image/svg+xml'
'svg' => 'image/svg+xml',
'jsonld' => 'application/ld+json'
];
if (array_key_exists($filext, $serve_rawfiles) && file_exists(self::$cmd)) {
$staticfilecwd = getcwd();
$staticfilerealpath = realpath(self::$cmd);
if (strpos($staticfilerealpath, $staticfilecwd) !== 0) {
http_status_exit(404, 'not found');
http_status_exit(404, 'not found', 1);
}
$staticfileetag = '"' . md5($staticfilerealpath . filemtime(self::$cmd)) . '"';
@@ -961,7 +961,7 @@ class App {
// If HTTP_IF_NONE_MATCH is same as the generated ETag => content is the same as browser cache
// So send a 304 Not Modified response header and exit
if ($_SERVER['HTTP_IF_NONE_MATCH'] == $staticfileetag) {
http_status_exit(304, 'not modified');
http_status_exit(304, 'not modified', 1);
}
}
header("Content-type: " . $serve_rawfiles[$filext]);

View File

@@ -25,6 +25,7 @@
"require": {
"php": ">=8.0.2",
"ext-curl": "*",
"ext-iconv": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-openssl": "*",
@@ -41,13 +42,14 @@
"lukasreschke/id3parser": "^0.0.3",
"smarty/smarty": "^4.1",
"ramsey/uuid": "^4.1",
"twbs/bootstrap": "5.3.0-alpha1",
"twbs/bootstrap": "^5.3",
"blueimp/jquery-file-upload": "^10.3",
"desandro/imagesloaded": "^4.1",
"phpseclib/phpseclib": "~2.0",
"jbroadway/urlify": "^1.2",
"chillerlan/php-qrcode": "^4.3",
"spomky-labs/otphp": "^11.1"
"spomky-labs/otphp": "^11.1",
"patrickschur/language-detection": "^5.3"
},
"require-dev": {
"phpunit/phpunit": "^9.4",

Some files were not shown because too many files have changed in this diff Show More