Compare commits

...

1427 Commits
7.2 ... 9.0.2

Author SHA1 Message Date
Mario
0c1d0f7498 version 9.0.2 2024-06-07 09:25:15 +00:00
Mario
81ba070e1a update changelog
(cherry picked from commit bd5f77dbeb)

Co-authored-by: Mario <mario@mariovavti.com>
2024-06-07 09:23:32 +00:00
Mario
a7812657f1 update changelog
(cherry picked from commit d862a6f075)

Co-authored-by: Mario <mario@mariovavti.com>
2024-06-07 09:23:02 +00:00
Mario
18725c47a0 move button class to the right dom
(cherry picked from commit 59b8c8ad48)

Co-authored-by: Mario <mario@mariovavti.com>
2024-06-07 09:12:32 +00:00
Mario
75e1b70584 php warnings/errors
(cherry picked from commit 10d1cbd3ce)

Co-authored-by: Mario <mario@mariovavti.com>
2024-06-04 09:09:41 +00:00
Mario
1dc73935d9 deal with inReplyTo array
(cherry picked from commit 2145207ad2)

Co-authored-by: Mario <mario@mariovavti.com>
2024-06-04 09:08:32 +00:00
Mario
7d7b43c5b9 hotfix to mitigate queueworker crash
(cherry picked from commit a4d63ab9a3)

Co-authored-by: Mario <mario@mariovavti.com>
2024-06-04 09:06:50 +00:00
Mario
b5223a4efb add pdl for mod home
(cherry picked from commit fe43e0994f)
2024-03-27 10:01:33 +00:00
Mario
d71c2c245f reduce default directory result set
(cherry picked from commit f85d2d3423)
2024-03-26 14:59:45 +00:00
Mario
526729c0f1 changelog
(cherry picked from commit 418b1eaf78)
2024-03-26 10:06:05 +00:00
Mario
1cd3369f6a version 9.0.1 2024-03-26 09:53:38 +00:00
Mario
c26ae553e6 if the updated item contains an open modal, the modal we be replaced with the new data but the backdrop will stay because it is attached to the end of the page -> remove it
(cherry picked from commit e0ac7b7f9f)
2024-03-26 09:28:25 +00:00
Mario
8d78698d00 deprecated bootstrap namespace in list mode
(cherry picked from commit 80d1e07908)
2024-03-25 21:53:25 +00:00
Mario
d5c189753a wrong dreport link in blog mode
(cherry picked from commit f72f5c7321)
2024-03-25 21:53:06 +00:00
Mario
9861e7a0c4 more bootstrap override
(cherry picked from commit a5d483fb5d)
2024-03-25 21:52:42 +00:00
Mario
6d5fa9205c more remove additional linebreaks after block element plus test
(cherry picked from commit 53354a1930)
2024-03-25 21:52:14 +00:00
Mario
0fee7804fb allow to run additional site specific commands at the end of util/udall
(cherry picked from commit c052b7fa99)
2024-03-25 21:51:49 +00:00
Mario
4002dbaa8b Merge branch 'master' of https://framagit.org/hubzilla/core 2024-03-25 17:32:11 +00:00
Mario
57e32a7912 add observer to the permissions query. this should not be necessary but it makes it clear why it should be included in the cache key 2024-03-25 17:31:53 +00:00
Mario
b6a72d6e4e tilt the piin
(cherry picked from commit 637f39f282)
2024-03-25 17:19:32 +00:00
Mario
6e592ed200 add the observer hash to the cache key in categories_widget() 2024-03-25 17:18:26 +00:00
Mario
6c033fc776 Merge branch 'fix-category-widget-template' into 'dev'
Fix smarty deprecation warning in category widget.

See merge request hubzilla/core!2116

(cherry picked from commit 2ff84ab25a)

b139e5bb Fix smarty deprecation warning in category widget.
2024-03-25 14:21:39 +00:00
Mario
7c4362db53 make sure we preserve linefeeds in the actual content of lists and tables also add tests
(cherry picked from commit 3c0d6339bb)
2024-03-24 17:00:56 +00:00
Mario
f7bf9ede72 revert default to activity type Article until we have a more stable solution to override it for platforms which do not support it
(cherry picked from commit ecdd9a4d6e)
2024-03-23 11:20:44 +00:00
Mario
1aeb05628b Merge branch '9.0RC' 2024-03-22 08:37:29 +00:00
Mario
b464fae3bf version 9.0 2024-03-22 08:36:38 +00:00
Mario
a34ce0732d Merge branch 'dev' into 9.0RC 2024-03-22 08:36:07 +00:00
Mario
f457b6623d changelog 2024-03-22 08:35:55 +00:00
Mario
01ebd51fb2 Merge branch 'dev' into 9.0RC 2024-03-22 08:27:18 +00:00
Mario
cb25fc031b use the correct tag for ordered lists 2024-03-22 08:23:44 +00:00
Mario
6c6fc82f43 Merge branch 'dev' into 9.0RC 2024-03-22 08:15:20 +00:00
Mario
990017b588 remove some unused variables 2024-03-22 08:14:41 +00:00
Mario
192ab22cda Merge branch 'dev' into 9.0RC 2024-03-21 20:48:33 +00:00
Mario
5e5a0d7c91 remove friendica specific hack that is not needed anymore 2024-03-21 20:48:10 +00:00
Mario
2dc1adf091 Merge branch 'dev' into 9.0RC 2024-03-21 11:37:55 +00:00
Mario
371b8440c3 adjust tests after recent commit 2024-03-21 11:04:03 +00:00
Mario
49509e7347 more whitespace fixes and some docu 2024-03-21 09:47:34 +00:00
Mario
66f5b34c07 possible fix for issue #1843 2024-03-20 21:08:23 +00:00
Mario
6a3d372050 RC3 2024-03-20 19:41:28 +00:00
Mario
c95359024c Merge branch 'dev' into 9.0RC 2024-03-20 19:39:00 +00:00
Mario
edf898d7b7 it appears the smallest size for pt videos is now 720 2024-03-20 19:33:50 +00:00
Mario
ee0060619d css fix 2024-03-20 15:25:38 +00:00
Mario
4f8ede35bd Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-03-20 13:37:11 +00:00
Mario
9d9c102da8 no extra margin under lists 2024-03-20 13:36:55 +00:00
Mario
3de8f5e7de deal with wihitespace issues in tables and lists and add tests 2024-03-20 14:35:43 +01:00
Mario
a18e873d08 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-03-20 09:31:58 +01:00
Mario
b3c260a145 fix reshares from streams loosing image 2024-03-20 09:31:17 +01:00
Mario
1097bcdaf9 Merge branch 'dev' into 9.0RC 2024-03-19 09:53:33 +00:00
Mario
cfde1be097 Merge branch 'dev' into 'dev'
Recreated hmessage.po for pt-br

See merge request hubzilla/core!2115
2024-03-19 09:51:15 +00:00
Pascal Deklerck
6df4da5313 Recreated hmessage.po for pt-br 2024-03-19 09:51:14 +00:00
Mario
f910de849f Merge branch 'dev' into 9.0RC 2024-03-19 09:46:21 +00:00
Mario
d6eaeba239 changelog
(cherry picked from commit 5c2e10c01e)
2024-03-19 09:45:36 +00:00
Mario
5c2e10c01e changelog 2024-03-19 09:44:18 +00:00
Mario
8754f72e63 fix cover photos not uploaded into folder due to missing source option 2024-03-19 10:39:59 +01:00
Mario
569f243ebd Merge branch 'dev' into 9.0RC 2024-03-18 22:10:16 +00:00
Mario
651a3f8380 docu 2024-03-18 22:09:05 +00:00
Mario
40714ecdd0 changelog 2024-03-18 22:02:09 +00:00
Mario
d4b1bcd641 Merge branch 'dev' into 9.0RC 2024-03-18 09:12:58 +00:00
Mario
acc1834b0d make theme compatible with rc version 2024-03-18 09:12:35 +00:00
Mario
e237cf226a Merge branch 'dev' into 9.0RC 2024-03-18 09:10:34 +00:00
Mario
7c5a0887cc css fix 2024-03-18 09:10:07 +00:00
Mario
0745d0616a Merge branch 'dev' into 9.0RC 2024-03-17 21:34:06 +00:00
Mario
9cbb9a4874 theme min/max version and minor css fix 2024-03-17 21:30:50 +00:00
Mario
14f3b72c82 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-03-17 22:22:33 +01:00
Mario
b05845f495 cleanup some ancient code and fix check for $path so that it will not pass if theme_include() will not return anything. also add an empty zen.css file for the zen template 2024-03-17 22:21:55 +01:00
Mario
2114779037 Merge branch 'dev' into 9.0RC 2024-03-17 11:01:27 +00:00
Mario
937b6d360e fix hardcoded color attr 2024-03-17 11:00:50 +00:00
Mario
0d30eed4a7 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-03-17 10:53:32 +00:00
Mario
39d4f67417 add Emoji to the AP schema 2024-03-17 10:53:09 +00:00
Mario
68d989c79e slightly adjust text sizing
(cherry picked from commit 9600789d6b)
2024-03-16 19:40:57 +00:00
Mario
9600789d6b slightly adjust text sizing 2024-03-16 19:39:48 +00:00
Mario
ea7559c158 RC2 2024-03-16 16:24:27 +00:00
Mario
baa12b7497 Merge branch 'dev' into 9.0RC 2024-03-16 16:23:32 +00:00
Mario
ac4aa6a9ea css fixes 2024-03-16 16:22:39 +00:00
Mario
732dbfd6f5 maybe git can be removed again now after the streams lib got removed?
(cherry picked from commit 5860abf46f)
2024-03-16 16:01:36 +00:00
Mario
5860abf46f maybe git can be removed again now after the streams lib got removed? 2024-03-16 15:50:58 +00:00
Mario
2874d3e1e1 Merge branch 'dev' into 9.0RC 2024-03-16 15:47:55 +00:00
Mario
42b0205ad0 apply the streams fixes manually until the addition of the streams library is sorted 2024-03-16 15:47:25 +00:00
Mario
36778850ee Merge branch 'dev' into 9.0RC 2024-03-16 12:18:46 +00:00
Mario
19c0e97658 add git again allthough it is not clear why it is required 2024-03-16 12:18:24 +00:00
Mario
fe018d646a more composer weirdness 2024-03-16 12:09:49 +00:00
Mario
24132e56d9 Merge branch 'dev' into 9.0RC 2024-03-16 11:56:44 +00:00
Mario
8fc0210428 Revert "another attmpt to install streams/php-jcs via composer"
This reverts commit 5af3c35778
2024-03-16 11:54:45 +00:00
Mario
64560cbca9 Revert "try installing git"
This reverts commit 0b4e086376
2024-03-16 11:54:07 +00:00
Mario
6e97c97920 Revert "remove streams folder"
This reverts commit 216f3755fc
2024-03-16 11:53:39 +00:00
Mario
916edcb45e Revert "really add streams folder"
This reverts commit f402baffd3
2024-03-16 11:53:16 +00:00
Mario
8873c10364 Merge branch '9.0RC' of https://framagit.org/hubzilla/core into 9.0RC 2024-03-16 11:50:42 +00:00
Mario
77e1220cf9 fix version 2024-03-16 11:50:16 +00:00
Mario
f402baffd3 really add streams folder 2024-03-16 11:48:27 +00:00
Mario
216f3755fc remove streams folder 2024-03-16 11:45:49 +00:00
Mario
d846cefade adjust encrypted content representation and also add it to bb_to_markdown
(cherry picked from commit f3efdbf230)
2024-03-15 22:36:44 +00:00
Mario
f3efdbf230 adjust encrypted content representation and also add it to bb_to_markdown 2024-03-15 22:34:27 +00:00
Mario
826ef11247 bump dev version 2024-03-15 19:05:55 +00:00
Mario
b68ddc4cd3 version, strings and dump composer autoload 2024-03-15 18:58:01 +00:00
Mario
41f909c415 update redbasic screenshot 2024-03-15 17:36:44 +00:00
Mario
0b4e086376 try installing git 2024-03-15 18:25:53 +01:00
Mario
5af3c35778 another attmpt to install streams/php-jcs via composer 2024-03-15 17:14:31 +01:00
Mario
dddcddc453 refactor sodium b2b encryption 2024-03-15 11:30:28 +00:00
Mario
754d90a676 fix overlay z-index 2024-03-14 19:21:01 +00:00
Mario
8b0dce56ad remove some now redundant css 2024-03-14 19:11:25 +00:00
Mario
42696606e3 wrong logic 2024-03-14 16:03:02 +00:00
Mario
b645ede168 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-03-14 13:35:39 +00:00
Mario
6e12b5ec08 fix shortnames replaced in html tags 2024-03-14 13:35:21 +00:00
Mario
fbf36992be Merge branch 'add-testing-doc' into 'dev'
Add some developer docs for the test system.

See merge request hubzilla/core!2113
2024-03-14 12:42:36 +00:00
Mario
e0de813700 Merge branch 'fix-test-setup-on-mariadb' into 'dev'
Fix test db setup on MySQL/Mariadb + changed default

See merge request hubzilla/core!2112
2024-03-14 12:42:04 +00:00
Harald Eilertsen
39448a0871 Fix test db setup on MySQL/Mariadb + changed default 2024-03-14 12:42:03 +00:00
Mario
4fb37ef6f3 revert adding of zip and bump composer php version to 8.1 2024-03-14 12:40:07 +00:00
Mario
a9d4adaf23 Revert "next try to use the streams php-jcs library until the floats issue will be fixed upstream. see here for reference https://codeberg.org/streams/streams/issues/151"
This reverts commit 70dfce356b.
2024-03-14 12:30:05 +00:00
Mario
70dfce356b next try to use the streams php-jcs library until the floats issue will be fixed upstream. see here for reference https://codeberg.org/streams/streams/issues/151 2024-03-14 11:15:20 +00:00
Mario
10fbfa06e9 add fix again after escaping composer hell 2024-03-14 11:06:32 +00:00
Mario
6315757967 Revert "use the streams php-jcs library until the floats issue will be fixed upstream. see here for reference https://codeberg.org/streams/streams/issues/151"
This reverts commit 81ce67df94.
2024-03-14 11:02:31 +00:00
Mario
9ddd840897 evert "fix deprecation warning"
This reverts commit 898762dd95.
2024-03-14 11:02:10 +00:00
Mario
6c5627ac0e Revert "update lock file"
This reverts commit a93fed5ae2.
2024-03-14 11:01:36 +00:00
Mario
c2d6d376a4 Revert "revert addition of zip"
This reverts commit 55532c7cb1.
2024-03-14 11:01:20 +00:00
Mario
55532c7cb1 revert addition of zip 2024-03-14 10:58:20 +00:00
Mario
a93fed5ae2 update lock file 2024-03-14 10:49:41 +00:00
Mario
ba1b48f177 lets try this 2024-03-14 10:45:09 +00:00
Mario
898762dd95 fix deprecation warning 2024-03-14 10:29:07 +00:00
Mario
81ce67df94 use the streams php-jcs library until the floats issue will be fixed upstream. see here for reference https://codeberg.org/streams/streams/issues/151 2024-03-14 10:18:51 +00:00
Mario
55097c47c5 Revert "composer update and use the fixed streams php-jcs library until the floats issue will be fixed upstream. see here for reference https://codeberg.org/streams/streams/issues/151"
This reverts commit 6bf61dfa6b.
2024-03-14 10:13:22 +00:00
Mario
97b82fc77b fix dreport links after recent changes 2024-03-14 09:53:40 +00:00
Mario
b7bda0b87d return false if we have nothing to look at 2024-03-14 09:47:08 +00:00
Mario
6bf61dfa6b composer update and use the fixed streams php-jcs library until the floats issue will be fixed upstream. see here for reference https://codeberg.org/streams/streams/issues/151 2024-03-14 09:35:09 +00:00
Mario
0e59cfb839 fix code comment 2024-03-13 14:08:56 +01:00
Mario
328ce0a837 fix another regression from last Lib/Config refactor which returned the default falue in case the value was an array. also add a testcase for this situation 2024-03-13 14:05:58 +01:00
Mario
34e24ea5e9 fix modal headerà 2024-03-12 09:11:53 +00:00
Mario
907426af5e deprecated function 2024-03-11 20:42:21 +00:00
Mario
360713c689 add sodium-plus js crypto library 2024-03-10 22:38:21 +00:00
Mario
ee8aba3221 implement sodium-plus library to replace unmaintained sjcl 2024-03-10 22:35:59 +00:00
Harald Eilertsen
ae657754b0 doc: Add some developer docs for the test system.
Not sure if this is too long, or if it would be better to split it into
multiple files. Also, still missing the "How to write your own tests"
section.
2024-03-10 21:41:11 +01:00
Mario
0a730935f5 remove superfluous () 2024-03-10 13:14:10 +01:00
Mario
d285da09fe add the file 2024-03-10 13:12:51 +01:00
Mario
b291f1bad3 move escape_tags() to Lib/Text.php and add test 2024-03-10 13:10:42 +01:00
Mario
e1b660bfa3 we usually use ENT_COMPAT for content, so stick to this 2024-03-10 10:06:15 +00:00
Mario
0036c0cde9 remove logging 2024-03-09 21:00:13 +00:00
Mario
49c1833a46 bump version 2024-03-09 20:58:53 +00:00
Mario
46fa26502b more work on emojis 2024-03-09 20:53:18 +00:00
Mario
ba1e705c61 passing null to mb_strlen() is deprecated 2024-03-08 10:28:48 +00:00
Mario
043e2ff58b check if term is set before processing it 2024-03-08 09:23:31 +00:00
Mario
deba1863f5 fix php warnings 2024-03-08 09:16:27 +00:00
Mario
0e27f010f9 start sending articles instead of notes by default 2024-03-08 08:44:16 +00:00
Mario
45b1be8962 inbound support for custom emojis 2024-03-08 08:42:50 +00:00
Mario
fe9ca30c5e list attachments in the original order 2024-03-07 10:38:08 +00:00
Mario
9e8ba5f6e2 add at the top to maintain original order 2024-03-07 10:16:35 +00:00
Mario
5207e1e774 remove unused include 2024-03-07 09:06:20 +00:00
Mario
c1228d6b6d whitespace 2024-03-07 10:01:46 +01:00
Mario
6262d351b7 fix deprecation warning and add test 2024-03-07 10:00:02 +01:00
Mario
27e57ff7aa fix another php warning 2024-03-06 20:52:36 +00:00
Mario
74fc7508f3 fix php warning 2024-03-06 20:49:01 +00:00
Mario
3eea4f475c Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-03-06 21:10:24 +01:00
Mario
37b22fe542 fix unterminated entity reference error when dealing with domxpath and add a test 2024-03-06 21:08:46 +01:00
Mario
b5b8106e7a minor refactor 2024-03-06 16:08:53 +00:00
Mario
b77100ff6d update fullcalendar 2024-03-06 14:20:21 +00:00
Mario
5eb6572277 update composer libs 2024-03-06 13:57:07 +00:00
Mario
69bed9c889 minor mod thing fixes 2024-03-06 13:04:06 +00:00
Mario
3c88c5e66a cleanup context and introduce schema:identifier for future use 2024-03-06 13:02:22 +00:00
Mario
d40d62ac4f bump version 2024-03-05 10:10:23 +00:00
Mario
d23ed6b11f improve things display a little 2024-03-05 09:45:49 +00:00
Mario
1e2a4a57b6 Merge branch 'fix-admin-site-page' into 'dev'
Remove obsolete field for system lang from site admin page.

See merge request hubzilla/core!2111
2024-03-04 21:37:37 +00:00
Mario
7892eeb2d2 Thing > Page 2024-03-04 21:27:53 +00:00
Mario
d7ceb977da basic AS2 support for things 2024-03-04 21:24:21 +00:00
Harald Eilertsen
36d0594b8e Remove obsolete field for system lang from site admin page.
The field was commented out in the module, but still remained in the
template. This patch also removes some processing to discover available
languages whose result were not used.

This should fix https://framagit.org/hubzilla/core/-/issues/1840
2024-03-03 12:30:27 +01:00
Mario
3f32a5239d we are checking for null|array union type later - false would throw an error 2024-03-01 19:17:57 +00:00
Mario
15a7d2d4de Merge branch 'some-bbcode-cleanup' into 'dev'
Add some beginning tests for bbcode, and a bit of refactoring

See merge request hubzilla/core!2110
2024-03-01 16:18:07 +00:00
Harald Eilertsen
80ed2ff89a Add some beginning tests for bbcode, and a bit of refactoring 2024-03-01 16:18:07 +00:00
Mario
37a0343163 Merge branch 'update-doxygen-config' into 'dev'
Update Doxygen config for generating online API docs

See merge request hubzilla/core!2109
2024-03-01 16:14:00 +00:00
Mario
8529e2f14e Merge branch 'dba-transactions' into 'dev'
include/dba: Make Dba driver transaction aware.

See merge request hubzilla/core!2108
2024-03-01 16:11:24 +00:00
Mario
b73401bd7f handle imagick readImageBlob() exception 2024-03-01 16:01:53 +00:00
Mario
af839a0589 AS2 Follow/Ignore 2024-03-01 15:47:40 +00:00
Mario
4bbeb224f6 more cleanup 2024-02-29 21:11:39 +00:00
Mario
8435d9eb13 some cleanup 2024-02-29 17:35:05 +00:00
Mario
d97df1859f Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-02-29 17:06:18 +00:00
Mario
46f67eaa1e AS2 Update and implement a first draft of AS2 Profile activities 2024-02-29 17:05:48 +00:00
System user; root
54451851bb changelog
(cherry picked from commit 5d64a9c90f)
2024-02-29 10:19:46 +00:00
System user; root
5b7387459c version 8.8.8 2024-02-29 11:05:01 +01:00
System user; root
5d64a9c90f changelog 2024-02-29 11:03:28 +01:00
System user; root
ffaa985339 streams compatibility 2024-02-29 11:01:30 +01:00
Mario
291e12574a more cleanup 2024-02-28 13:16:47 +00:00
Mario
fc5b5ba021 if we rename a folder in dav we should also move its content 2024-02-28 12:04:46 +00:00
Mario
056c55a963 bump version 2024-02-28 10:20:34 +00:00
Mario
02a0af3eef remove poke and mood from apps 2024-02-28 10:19:57 +00:00
Mario
96e8316633 some cloeanup after last commit 2024-02-28 10:04:22 +00:00
Mario
37878bf0a3 do away with deprecated activity types 2024-02-28 09:18:31 +00:00
Mario
b4f079c4b5 For now we will use standard Create verb for emoji reactions 2024-02-27 10:31:27 +00:00
Harald Eilertsen
18abfb11ef Update Doxygen config for generating online API docs
Enabled implicit brief descriptions (`JAVADOC_AUTOBRIEF`), and markdown
support (`MARKDOWN_SUPPORT`) for doc blocks. This means that we no
longer need to explicitly inclufe a `@brief` tag in the doc block, the
first full sentence will be regarded as the brief documentation if it's
not explicitly given. Also we can use Markdown formatting in the
comments, which is a bit nicer than the native Doxygen tags.

I also disabled the Doxygen_phpvarfilter, but leave it commented out. It
should not be needed anymore unless somebody is using an ancient version
of doxygen. (Don't do that!)

I also changed the heading a bit, removed "The" from "The Hubzilla", and
added a tagline. Feel free to revise to whatever conforms to the project
norms.
2024-02-27 11:08:18 +01:00
Harald Eilertsen
25dbc8a9f6 include/dba: Make Dba driver transaction aware.
This patch introduced database transaction support to the Dba driver via
the DbaTransaction class.

The goal of this is to allow the driver control over the creation and
finalization of database transactions.

Until now code that has needed transaction support has done so directly
by issuing "BEGIN", "ROLLBACK" and "COMMIT" commands to the underlying
database directly.

This has several disadvantages:

  - We do have no control or knowledge of whether any transactions being
	active.

  - Since transactions can not be nested, we run the risk of unrelated
	code trying to create a transaction when one is already active.

  - Code using transactions are not testable, as the test runner wraps
	all tests within a transaction to begin with.

This patch should eliminate all these problems.

A transaction is started by instantiating the DbaTransaction class:

    $my_transaction = new \DbaTransaction();

The transaction will automatically be _rolled back_ if it has not been
committed before the instance is destroyed. (When the variable holding
it goes out of scope, i.e when the containing function returns.)

A transaction is committed like this:

    $my_transaction->commit();

This will immediately commit the changes in the transaction, and the
transaction will be marked as committed, so it will not be attempted to
be rolled back on destruction.

I have chosen to "ignore" the problem of nested transactions by having
the DbaTransaction class _not_ initiate a new transaction if one is
already active. This also makes the rollback and commit actions of the
DbaTransaction class into no-ops.

An alternative would be to simulate nested transactions by using save
points if a transaction is already active. However, I'm unsure about
wether there's any safe way to avoid all potential pitfalls when doing
that.

In any case, nested transactions should preferably be avoided, and
afaict we don't rely on that in any of the existing code. The reason we
need to support it in some way is that it's needed for testing where the
code under test is creating a transaction on it's own. (Since each test
is run within a db transaction to begin with.)

Also, I have taken the liberty to assume a PDO based db driver for this
stuff. I don't think that's going to be a problem, as that's the only
thing supported by the rest of the code in any case.
2024-02-26 15:11:39 +01:00
Mario
c639704f3c more streams compatibility 2024-02-25 21:36:34 +00:00
Mario
3dd7394247 AS2 2024-02-25 19:29:50 +00:00
Mario
b860b730a9 simplify pleroma custom emoji stuff and some cleanup 2024-02-22 10:23:38 +00:00
Mario
17e2877c91 make sure to decode html special chars before sending over the wire and 2024-02-21 10:44:56 +00:00
Mario
b7bc28c333 update test 2024-02-20 15:09:11 +00:00
Mario
fb5a52cbde Merge branch 'bootstrap-new2-v5' into 'dev'
update to Bootstrap 5

See merge request hubzilla/core!2107
2024-02-20 15:08:44 +00:00
Mario
6d125d02d8 introduce get_actor() force flag to omit cache, rework contact refresh, special handling for announce by group, and revert change regarding friendica addressing anomality 2024-02-15 14:27:50 +00:00
Mario
0b18b35f5f require the intl extension for 2024-02-14 21:28:20 +00:00
Mario
9859008271 deal with inReplyTo array + some docu and style 2024-02-14 20:23:02 +00:00
Mario
423c36f67b improved checks in HTTPSig::find_headers() 2024-02-14 18:07:29 +00:00
Rocky
1e0195e439 update to Bootstrap 5 2024-02-14 15:02:31 +01:00
Mario
30271bb32f minor css adjustment 2024-02-14 11:33:31 +00:00
Mario
e2b1670d6c fix round buttons not being round 2024-02-13 21:14:03 +00:00
Mario
2bfdfbe3cc do not feed null to TimeZoneUtil::getTimeZone() 2024-02-13 15:00:41 +00:00
Mario
9a85421a0e we are now using the item uuid for the notification hash if available. since we can have more than one notification per item (e.g. tag and comment) also look for the notification type to make sure we get the right one 2024-02-13 14:05:30 +00:00
Mario
1fa59df6f3 Add test for a paragraph with a mention and some text 2024-02-13 13:01:09 +00:00
Mario
2c93294eea scss: show current color and add some help text 2024-02-13 12:28:11 +00:00
Mario
316829269a bump version 2024-02-13 11:57:55 +00:00
Mario
55236f86e0 move the empty recips check to store(). otherwise it might interfere with zot6 native addressing which is always empty 2024-02-13 11:19:28 +00:00
Mario
060210e930 consider a message arriving to our inbox with no recipients (as seen from friendica) a direct message 2024-02-13 11:00:49 +00:00
Mario
9291622885 fix logic so that direct messages will be allowed in case the send_mail permission is granted even if the send_stream permission is not granted 2024-02-13 10:48:06 +00:00
Mario
07978a061e mb_strlen() will return 2 for some emojis - possibly grapheme_strlen() will be better for this job 2024-02-13 09:22:12 +00:00
Mario
08b2356ed1 add sample scss file 2024-02-12 22:09:07 +00:00
Mario
d17934ed80 scss: more options and some fixes 2024-02-12 22:07:54 +00:00
Mario
94f17f0dae use primary color 2024-02-10 22:22:03 +00:00
Mario
7ccb2a2615 custom sass bootstrap builds for channels and site 2024-02-10 22:04:24 +00:00
Mario
067a66b927 fix some whitespace issues after recent changes 2024-02-09 11:20:46 +00:00
Mario
096fad5e8c another try 2024-02-09 08:02:58 +00:00
Mario
e21e4c7127 let's try this 2024-02-09 07:33:13 +00:00
Mario
5754ea828d move parsing of a tags upà to fix an issue where mentions arriving from masto did not parse correctly, fix typo when restoring temporary linebreaks and remove redundant codeline when converting span tags 2024-02-08 20:22:26 +00:00
Mario
5fbc203367 mark items verified in zot delivery also if either LDSignature or EddsaSignature verified 2024-02-08 19:32:40 +00:00
Mario
08884c44fb whitespace 2024-02-08 19:15:00 +00:00
Mario
bd04ca21a4 Merge branch 'minor-markdown-fixes' into 'dev'
Minor markdown fixes

See merge request hubzilla/core!2098
2024-02-08 19:14:29 +00:00
Harald Eilertsen
19ae8cfdfc Support code blocks with language in markdown and html. 2024-02-08 10:00:12 +01:00
Harald Eilertsen
86e953f495 Fix: Preserve hard linebreaks from markdown and html 2024-02-07 22:34:13 +01:00
Mario
4bc4f5b2a6 update docu and remove redundant pernission check after vonv fetch fixes 2024-02-07 15:56:54 +00:00
Mario
5f2e808497 add uuid to dreport for internal use and and fix issues with conversation fetches 2024-02-07 15:37:20 +00:00
Harald Eilertsen
4f69e02768 Don't concert html nodes with no bbcode equivalent. 2024-02-07 16:02:53 +01:00
Harald Eilertsen
e6ce2885c0 Fix: Keep indentation in html and md code blocks.
Moves the logic for unwrapping broken lines in html (and Markdown) to
the node processing, instead of doing it over the full html content.
This allows us to skip if for code blocks (aka `<code>` elements within
`<pre>` elements).
2024-02-07 15:54:40 +01:00
Harald Eilertsen
ec19ee9d82 Fix convert code blocs from markdown/html to bbcode 2024-02-06 18:39:51 +01:00
Harald Eilertsen
983f063d33 Fix image with alt text for html/md to bbcode 2024-02-06 16:23:39 +01:00
Harald Eilertsen
eb6a143fff Add some tests for markdown to bbcode conversion. 2024-02-06 16:19:30 +01:00
Harald Eilertsen
1881029040 Clean up markdowntest and fix bb to markdown test. 2024-02-06 11:43:32 +01:00
Mario
209651705d fix custom emoji reactions arriving from pleroma 2024-02-04 19:50:31 +00:00
Mario
fab3c92a7c streams collection branch compatibility 2024-02-02 20:23:06 +00:00
Mario
8ad7376865 more fix conv_list template 2024-02-01 17:12:43 +00:00
Mario
c41831aff9 fix conv_list template 2024-02-01 17:05:00 +00:00
Mario
8515aa6966 fix issues related to b64mid to uuid conversion 2024-02-01 16:29:23 +00:00
Mario
691de5bf2e Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-02-01 16:00:36 +00:00
Mario
2e155892fe testing JcsEddsa2022 sigs 2024-02-01 16:00:17 +00:00
Mario
6680c2faf3 Merge branch 'add-ci-job-for-mariadb' into 'dev'
CI: Add job for MariaDB 10.6

See merge request hubzilla/core!2097
2024-02-01 14:22:48 +00:00
Mario
decc8f2162 strip a possible fragment 2024-02-01 14:14:53 +00:00
Mario
7d7a0c160f bump version 2024-02-01 13:27:09 +00:00
Mario
e89563eb4c fix edgecase for notices and make mod hq backwards compatible 2024-02-01 13:25:40 +00:00
Mario
dd204ec34f start using uuid for internal reference instead of base64 encoded mid 2024-02-01 11:42:55 +00:00
Mario
b3a5dd8aa8 store seen mids in session instead of cache and increase sess_data column to medium text 2024-01-31 13:29:56 +00:00
Mario
26ee56f39c remove logging 2024-01-29 10:39:15 +00:00
Mario
300b0e27bd bump version 2024-01-29 10:35:48 +00:00
Mario
29489f62cf introduce Activity::init_background_fetch() and refactor zotconvo to implement it 2024-01-29 10:33:13 +00:00
Mario
09465619e5 enable object cash by default, introduce system.cache_expire_days and default to 7, default system.default_expire_days to 30 and system.active_expire_days to 7 2024-01-28 17:03:05 +00:00
Mario
390af7722d fix last commit 2024-01-28 15:03:40 +00:00
Mario
e18157f818 make sure we return an array if there is no cache entry 2024-01-28 11:35:15 +00:00
Mario
5435d2881c Merge branch 'dev' into 'dev'
Added Circle Person Avatar

See merge request hubzilla/core!2096
2024-01-27 20:26:29 +00:00
Mario
2e8f3d1869 Merge branch 'upgrade-ci-to-mysql-8.0' into 'dev'
CI: Upgrade to use MySQL version 8.0

See merge request hubzilla/core!2093
2024-01-27 20:21:13 +00:00
Mario
3ad1cab006 Merge branch 'doc-updates' into 'dev'
Doc updates

See merge request hubzilla/core!2092
2024-01-27 20:20:18 +00:00
Mario
b806a3ccc2 use std functions 2024-01-27 20:18:28 +00:00
Mario
5e780ba089 implement short time object cache to reduce network calls and some cleanup 2024-01-27 16:36:26 +00:00
Mario
c0a7dfe2f6 refactor fetch_and_store_parents() and inroduce the fetchparents daemon 2024-01-25 10:13:10 +00:00
Mario
fe50d78a0f missing hook 2024-01-24 19:34:41 +00:00
Mario
e513950cb5 restructure Libzot::process_delivery() 2024-01-24 16:44:42 +00:00
Mario Vavti
adc6390a22 bump version 2024-01-24 16:41:03 +01:00
Mario Vavti
9449e8bd61 fix issue where if an item is created and deleted again before the notifier has completed the queueworker will dismiss the delete because it looks like a duplicate entry 2024-01-24 16:40:05 +01:00
Mario
f13af0f60b process source xchan in xchan_query() 2024-01-23 08:46:18 +00:00
Harald Eilertsen
acdb773f89 CI: Add job for MariaDB 10.6
Reuse job definition for mysql job, and alias the mariadb service to
mysql so that the job will find it.
2024-01-22 12:44:36 +01:00
Mario
651a288148 set item_uplink to 0 just to be sure (this should not be necessary) 2024-01-22 09:17:55 +00:00
Mario
b0664f7349 store the original announce actor (the one that pushed the item into our stream first) in source_xchan instead of owner_xchan. this way we will preserve the real owner for the thread and not have conflicts when dealing with deletes of comments or likes 2024-01-22 09:09:41 +00:00
Scott M. Stolz
51586037e1 Added Circle Person Avatar
Added an additional avatar to choose from.
2024-01-21 16:11:35 -06:00
Harald Eilertsen
f573c1772a CI: Slight refactoring. 2024-01-21 22:51:42 +01:00
Harald Eilertsen
f08e91e19d CI: Upgrade to use MySQL version 8.0
This is the oldest version we support now.
2024-01-21 17:50:06 +01:00
Harald Eilertsen
8cd9fff26a Add some developer doc for check_account_password hook 2024-01-21 17:43:35 +01:00
Harald Eilertsen
d489a2854e Update admin guide with min supported db versions 2024-01-21 17:42:42 +01:00
Mario Vavti
9cfd1c2318 missing include 2024-01-21 09:52:13 +01:00
Mario
2dd0677d23 Merge branch 'dont-include-db-updates-in-test-coverage' into 'dev'
Don't include db updates in test coverage.

See merge request hubzilla/core!2090
2024-01-19 20:36:04 +00:00
Mario
00d403e729 Merge branch 'improve-validate-email' into 'dev'
Improve validate_email function

See merge request hubzilla/core!2088
2024-01-19 20:35:43 +00:00
Mario
d83e2daf36 Merge branch 'fix-postgres-ci' into 'dev'
tests: Remove id from db fixtures.

See merge request hubzilla/core!2087
2024-01-19 20:33:36 +00:00
Mario
8fe6aede03 bump version 2024-01-19 20:11:35 +00:00
Mario
fa4ab45692 native repeats continued 2024-01-19 20:10:50 +00:00
Mario Vavti
f57fbaa5dd version 8.8.7 2024-01-19 11:07:23 +01:00
Mario Vavti
aba8002170 Fix regression in Activity::actor_store()
(cherry picked from commit 9cc85adf47)
2024-01-19 10:03:58 +00:00
Mario Vavti
9cc85adf47 Fix regression in Activity::actor_store() 2024-01-19 11:02:13 +01:00
Harald Eilertsen
01ed001041 Don't include db updates in test coverage.
We're not likely to add tests for these in any case.
2024-01-16 10:13:24 +01:00
Harald Eilertsen
403539919a Improve the validate_email function
The validate_email function relied on doing an actual domain lookup (on
supported platforms) to validate the domain of the email address. This
does not work too well in testing environments where we may not want to
spam the DNS system, if it at all is available.

Apart from the the function did very little to actually verify that it
was a valid email address.

This patch tries to change that by usng a somewhat stricted regex based
validation. While this may not be perfect, it should be good enough in
the vast majority of cases. For platforms where no validation was
performed with the old version, it will at least be an improvement.

Also, it allows testing without having an external network connection.

Also clarify the doc comment, that it does not actually try to resolve
the email address, just the domain.
2024-01-15 19:52:31 +01:00
Harald Eilertsen
52ea2fa33e Update CI run to archive dbfail.out if test run fails 2024-01-15 19:32:19 +01:00
Harald Eilertsen
ecd4754f6d tests: Enable debug logging during tests
The debug log will be stored in the test/results directory, and archived
as part of the artifacts of the CI run. This should make it easier to
get some debugging info out from the CI runs if they fail.
2024-01-15 19:25:09 +01:00
Harald Eilertsen
f71033b30d tests: Remove id from db fixtures.
It seems that PostgreSQL will not update the autoincrement index of the
table when inserting rows with an id set. Later inserts without an id
set will then fail, because they get assigned an id that already exists.

MySQL seems to handle this just fine.

Why the id column was added in the first place, one may wonder, but
that's how it were.

In any case, this broke the PostgreSQL tests in the gitlab CI
environment. (While it mysteriously worked in my local ddev
environment.) Anyways, the id column is not needed, and things work
better without them.
2024-01-15 19:11:25 +01:00
Mario
885068834f fix more php deprecations 2024-01-14 19:58:36 +00:00
Mario
c4c4ab2f3d fix regression in commit b05b7561 2024-01-14 19:52:05 +00:00
Mario
aec3247952 fix more php deprecations 2024-01-14 19:40:59 +00:00
Mario
b05b756148 Handling HTML entities via mbstring is deprecated 2024-01-14 17:23:57 +00:00
Mario
03819abb22 remove acct from webfinger 2024-01-14 17:23:19 +00:00
Mario
d074e2aba0 fix more php deprecations 2024-01-14 17:22:33 +00:00
Mario
2bbecfe8dd only attempt fetch if zotfinger actually returned something 2024-01-14 10:11:20 +00:00
Mario
e078e13325 make sure we are dealing with an array 2024-01-14 09:40:18 +00:00
Mario
9d3b852d38 fix wrong array key 2024-01-14 08:10:27 +00:00
Mario
fadb0a5bf2 check for assertionMethod 2024-01-13 20:45:32 +00:00
Mario
fa7aa6cedb start checking integrity proofs, remove signature prior to verify, iterate trough the array to find the desired ekey in actor_store() 2024-01-13 20:38:34 +00:00
Mario
6df98f2fad private -> public 2024-01-13 19:10:44 +00:00
Mario
c597017402 fix some deprecation warnings 2024-01-13 17:38:31 +00:00
Mario
9cb95f6065 store epubkey in actor_store 2024-01-13 16:19:53 +00:00
Mario
477b1535a2 start storing epubkeys in libzot 2024-01-13 15:28:20 +00:00
Mario
1d652cfcbd expose epubkey in zotinfo 2024-01-13 15:09:39 +00:00
Mario
28b604c7c7 typo 2024-01-13 13:46:40 +00:00
Mario
8c11be07cd Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-01-13 08:51:19 +00:00
Mario
e8dd2c28ff make our jsonld parser happy 2024-01-13 08:50:57 +00:00
Mario Vavti
0bdffc4a2d make our jsonld parser happy 2024-01-13 08:49:14 +01:00
Mario
94b1fe4a8b Merge branch 'cherry-pick-96ae46c5' into 'dev'
Update lostpass_eml.tpl

See merge request hubzilla/core!2086
2024-01-11 17:15:38 +00:00
Mario
11ed445319 Merge branch 'cherry-pick-ddfa613e' into 'dev'
Update Spanish strings

See merge request hubzilla/core!2085
2024-01-11 17:15:21 +00:00
Mario Vavti
400dfb4e6b version 8.8.6 2024-01-11 17:57:51 +01:00
Mario
6b951734ce changelog
(cherry picked from commit 000fcfd1ac)
2024-01-11 16:56:13 +00:00
Mario
000fcfd1ac changelog 2024-01-11 16:55:44 +00:00
Mario
051e2ed6cd provide some more jsonld builtins
(cherry picked from commit aac406a245)
2024-01-11 16:40:16 +00:00
Mario
aac406a245 provide some more jsonld builtins 2024-01-11 16:27:57 +00:00
Mario Vavti
ef2952b5fd libsync: dev branch compatibility 2024-01-11 17:00:47 +01:00
Mario
ffdf54b097 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-01-10 13:34:23 +00:00
Mario
58593d7da6 prepare outbound fep-8b32 (object integrity) but do not enable yet since the additional context seems to break ldsig for some reason, introduce Activity::build_packet() and Activity::ap_context() to reduce code duplication, implement fep-2c59 (webfinger) and some cleanup 2024-01-10 13:33:57 +00:00
mjfriaza:4GF~eYj,-iAv
3d13f36ce2 Update lostpass_eml.tpl
(cherry picked from commit 96ae46c5a4aa614b9aed7b640d69e8cd8210595f)
2024-01-09 12:52:48 +00:00
mjfriaza:4GF~eYj,-iAv
8c843ec6d0 Update Spanish strings
(cherry picked from commit ddfa613e828e8f0a569a2d938d3839f5608bc9c3)
2024-01-09 12:49:55 +00:00
Mario
232c7f5301 Merge branch 'tests/includes/account' into 'dev'
Some test cleanup and tests for check_account_email

See merge request hubzilla/core!2083
2024-01-09 08:05:28 +00:00
Harald Eilertsen
16cd8caef3 tests: Add tests for check_account_email 2024-01-08 14:09:13 +01:00
Harald Eilertsen
43dabee53d tests: Set app config in a known state for each test 2024-01-08 14:09:13 +01:00
Harald Eilertsen
f016760851 tests: Add config fixtures.
Adds fixtures for the config table:
- Disables dns checking globally for the tests.
- Adds a few disallowed email domains and addresses.
2024-01-08 14:09:13 +01:00
Harald Eilertsen
99b5166f21 tests: Clean up unused debug stuff from UnitTestCase 2024-01-08 14:01:02 +01:00
Mario
4aa29db7aa reflect new fields in low level functions 2024-01-07 21:27:12 +00:00
Mario
f5b8b18c8e Merge branch 'tests/remove-behat' into 'dev'
Remove unused acceptance tests and dependencies

See merge request hubzilla/core!2082
2024-01-07 21:00:40 +00:00
Mario
6e5566f9c8 bump version 2024-01-07 20:38:40 +00:00
Mario
ca216ae819 set default value for postgres only 2024-01-07 20:34:47 +00:00
Mario Vavti
4713241444 set a default value 2024-01-07 21:18:20 +01:00
Mario
4917170a0d remove logging 2024-01-07 20:00:29 +00:00
Mario
87775ae37a ekey and xchan_updated updates 2024-01-07 19:58:09 +00:00
Harald Eilertsen
eaa244a2a3 CI: Install pecl extensions after system packages.
The php yaml extension requires libyaml, which has to be installed
first.
2024-01-07 20:39:06 +01:00
Harald Eilertsen
db91d66d1a CI: Install yaml extension from PECL. 2024-01-07 20:35:08 +01:00
Harald Eilertsen
4d64481564 Remove unused acceptance test stuff from source tree. 2024-01-07 20:26:14 +01:00
Harald Eilertsen
0a31fc176c Remove behat as dev dependency.
As the Symphony\Yaml stuff disappeared with behat, we need another way
to load read the yaml files with database fixtures for the integration
tests.

As the php yaml extension is not distributed with PHP by default, this
creates it as another dev dependency!
2024-01-07 20:24:52 +01:00
Harald Eilertsen
659a8c967c Exclude dev dependencies from version control.
This will ignore dependencies only installed as part of the dev setup.
2024-01-07 19:39:49 +01:00
Harald Eilertsen
626887a792 Exclude phpunit cache from version control 2024-01-07 19:25:01 +01:00
Mario
256b66de41 Revert "DB update 1260 - REQUIRES SODIUM PHP EXTENSION!!!"
This reverts commit 5ee4f37b8d
2024-01-07 15:50:50 +00:00
Mario
5ee4f37b8d DB update 1260 - REQUIRES SODIUM PHP EXTENSION!!! 2024-01-07 15:34:25 +00:00
Mario
3dc122db84 fix regression collapsing non conv item content 2024-01-07 10:43:43 +00:00
Mario
99c5a4e2f8 we do not use named params yet 2024-01-06 16:44:17 +00:00
Mario
f922a92ffa install bcmath 2024-01-06 16:37:11 +00:00
Mario
a36de8ba1a Merge branch 'tests/fix-db-and-ci-integration' into 'dev'
tests: Integrate the DB in "unit" tests.

See merge request hubzilla/core!2081
2024-01-06 16:34:39 +00:00
Harald Eilertsen
e3d30763da tests: Integrate the DB in "unit" tests. 2024-01-06 16:34:38 +00:00
Mario
c73518d8ec dump composer autoload 2024-01-06 16:31:42 +00:00
Mario
ed0d2fed66 require bcmath or gmp extension 2024-01-06 16:23:26 +00:00
Mario
960bcb6b53 port test for JcsEddsa2022 from streams 2024-01-06 16:12:25 +00:00
Mario
6252340804 add Bookmark and Category to ap schema and bump ap schema version 2024-01-06 10:03:44 +00:00
Mario
517d67b2e0 add check for sodium on setup 2024-01-05 20:16:13 +00:00
Mario
e95b7ca3a0 require ext-sodium, dump composer autoload and a minor js fix 2024-01-05 19:30:37 +00:00
Mario
c771d7c31a Ãdisplay selected mid in an open state - issue #1425 2024-01-05 12:53:00 +00:00
Mario
ce0e8d7497 update apache rewite rule to fix issue with recent apache versions - issue #1822 2024-01-05 11:06:08 +00:00
Mario
852678e238 port multibase and jcsedssa2022 libs from streams 2024-01-03 19:20:28 +00:00
Mario
16e6eec3fb composer add mmccook/php-json-canonicalization-scheme 2024-01-03 11:09:22 +00:00
Mario
afe8552be6 comÃposer add tephenhill/base58 2024-01-03 11:07:03 +00:00
Mario
cd0e50da24 update symfony/polyfill-php81 2024-01-03 11:00:20 +00:00
Mario
85001c034b update sabre/vobject 2024-01-03 10:58:31 +00:00
Mario
a56f6576e2 update ramsey/uuid 2024-01-03 10:57:15 +00:00
Mario
d3e5d05026 update ezyang/htmlpurifier 2024-01-03 10:56:03 +00:00
Mario
322b619a71 update sabre/dav 2024-01-03 10:53:37 +00:00
Mario
dff906ca69 bump version 2024-01-02 20:50:50 +00:00
Mario
515d1d5e63 postgres does not like binaries to be string while mariadb/mysql does not seem to care - let's see 2024-01-02 20:49:57 +00:00
Mario
bb6ed22594 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-01-01 20:35:28 +00:00
Mario Vavti
d655e1d765 version 8.8.5 2024-01-01 21:30:45 +01:00
Mario Vavti
db70ed006d Merge branch 'dev' 2024-01-01 21:29:53 +01:00
Mario Vavti
ce1dd5c632 changelog 2024-01-01 21:29:15 +01:00
Mario Vavti
9e2a253dda Merge branch 'dev' 2024-01-01 21:21:04 +01:00
Mario
95c645865d Merge branch 'doc-fixes' into 'dev'
docs: Update admin guide requirements

See merge request hubzilla/core!2080
2024-01-01 20:17:52 +00:00
Mario
ceb510bbf5 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2024-01-01 20:04:44 +00:00
Mario
2590e3c99b reveal repeat 2024-01-01 20:04:24 +00:00
Mario Vavti
f2f9cfaf28 Work around possible loop and use Lib/Config in init 2024-01-01 21:01:47 +01:00
Mario Vavti
62db8c3969 fix php errors and deprecation warnings 2023-12-31 09:55:27 +01:00
Mario Vavti
ae3db366e5 deprecate simplepie idna_convert 2023-12-31 09:54:54 +01:00
Harald Eilertsen
57570c144a doc/admin-guide: Update min php version and reqd extensions. 2023-12-26 15:34:50 +01:00
Mario
c3a235242e do not double process quoted strings 2023-12-21 10:19:26 +00:00
Mario
b629eb5657 fix merge conflict 2023-12-20 12:32:15 +00:00
Mario
2e674cd0b3 version 8.8.4 2023-12-20 12:26:28 +00:00
Mario
3330e9a19a Merge branch 'dev' 2023-12-20 12:25:43 +00:00
Mario
c5f6208396 changelog 2023-12-20 12:25:27 +00:00
Mario
c0d93bbcf4 Merge branch 'dev' 2023-12-20 12:20:04 +00:00
Mario
db941e7007 changelog 2023-12-20 12:17:35 +00:00
Mario
4761857157 Revert "changelog"
This reverts commit 3aefe23184.
2023-12-20 12:15:42 +00:00
Mario
3aefe23184 changelog 2023-12-20 12:15:24 +00:00
Mario
6f852814fd move App::$install check to Config::Load() as suggested by Harald 2023-12-20 11:58:33 +01:00
Mario
b15e521b0e Merge branch 'fix-config-deserialization' into 'dev'
Fix deserialization of config values broken by 69266cd6.

See merge request hubzilla/core!2077
2023-12-20 10:27:56 +00:00
Mario
63c401e6d6 Merge branch 'extend-siteinfo' into 'dev'
Add active addons and blocked sites to siteinfo (html)

See merge request hubzilla/core!2079
2023-12-20 10:16:44 +00:00
Harald Eilertsen
e59750e8de Add active addons and blocked sites to siteinfo (html)
This adds information about addons activated on the hub, as well as
which other sites this hub won't federate with in the HTML version of
siteinfo.

Based on suggestions by @rockyiii@huby.infozoo.de.
2023-12-18 15:05:23 +01:00
Harald Eilertsen
9c184ddfd0 Fix deserialization of config values broken by 69266cd6.
This should fix issue #1828.

This patch makes it explicit that we store arrays in the config as json
encoded arrays, while we allow both json encoded and PHP serialized
arrays to be deserialized correctly. Unless it's a brand new install,
the existing data in the database will be PHP serialized.

I've also added a hardening measure in case we fall back to PHP
unserialize, making sure we're not vulnerable to a PHP Object Injection
attack. This means that deserializing arrays containing PHP objects will
no longer work, but afaict we never do that anyways, so I don't think
that should break anything.
2023-12-17 19:30:05 +01:00
Mario
9df6e821d8 use reqiure_once() - second part of issue #1827 2023-12-17 16:47:19 +00:00
Mario
9551dc5ecd fix loop as described in issue #1827 2023-12-17 16:36:13 +00:00
Mario
d372daff60 Revert "check return from Config::Load() and retry on failure plus cleanup"
This reverts commit 69266cd6c6
2023-12-17 11:16:58 +00:00
Mario
f742e6e394 Merge branch 'dev' 2023-12-17 08:53:32 +00:00
Mario
414b2b0e4c changelog 2023-12-17 08:53:14 +00:00
Mario
603c5692ae Merge branch 'dev' 2023-12-17 08:50:39 +00:00
Mario
b35e994d1b Merge branch 'translations-nb_no' into 'dev'
More translations for Norwegian Bokmål (nb_NO)

See merge request hubzilla/core!2075
2023-12-17 08:50:13 +00:00
Mario
abe2ab229a version 8.8.3 2023-12-17 08:43:08 +00:00
Mario
5ad9939bcf Merge branch 'dev' 2023-12-17 08:41:48 +00:00
Mario
ce451128ba changelog 2023-12-17 08:41:21 +00:00
Mario
70470016cc Merge branch 'dev' 2023-12-17 08:35:33 +00:00
Harald Eilertsen
2122ea77e1 More translations for Norwegian Bokmål (nb_NO) 2023-12-16 14:57:01 +01:00
Mario Vavti
69266cd6c6 check return from Config::Load() and retry on failure plus cleanup 2023-12-14 12:32:34 +01:00
Mario Vavti
062d61567e return if we could not fetch the author 2023-12-14 12:06:50 +01:00
Mario Vavti
d6120fc908 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-12-14 12:06:21 +01:00
Mario
91f8e7a07b typo 2023-12-13 14:34:34 +00:00
Mario Vavti
f57d89245c add the app terms before syncing - otherwise the terms will be reset at the other end 2023-12-08 21:44:32 +01:00
Mario Vavti
c307a71f53 Merge branch 'dev' 2023-12-08 18:08:03 +01:00
Mario Vavti
1e4e59bb57 if it is not an array do not attempt count() 2023-12-08 18:02:54 +01:00
Mario
f62d16d274 Merge branch 'dev' 2023-12-06 11:27:54 +00:00
Mario
f175712d4b typo 2023-12-06 11:27:35 +00:00
Mario
5f942d78e6 Merge branch 'dev' 2023-12-06 11:23:21 +00:00
Mario
538c8885ad changelog 2023-12-06 11:23:02 +00:00
Mario
c8158c3d62 vesrion 8.8.2 2023-12-06 11:14:00 +00:00
Mario
1f4762060f Merge branch 'dev' 2023-12-06 11:12:25 +00:00
Mario
81c3682781 more issue #1820 2023-12-06 09:47:13 +00:00
Mario
2e6e1fdd55 css fixes 2023-12-04 09:28:16 +00:00
Mario
1a09cd560b require acl_selectors.php - fix issue #1820 2023-11-30 08:02:33 +00:00
Mario
8c9d2bc6f6 Merge branch 'dev' 2023-11-27 08:48:47 +00:00
Mario
78ad5ca713 changelog 2023-11-27 08:48:23 +00:00
Mario
43c2e71b25 Merge branch 'dev' 2023-11-27 08:45:19 +00:00
Mario
5b9f32fade Merge branch 'dev' into 'dev'
Update doubleleft.css and doubleright.css according to v.8.8 default.css

See merge request hubzilla/core!2074
2023-11-27 08:44:25 +00:00
Mario
76a1a6da34 version 8.8.1 2023-11-27 08:42:09 +00:00
zlaxy
a2b0abc90d Update doubleleft.css and doubleright.css according to v.8.8 default.css 2023-11-27 10:50:31 +03:00
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
Mario
89285f1408 Merge branch '8.2RC' 2023-03-19 13:55:18 +00:00
Mario
17c0bb2069 version 8.2 2023-03-19 13:54:15 +00:00
Mario
192736f6d7 Merge branch 'dev' into 8.2RC 2023-03-19 13:53:12 +00:00
Mario
ae928b9aff changelog 2023-03-19 13:52:43 +00:00
Mario
4eee8ce770 Merge branch 'dev' into 8.2RC 2023-03-19 13:50:39 +00:00
Mario
723eb6597a simplify 2023-03-19 13:29:35 +00:00
Mario
3dcfdba74b simplify 2023-03-19 13:28:43 +00:00
Mario
5428053663 Merge branch 'dev' into 8.2RC 2023-03-19 09:43:34 +00:00
Mario
d0b41d0b07 more changelog 2023-03-19 09:41:17 +00:00
Mario
a82d861d2c update changelog 2023-03-19 09:25:56 +00:00
Mario
1e184b781b Merge branch 'dev' into 8.2RC 2023-03-19 08:22:29 +00:00
Mario
54b684fdb8 css fixes 2023-03-19 08:22:08 +00:00
Mario
c1ddb89990 Merge branch 'dev' into 8.2RC 2023-03-18 15:47:09 +00:00
Mario
2f5fa4df75 add the download attribute to prevent onbeforeunload 2023-03-18 15:46:30 +00:00
Mario
20735083b3 update bb_parse_b64_crypt() 2023-03-18 14:52:25 +00:00
Mario
7ac7cb129f Merge branch 'dev' into 8.2RC 2023-03-17 09:44:17 +00:00
Mario
f8b2f738bb remove redundant untranslated htconfig templates and add the db_skip_locked_supported config option 2023-03-17 09:30:17 +00:00
Mario
11b9e546a9 Merge branch 'dev' into 8.2RC 2023-03-14 10:43:03 +00:00
Mario
7e4721e4c7 work around friendica img attachment has different href than body which results in duplicate images 2023-03-14 10:35:01 +00:00
Mario
3a3fd38e3a Merge branch 'dev' into 8.2RC 2023-03-12 22:04:37 +00:00
Mario
63a8611579 fix issue #1728 2023-03-12 22:03:47 +00:00
Mario
38a1b79174 fix max_oembed_size check if content length header is an array (e.g. after a redirect with code 301) - fix issue #1727 2023-03-12 20:59:36 +00:00
Mario
0a679e503e make sure to only transform channel wall posts for group actors
(cherry picked from commit 95cbcf30d7)
2023-03-12 19:56:34 +01:00
Mario
e7c529f2c3 Merge branch 'dev' into 8.2RC 2023-03-12 18:44:28 +00:00
Mario
95cbcf30d7 make sure to only transform channel wall posts for group actors 2023-03-12 18:43:50 +00:00
Mario
dfc70021e3 fix version after merge 2023-03-12 09:38:31 +00:00
Mario
9daecca0ad make an format exception for repeated forum posts 2023-03-12 09:34:35 +00:00
Mario
c9d8a4dc1d bump dev version 2023-03-11 20:43:21 +00:00
Mario
5fada6a497 more strings and provide mfa feedback via jgrowl 2023-03-11 20:40:32 +00:00
Mario
ac9c33fb3b check form security token and require password to enable/diable mfa 2023-03-11 20:24:56 +00:00
Mario
641b1c2e1b fix php error 2023-03-11 19:38:37 +00:00
Mario
f031707563 strings and version 2023-03-11 19:37:34 +00:00
Mario
7f0518f693 merge es translations as per manuel 2023-03-11 19:28:17 +00:00
Mario
634d2f02b5 translateable strings 2023-03-11 19:25:27 +00:00
Mario
d7aee292d3 mark items as fetched in other places 2023-03-11 14:47:10 +00:00
Mario
1987517836 only set owner to observer if the item is not fetched otherwise the comment author could end up as owner 2023-03-09 18:31:43 +00:00
Mario
203d9d651f mfa strings update 2023-03-09 15:48:03 +00:00
Mario
8af5788fc1 more mfa cleanup, set the value in session if mfa is enabled and only allow enabling mfa after a test passed 2023-03-08 17:29:56 +00:00
Mario
3de81877c6 more mfa cleanup 2023-03-08 13:15:33 +00:00
Mario
2665b34962 whitespace 2023-03-08 10:21:05 +00:00
Mario
2ffef2be8f minor cleanup 2023-03-08 10:18:32 +00:00
Mario
c2e5610455 tests 2023-03-08 10:11:59 +00:00
Mario
234bb64250 port totp mfa from streams with some adjustions 2023-03-08 10:04:29 +00:00
Mario
d43a56614c position should be fixed 2023-03-04 21:33:50 +00:00
Mario
9f10e7e356 simplify pageloader animation 2023-03-04 17:03:37 +00:00
Mario
dc6075aa3f do not use zrl tag for non zot profiles and remove redundant foreach which was a leftover from zot to zot6 transition days 2023-03-03 19:33:39 +00:00
Mario
972d6917ac add fixme 2023-03-03 14:59:48 +00:00
Mario
ec3ba87f3a Revert "some work on bringing bang tags back for forums"
This reverts commit da034045cc.
2023-03-03 08:49:18 +00:00
Mario
da034045cc some work on bringing bang tags back for forums 2023-03-02 21:15:19 +00:00
Mario
65f001b4b7 provide a fake progress bar for pwa standalone mode 2023-03-02 16:45:10 +00:00
Mario
d81473487f minor cleanup and docu 2023-03-02 12:39:21 +00:00
Mario
06a8d5a4fa bump version 2023-03-02 11:48:52 +00:00
Mario
3653a86ad3 message filter entries are stored encoded - make sure to decode the word before we use it 2023-03-02 11:00:03 +00:00
Mario
c8d913fba7 wrong variable 2023-03-02 10:24:18 +00:00
Mario
b70acd0079 wrong variable 2023-03-02 10:20:43 +00:00
Mario
f167648115 improve mod hq to save some db lookups 2023-03-02 10:14:49 +00:00
Mario
b457c66bf9 do not include deleted hublocs when looking for author 2023-03-02 10:13:54 +00:00
Mario
ca0bd3ed32 fix some php warnings 2023-02-28 09:29:39 +00:00
Mario
7dacc7c268 Revert "fix second part of issue #1731"
This reverts commit 0db2e6b62c.
2023-02-27 20:38:42 +00:00
Mario
0db2e6b62c fix second part of issue #1731 2023-02-27 20:31:16 +00:00
Mario
e412bdbdbe bump version 2023-02-27 09:07:26 +00:00
Mario
f032bcc5f2 Default owner_xchan to $observer (sender) in Activity::store() - this is because in case where an announce holds a relayed activity we drop the announce and process the relayed activity only. In that case actor.id as set in Activity::decode_note() will not be the correct owner. In other cases actor.id and sender should be identical. 2023-02-27 08:42:13 +00:00
Mario
9ab9ac0e2e possible fix for issue #1731 2023-02-27 08:22:35 +00:00
Mario
fd3adf4d11 slightly improve contact search 2023-02-24 21:35:22 +00:00
Mario
c42911bd8d css fixes 2023-02-23 16:19:02 +00:00
Mario
828087ee8c fix syntax for get_compund_property() 2023-02-23 14:54:04 +00:00
Mario
efcda1d37d port some functions from streams 2023-02-23 09:51:37 +00:00
Mario
656400b418 look for owner instead of author - this way we will also catch the via posts 2023-02-22 17:07:53 +00:00
Mario
ca7bd49964 Activity: do not force new thread if the announce is from a group actor 2023-02-22 11:20:32 +00:00
Mario
3527137264 Activity: set xchan_pubforum if we deal with a group actor 2023-02-22 10:47:11 +00:00
Mario
e045a36559 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-02-17 10:18:30 +00:00
Mario
ee8fc701a6 do not try to oembed in notes 2023-02-17 10:18:01 +00:00
Mario Vavti
777fdeb462 realy make sure we will deduplicate even if there is a bogus second primary entry 2023-02-16 16:56:57 +01:00
Mario Vavti
1078b774ae make sure we will deduplicate even if there is a bogus second primary entry 2023-02-16 16:52:29 +01:00
Mario
62a363debc queue fixes 2023-02-16 14:17:05 +00:00
Mario Vavti
7839b931f1 make sure we provide a created timestamp for likes and remove the workaround which returned the wrong date format 2023-02-16 13:12:22 +01:00
Mario
cbf8c4bdb2 more queue updates from streams and remove a hz_syslog 2023-02-16 11:16:44 +00:00
Mario
321cd9f2e0 more restructure for better responsive behaviour 2023-02-15 18:06:16 +00:00
Mario
09a60774d7 we can sign messages which are not from the primary location 2023-02-15 13:33:23 +00:00
Mario
1ca988b177 revisit author_id and fix issue with pinned content 2023-02-15 09:41:48 +00:00
Mario
07fd8cf6cd restructure wall-item-head 2023-02-15 08:51:23 +00:00
Mario
e7fb56447a bump version 2023-02-14 07:35:41 +00:00
Mario
de3e83f0a2 fix mod cal after fullcalendar update 2023-02-14 07:33:05 +00:00
Mario
6c78f7b769 css fixes 2023-02-12 15:05:06 +00:00
Mario
2c459fefce remove deprecated functions 2023-02-12 14:13:59 +00:00
Mario
a1eb39872b implement hq widget author image and notifications updates 2023-02-12 10:43:31 +00:00
Mario
724b8cc6a5 port queue improvements from streams 2023-02-12 10:41:23 +00:00
Mario Vavti
2bfd18e6cd css fixes 2023-02-10 21:08:49 +01:00
Mario
20658f3b4a do not blur 2023-02-09 12:46:23 +00:00
Mario
c945698eb4 work around wierd textcomplete behaviour 2023-02-09 12:37:08 +00:00
Mario
5f89bd75a4 bump version 2023-02-09 01:53:46 +00:00
Mario
09c9b47265 fix more hubloc confusion, implement hq widget author filter and some autocomplete fixes 2023-02-09 01:52:48 +00:00
Mario
ea2b653b9b queueworker: do not wait for locked rows, use skip locked if configured via system.db_skip_locked_supported 2023-02-08 11:03:29 +00:00
Mario
9c3660e2f6 remove superfluous semicolon 2023-02-01 10:02:35 +00:00
Mario
4bcacf858b do not deduplicate notifications because the dupes could be valid and var -> let 2023-01-29 10:06:58 +00:00
Mario
7faa3359f0 fix undefined varable warning 2023-01-28 20:19:51 +00:00
Mario
71f1814477 remove redundant argument 2023-01-28 20:04:18 +00:00
Mario
a3913c5ca4 fix ics import 2023-01-28 16:57:32 +00:00
Mario
ae1cc65b23 do not use transparency for navbar togglers in dark mode 2023-01-28 15:00:11 +00:00
Mario
9a16bf65bd update simplepie 2023-01-27 07:28:21 +00:00
Mario
c3d3dc9d92 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-01-27 07:26:35 +00:00
Mario
e54eb21b71 update smarty 2023-01-27 07:24:50 +00:00
Harald Eilertsen
0140f9fe56 translations: Misc updates for nb_NO.
(cherry picked from commit ec6832687b)
2023-01-27 08:00:26 +01:00
Harald Eilertsen
03243df16a translations: Fix timeago for nb_NO.
(cherry picked from commit 9065a90ac0)
2023-01-27 08:00:07 +01:00
Mario
28dc8443a8 Merge branch 'translations/update-nb-no' into 'dev'
Translations/update nb no

See merge request hubzilla/core!2034
2023-01-27 06:58:45 +00:00
Harald Eilertsen
ec6832687b translations: Misc updates for nb_NO. 2023-01-26 20:07:59 +01:00
Harald Eilertsen
9065a90ac0 translations: Fix timeago for nb_NO. 2023-01-26 20:07:02 +01:00
Mario
94b26e1e66 redbasic: fix regression 2023-01-26 18:35:49 +00:00
Mario
a2fc2e776a bump version 2023-01-26 18:29:21 +00:00
Mario
79b40179b4 redbasic: implement setting for always light navbar icons and some minor fixes 2023-01-26 18:28:40 +00:00
Mario
60c968222f bump version 2023-01-26 10:26:55 +00:00
Mario
e99dc2193f remove unsused variables 2023-01-26 10:23:33 +00:00
Mario
cf1838f76e minor cleanup and prevent duplicate recipients in some places 2023-01-26 10:10:06 +00:00
Mario
0db5016666 remove redundant code 2023-01-26 09:15:46 +00:00
Mario
c4b37ba462 theme fixes 2023-01-26 07:22:21 +00:00
Mario
c3b908dcfc : fixes 2023-01-25 16:35:18 +00:00
Mario
23f93044c1 update forkawesome lib 2023-01-25 15:22:15 +00:00
Mario
32dcc28414 calendar: fixes 2023-01-25 14:05:20 +00:00
Mario
ddae3eaf84 calendar: remove deprecated options 2023-01-25 13:39:50 +00:00
Mario
a9ae17036d update fullcalendar 2023-01-25 13:09:00 +00:00
Mario
08e925758e update fullcalendar library 2023-01-25 13:08:05 +00:00
Mario
213c8a6eec according to spec this should be id instead of href 2023-01-25 13:06:50 +00:00
Mario
ca4ad836a3 revert theme color 2023-01-25 11:00:01 +00:00
Mario
56361fa2fc theme fixes 2023-01-25 10:59:17 +00:00
Mario
fedce4cd74 cleanup 2023-01-24 09:36:27 +00:00
Mario
cac48fc4bf use light colored navbar for light mode - this makes the focus light schema redundant 2023-01-24 09:29:00 +00:00
Mario
1cad844d2d theme fixes 2023-01-22 15:35:55 +00:00
Mario
2d5e09f930 theme fixes 2023-01-20 20:07:37 +00:00
Mario
fbda34935d remove dark schema quirks 2023-01-20 11:19:39 +00:00
Mario
c5ca7f236f bump version 2023-01-20 11:06:05 +00:00
Mario
9dc949b62c native dark theme initial checkin 2023-01-20 11:05:15 +00:00
Mario
40394b94d7 typo :\ 2023-01-17 10:33:31 +00:00
Mario
bae446973f reflect pubstream disable/enable logic change in can_view_public_stream() 2023-01-17 10:29:12 +00:00
Mario
2805520d1b Merge remote-tracking branch 'origin/8.0RC' 2023-01-13 20:01:05 +00:00
Mario
fb7ca18820 version 8.0 2023-01-13 19:56:11 +00:00
Mario
1b00d5657f Merge branch 'dev' into 8.0RC 2023-01-13 19:55:44 +00:00
Mario
cd9f35e78a update changelog 2023-01-13 19:55:18 +00:00
Mario
f9cedab964 update changelog 2023-01-13 09:42:57 +00:00
Mario
9ec516e5a4 Merge branch 'dev' into 8.0RC 2023-01-12 16:12:26 +00:00
Mario
550b6d90a4 missing semicolon 2023-01-12 16:11:42 +00:00
Mario
5cb92b6e21 Merge branch 'dev' into 8.0RC 2023-01-12 11:55:13 +00:00
Mario
8a7b221412 mark old hubloc entries from re-installed hubs deleted if we discover any 2023-01-12 11:28:48 +00:00
Mario
d092e79ebc remove fragment in notifier - it should not be required, when processing multiple choice polls sleep some time before calling the notifier 2023-01-12 11:04:03 +00:00
Mario
2ddb88a34d RC2 2023-01-11 19:57:35 +00:00
Mario
71761c9039 Merge branch 'dev' into 8.0RC 2023-01-11 16:35:21 +00:00
Mario
16555b93bb fix race conditions when processing multiple choice polls 2023-01-11 16:34:23 +00:00
Mario
bd5e834b42 Merge branch 'dev' into 8.0RC 2023-01-08 08:20:05 +00:00
Mario
2eb4f093be update theme requirements 2023-01-08 08:19:37 +00:00
Max Kostikov
d4bf587103 Merge branch 'dev' into 'dev'
Fix Russian translation escaping

See merge request hubzilla/core!2033
2023-01-07 14:06:54 +00:00
Max Kostikov
ae7bd8b644 Fix translation escaping 2023-01-07 14:05:52 +00:00
Max Kostikov
f89cede020 Merge branch 'dev' into 'dev'
Update Russian translations

See merge request hubzilla/core!2032
2023-01-07 13:58:39 +00:00
Max Kostikov
59facf6f00 Update hstrings.php 2023-01-06 11:29:49 +00:00
Max Kostikov
01d93733ae Update hmessages.po 2023-01-06 11:24:03 +00:00
Mario
4c434129a6 Merge branch 'dev' into 8.0RC 2023-01-05 18:25:45 +01:00
Mario
b40499b4c1 revert accidental change in session 2023-01-05 18:25:08 +01:00
Mario
66333aedb7 fix version 2023-01-05 18:23:00 +01:00
Mario
47071c58aa fix affinity slider updates - issue #1714 2023-01-05 18:21:49 +01:00
Mario
79d99688b4 bump version 2023-01-05 11:39:09 +01:00
Mario
edcb0631aa composer dump autoload 2023-01-05 11:35:15 +01:00
Mario
bc361e6469 strings and version 2023-01-05 11:33:50 +01:00
Mario
c95ef1a5c0 pdledit_gui: only show installed modules and widgets 2023-01-05 11:06:19 +01:00
Mario
0c0891f64f bump version 2023-01-05 10:37:40 +01:00
Mario
23828f53bc pubstream: when going to conv from unthreaded mode stay in the module 2023-01-05 10:29:42 +01:00
Mario
f909e129ab Merge branch 'nb-no/update-translations' into 'dev'
Update translations for nb-no (Norsk Bokmål)

See merge request hubzilla/core!2031
2023-01-04 20:34:57 +00:00
Mario
7d4bcc2e8b translateable strings 2023-01-04 20:20:14 +00:00
Mario
2eb4d87621 fix issue #1717 2023-01-04 20:14:11 +00:00
Mario
435888c1a3 bump version 2023-01-04 19:39:11 +00:00
Mario
e69fabcd71 pdledi_gui: sort widgets 2023-01-04 19:33:18 +00:00
Mario
1a283301cf Revert "pdledit_gui: minor cleanup"
This reverts commit 031df70cf8.
2023-01-04 19:29:42 +00:00
Mario
031df70cf8 pdledit_gui: minor cleanup 2023-01-04 19:29:11 +00:00
Mario
3ad36db7dd pdledit_gui: minor cleanup 2023-01-04 19:27:44 +00:00
Mario
e16ea1ae05 pdl editor for addon iitial commit 2023-01-04 14:25:46 +00:00
Mario
941135a0a6 we should look for owner_xchan just like in mod pubstream 2023-01-04 09:01:44 +00:00
Mario
29776ecea2 queueworker: implement auto_queue_worker_sleep setting in frontend 2023-01-03 13:50:22 +00:00
Mario
d2edef5c5a go away if method is not implemented 2023-01-03 13:30:53 +00:00
Mario
da9349ea62 provide inline error messages for mod cloud 2023-01-03 10:59:38 +00:00
Mario
de0d2afc15 fix issues with pubstream tagcloud 2023-01-02 21:56:20 +00:00
Mario Vavti
d8c94c2003 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2023-01-02 20:39:15 +01:00
Mario Vavti
0e71bfe222 add sys channel to receiveres for public items 2023-01-02 20:38:56 +01:00
Mario
0ae402e624 bump version 2023-01-02 18:38:44 +00:00
Mario
b96dc11ddd improve sse loop 2023-01-02 18:37:36 +00:00
Mario Vavti
37b539eaa5 fix wrong variable - issue #1720 2023-01-01 21:25:15 +01:00
Mario Vavti
0741708086 change the logic of building the site only public stream. we will now fetch sys channel items but restrict them to authors of this site only. this fixes a comment permission issue. 2023-01-01 21:21:13 +01:00
Mario
a30cfd8fec filter approvals 2022-12-27 16:08:08 +00:00
Mario
633cd11c5b move mod queueworker to /admin 2022-12-27 10:44:54 +00:00
Mario
3101c6540a add workerq to the install schemas 2022-12-27 10:33:29 +00:00
Mario
d2d6be73b8 fix subquery in hq widget and order by hubloc_id desc in handle_tag() to make sure we get the most recent entry when using privacy tags 2022-12-26 09:08:54 +00:00
Mario
a46e2c1e6d only display details if there are any 2022-12-22 13:35:46 +00:00
Mario
2b0404fefc queueworker: add some more details 2022-12-22 13:29:34 +00:00
Mario
7ef9462286 bring back item-highlight 2022-12-22 12:22:32 +00:00
Mario Vavti
c6e7a7eaee comment out unused code 2022-12-22 12:42:44 +01:00
Mario
999e142370 minor cleanup 2022-12-22 10:09:35 +00:00
Mario
a7ad117a83 there is no point in wrapping single queries into a transaction 2022-12-22 10:02:31 +00:00
Mario
1ba44fc117 update 2022-12-21 17:15:34 +00:00
Mario
ca5610ebf1 bump version 2022-12-21 17:13:09 +00:00
Mario
e5c70a1304 queueworker: adjust process query to be complient with mariadb < 10.6 and add process timeout exceptions for long running processes 2022-12-21 17:11:33 +00:00
Mario
7dd2308534 pooll fixes 2022-12-20 20:16:06 +00:00
Mario Vavti
62eee07b6e make sure to include only zot6 hublocs in this query. including other networks could lead to unexpected results 2022-12-20 14:06:14 +01:00
Mario
f6d9406063 streamline ap followers only privacy warning with current handling. also fixes possible php error.
(cherry picked from commit 34125177e8)
2022-12-19 10:05:02 +01:00
Mario
34125177e8 streamline ap followers only privacy warning with current handling. also fixes possible php error. 2022-12-19 09:04:24 +00:00
Mario
d977b5d662 bump version 2022-12-18 10:24:44 +00:00
Mario
e36677b757 queueworker: cleanup and implement auto sleep interval (hidden config for now) 2022-12-18 10:19:06 +00:00
Mario
4d54755057 queueworker: fix maxworkers check and cleanup 2022-12-15 16:53:17 +00:00
Mario
91917c98e4 bump version 2022-12-15 09:19:56 +00:00
Mario
2f687de477 queueworker testing and more logging to syslog 2022-12-15 09:18:58 +00:00
Mario Vavti
5446062b95 bump version 2022-12-12 23:28:26 +01:00
Mario Vavti
c9e170dfcc queueworker: introduce new interval config queueworker.queue_interval - defaults to 500000 microseconds. No config UI yet. 2022-12-12 23:26:45 +01:00
Mario
e3a19469eb bring back poll and delivery interval 2022-12-12 09:03:49 +00:00
Mario
45f8e43be4 debug from php log 2022-12-11 20:46:02 +00:00
Mario
7ef0b05ce6 fix typo 2022-12-11 20:24:22 +00:00
Mario
c5a0ec4e93 css fixes 2022-12-11 19:19:47 +00:00
Mario
1c17768dc5 minor fixes 2022-12-11 10:40:02 +00:00
Mario
86e1dd4673 remove debug logging 2022-12-10 17:06:54 +00:00
Mario
0ee41c3341 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2022-12-10 17:04:18 +00:00
Mario
e1c2835173 add option to set worker sleep based on load average, remove redundand code and add return to some daemons 2022-12-10 17:03:57 +00:00
Max Kostikov
5c6d3753ef Fix Redis session PHP warnings 2022-12-09 15:53:01 +00:00
Mario
6e881bcef2 exclude not tagable xchan networks handle_tag()
(cherry picked from commit 4f9a933108)
2022-12-08 21:41:56 +01:00
Mario
4f9a933108 exclude not tagable xchan networks handle_tag() 2022-12-08 20:40:37 +00:00
Mario
9f8585914c sse_bs: respect the site firehose setting 2022-12-07 14:07:31 +00:00
Mario
3ba27b9752 add mark to html2bbcode parser 2022-12-07 11:01:28 +00:00
Mario
abae5de4d8 when uploading a image file, embed it in the item. otherwise attach it 2022-12-07 10:50:26 +00:00
Mario
6952c5a3f5 $visitor is a string 2022-12-06 11:15:53 +00:00
Mario
0184d2c292 typo 2022-12-04 10:43:57 +00:00
Mario
7a40561aaa wording 2022-12-04 10:36:30 +00:00
Mario
79e6c9590a the logic for public stream has changed - adjust help text and externals, disable lockfile check in cron daemon 2022-12-04 10:27:02 +00:00
Mario
12a963cc40 version 7.8.7 2022-12-03 09:01:18 +00:00
Mario
f89975fd0e changelog 7.8.7
(cherry picked from commit b4dffe5946)
2022-12-03 09:59:06 +01:00
Mario
b4dffe5946 changelog 7.8.7 2022-12-03 08:57:56 +00:00
Mario
539b69d507 look for iconfig at the right place, fix mod sharedwithme, comment out unused configs 2022-12-03 08:53:53 +00:00
Harald Eilertsen
9927363f39 Update translations for nb-no (Norsk Bokmål) 2022-12-03 00:30:16 +01:00
Mario
1a4f59cd70 bump version 2022-12-02 19:32:47 +00:00
Mario
25727a24a5 fix typos 2022-12-02 19:29:46 +00:00
Mario
2fd2dc964b Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2022-12-02 19:28:52 +00:00
Mario
935b032f15 db update 1254 2022-12-02 19:22:50 +00:00
Mario
2bb58843ab move queueworker to core and bump version 2022-12-02 19:22:19 +00:00
Mario
00512579f3 fix regression when adding feed contacts
(cherry picked from commit 5216c5b232)
2022-12-02 18:47:40 +01:00
Mario
6f09796142 Merge branch 'fix-category-widget-urls' into 'dev'
Fix Category widget URLs

See merge request hubzilla/core!2030
2022-12-02 17:46:42 +00:00
Mario
697a74f37e fix regression: new event not created
(cherry picked from commit d16b6c3838)
2022-12-02 18:06:20 +01:00
Mario
d16b6c3838 fix regression: new event not created 2022-12-02 15:18:01 +00:00
Mario
e4461f2e61 adjust the query to work with postgres 2022-11-30 11:20:10 +00:00
Mario
baf1b8b02d fetch the unseen count in a subquery instead of a separate query and rename array key 2022-11-30 10:36:55 +00:00
Mario
3ce1373ae0 provide a pdl file for mod invite and set the profile 2022-11-30 09:18:57 +00:00
Mario
4002531b92 fix issue where site_firehose setting was always false 2022-11-29 10:00:07 +00:00
Mario
004d0f074d disable context help until its content will be updated - it is not helpful otherwise 2022-11-27 12:20:04 +00:00
Mario
e87887c328 re-install: make sure to fetch the latest hubloc in api_auth otherwise authentication might fail 2022-11-27 09:40:23 +00:00
Harald Eilertsen
2de2c8e207 Fix Category widget URLs
The category widget template expects a URL without any query params, as
it appends `/?cat=<selected category>` to the base URL passed to it.

The Widget code tried to preserve any query param passed to it except
for the `cat` query param. When passed to the template, this caused the
invalid URLs to be generated.

Example input url:

    https://example.com/channel/user?f=&tag=pasta

The URL generated for the "Dinner" category would then be:

    https://example.com/channel/user&tag=pasta&tag=pasta/?cat=Dinner

Which is troublesome in more than one way, and cause at least some
search bots to go wild by sending requests with increasingly long URLs.

This patch will simply discard the existing query params in the URL, so
with the same input url, the generated URL for the "Dinner" category
will now be:

    https://example.com/channel/user/?cat=Dinner

This is comparable to what the Category Cloud and Tag Cloud widgets
already do.
2022-11-26 15:45:37 +01:00
Mario
c76f19f19a bump version 2022-11-26 08:39:59 +00:00
Mario
a050e8c8f5 should compare against abook_updated to make sure we do not always poll broken feeds 2022-11-26 08:37:45 +00:00
Mario
ae1fad5de7 basically every incoming item should have a uuid by now 2022-11-25 18:44:33 +00:00
Mario
68ca8951a8 mark unseen items seen after a certain amount of time (default 90 days) 2022-11-25 18:37:22 +00:00
Mario Vavti
1e4718eae1 do not always trigger a sse event if pubs notification are off or the app is not installed for the channel 2022-11-24 16:42:09 +01:00
Mario Vavti
680cf25f37 de-duplicate by mid. there is no combined index for uid and uuid hence the query could be slow if an uid has a lot of items. the workaround for hubzilla < 4.0 is not required anymore 2022-11-24 16:08:57 +01:00
Mario Vavti
7ec6df495f slight restructure 2022-11-24 16:05:19 +01:00
Mario
aeda31fda7 fix warnings 2022-11-24 09:52:50 +00:00
Mario
5248aa3065 css fix 2022-11-24 09:42:35 +00:00
Mario
67767c5853 Merge branch 'redbasic/dark-theme-fixes' into 'dev'
redbasic: Dark scheme fixes

See merge request hubzilla/core!2029
2022-11-23 18:43:42 +00:00
Mario
6de1aec683 the blue dots were slightly too bold. 2022-11-22 21:10:11 +00:00
Harald Eilertsen
221d3cdf6a redbasic: Dark theme fixes
- Make rows in admin tables readable while hovering over them.
2022-11-22 15:31:54 +01:00
Harald Eilertsen
1ff12c5520 redbasic: Dark scheme fixes
- Changed background of category tags to make them readable.
- Changed background on "view source" dialog to make it readable.
2022-11-22 09:46:41 +01:00
Mario
41376ec2cd fix issue in tag_deliver() and silence some more warnings 2022-11-20 20:31:59 +00:00
Mario
bf335ecaf3 hq widget: use distinct classes for seen and unseen thread items count 2022-11-18 13:32:14 +00:00
Mario
424bc73f58 bump version 2022-11-18 10:45:42 +00:00
Mario
59e6989cbc hq widget: implement thread unseen items count 2022-11-18 10:43:33 +00:00
Mario
0e6b27c9f4 if a feed fails, do not update connected timestamp. attempt to poll feeds only once a day if we could not fetch it last time we tried 2022-11-17 11:50:13 +00:00
Mario
0e157e4e8b remove logging 2022-11-17 09:11:34 +00:00
Mario
805074a0f9 externals: fix warnings 2022-11-17 09:09:02 +00:00
Mario
5216c5b232 fix regression when adding feed contacts 2022-11-17 08:57:09 +00:00
Mario
8633162f0c bump versionà 2022-11-15 21:22:39 +00:00
Mario
c392a77b46 performance: just count the first 99 unseen items and display 99+ if there are more than 99 2022-11-15 21:22:10 +00:00
Mario
08c2c9bc22 possible fix for issue #1698 2022-11-15 19:29:29 +00:00
Mario
f64bd590a8 bump version 2022-11-14 05:51:32 +00:00
Mario
131ffcf582 changelog 7.8.6 2022-11-14 05:49:33 +00:00
Mario
b17a0aef17 fix typo and version 7.8.6 2022-11-14 05:47:16 +00:00
Mario
8a21783fa5 bump version 2022-11-13 19:45:36 +00:00
Mario
53152e2ef5 version 7.8.5 2022-11-13 19:44:08 +00:00
Mario
ca6ba92d82 Merge branch 'dev' 2022-11-13 19:43:12 +00:00
Mario
04516b787a update changelog 2022-11-13 19:42:07 +00:00
Mario
6e124a4d72 changelog 2022-11-13 19:40:03 +00:00
Mario
6da65c7ddc cast the type to update if it is an edit 2022-11-13 17:13:33 +00:00
Mario
9eb332f032 allow to look for pubstream items if we do not own one but make sure the permissons are checked correctly 2022-11-10 17:57:26 +00:00
Mario
30ddee65a4 fix wrong array key and undefined array key 2022-11-10 10:48:24 +00:00
Mario
63dc8d7fc4 fix undefined variable 2022-11-10 10:37:41 +00:00
Mario
a1a287bac7 fix typo in variable name 2022-11-10 10:34:05 +00:00
Mario
e9b786d5e8 Ãwrong array key 2022-11-09 13:05:48 +00:00
Mario
ad9fb411f6 address issue #1705 2022-11-09 11:52:55 +00:00
Mario
1ff982983e items_fetch(): check if set and if there is a value 2022-11-09 11:34:03 +00:00
Mario
8c6c43d762 items_fetch(): check if set and if there is a value 2022-11-09 11:33:10 +00:00
Mario
6baf197842 version 7.8.4 2022-11-09 09:38:09 +00:00
Mario
42e5a50e4f changelog and version 2022-11-09 09:33:18 +00:00
Mario
b713c9a491 fix new uuid created when editing post 2022-11-09 09:27:33 +00:00
Mario
64ade742d9 whitespace 2022-11-07 19:55:30 +00:00
Mario
1870c3c876 whitespace 2022-11-07 19:55:13 +00:00
Mario
23b272aafd merge conflict 2022-11-07 19:53:03 +00:00
Mario
057db41758 bump version 2022-11-07 19:50:55 +00:00
Mario
839c5a8e41 fix regression where automatically created directories were not public and pinned/featured state of apps was not displayed correctly 2022-11-07 19:41:22 +00:00
Mario
36b8b6bf6c Merge branch 'dev' 2022-11-06 08:27:18 +00:00
Mario
40d74fa779 fix case and german translation string 2022-11-06 08:27:00 +00:00
Mario
249bdeb642 Merge branch 'dev' 2022-11-05 10:26:14 +00:00
Mario
b4ee80d1ea changelog 2022-11-05 10:25:40 +00:00
Mario
96bf9d0769 version 7.8.2 2022-11-05 09:52:11 +00:00
Mario
7fc9c83986 Merge branch 'dev' 2022-11-05 09:50:55 +00:00
Mario
5502f1cc63 do not update the guid on xchan/hubloc updates and define some array keys 2022-11-04 10:31:05 +00:00
Mario
b55801323c fix warnings 2022-11-03 15:26:46 +00:00
Mario
818374c8cc wor around shares from streams not rendered correctly 2022-11-03 13:54:40 +00:00
Mario
e80191d4cd fix regression 2022-11-03 13:09:11 +00:00
Mario
c2a796b6ea rename variable and warning fixes 2022-11-03 11:57:35 +00:00
Mario
00694f0dfd css fixes 2022-11-02 19:19:24 +00:00
Mario
134f4c5b52 undefined array key 2022-11-02 18:59:47 +00:00
Mario
0840fc42f9 php warning 2022-11-02 18:49:36 +00:00
Mario
2650a647e9 php warnings 2022-11-02 18:32:52 +00:00
Mario Vavti
3311269162 throw a 404 if we could not determine which channel to load 2022-11-02 17:52:19 +01:00
Mario
b2172d39f6 re-install: if we have a cashed entry, make sure we fetch the latest 2022-11-02 15:54:12 +00:00
Mario Vavti
f4d39bd3c8 fix more php warnings 2022-11-02 16:52:42 +01:00
Mario Vavti
1cf659033b set hubloc_connected in mod fhublocs otherwise the hublocs might be removed by prune_hub_reinstalls() 2022-11-02 10:38:40 +01:00
Mario
3dc5527690 css variables 2022-10-31 14:01:00 +00:00
Mario
81b02d04b5 version 7.8.1 2022-10-26 21:57:53 +00:00
Mario
95f6f9e10a Merge branch 'dev' 2022-10-26 21:56:32 +00:00
Mario
9554f53519 update version and changelog 2022-10-26 21:54:29 +00:00
Mario
5d7081a224 fix php warnings 2022-10-26 21:40:27 +00:00
Mario
9cbdf3f31f wrong argument in documentation 2022-10-26 19:27:15 +00:00
Mario
c8bc1b560b missing field in query 2022-10-26 19:11:13 +00:00
Mario
40ae6b396f fix php warnings 2022-10-26 18:12:56 +00:00
Mario
9c117ffa05 fix php warnings 2022-10-26 15:56:41 +00:00
Mario Vavti
9e95f189ed fix php warnings 2022-10-26 17:56:04 +02:00
Mario Vavti
221b31bcc6 fix php warnings 2022-10-25 19:06:17 +02:00
Mario Vavti
8879776d64 fix php warnings 2022-10-23 14:02:19 +02:00
Mario
5edd13c6bb fix various issues 2022-10-21 11:20:23 +02:00
Mario
7ca289edd0 fix php warnings 2022-10-20 19:25:01 +00:00
Mario
bf434818d7 fix php warnings 2022-10-20 13:16:03 +00:00
Mario
03aeb88832 fix php warnings 2022-10-20 10:25:11 +00:00
Mario Vavti
bb5b33a0d3 fix more php warnings 2022-10-20 11:40:31 +02:00
Mario Vavti
53931017b9 fix php warnings 2022-10-20 11:15:06 +02:00
Mario Vavti
e9ca17cec1 fix php warnings 2022-10-18 12:39:13 +02:00
Mario
f70956964b fix php warning 2022-10-14 15:23:23 +00:00
Mario Vavti
4547a9d9d3 catch decryption failure edgecase 2022-10-14 17:13:23 +02:00
Mario Vavti
71accb6b0a fix php warnings 2022-10-13 16:38:18 +02:00
Mario Vavti
2a95500b65 fix more php warnings 2022-10-13 13:15:08 +02:00
Mario Vavti
2ddad66ce7 mod dirsearch: fix php warnings 2022-10-13 12:48:22 +02:00
Mario
108be24aed remove logging 2022-10-12 19:39:15 +00:00
Mario
71efb05658 fix php warnings 2022-10-12 19:36:24 +00:00
Mario
a9a36894cb fix php warnings 2022-10-12 12:15:30 +00:00
Mario
bc9778e02f poco: remove unused parameters 2022-10-12 10:02:18 +00:00
Mario
a83d2efe84 remove dead code and deal with conv privacy mismatches in Activity::store() 2022-10-12 09:47:47 +00:00
Mario
d3856caf81 composer update michelf/php-markdown 2022-10-12 09:09:55 +00:00
Mario
e1f9b1c47d composer update jbroadway/urlify 2022-10-12 09:01:22 +00:00
Mario
497c953d0e composer update bshaffer/oauth2-server-php 2022-10-12 08:54:51 +00:00
Mario
bec76bd057 composer update ezyang/htmlpurifier 2022-10-12 08:53:14 +00:00
Mario
54f4762e1a composer update symfony 2022-10-12 08:48:27 +00:00
Mario
8bf5c18425 composer update ramsey/uuid 2022-10-12 08:45:01 +00:00
Mario
c36bb17475 composer update sabre 2022-10-12 08:42:41 +00:00
Mario
2291fcdf11 composer update simplepie 2022-10-12 08:28:35 +00:00
Mario
4070c46d15 composer update smarty 2022-10-11 19:20:46 +00:00
Mario
a749db8d0f composer update twbs 2022-10-11 18:45:17 +00:00
Mario
10ba98c4f5 Revert "update composer libs"
This reverts commit 108a3efe0b.
2022-10-11 18:41:34 +00:00
Mario
108a3efe0b update composer libs 2022-10-11 18:34:03 +00:00
Mario
ccd826f63a Revert "update composer libs"
This reverts commit 5e5f0aa955.
2022-10-11 18:29:06 +00:00
Mario
5e5f0aa955 update composer libs 2022-10-11 18:18:57 +00:00
Mario
f9a4c53e3f jQuery.timeago.settings.strings should not be in document.ready 2022-10-11 10:03:05 +00:00
Mario
60b576568e more css fixes 2022-10-11 09:45:12 +00:00
Mario
d0e1b73205 css fixes 2022-10-11 09:18:40 +00:00
Mario
ef2448e17e Merge branch '7.8RC' 2022-10-10 18:05:26 +00:00
Mario
99a5cf1ad4 version 7.8 2022-10-10 18:03:48 +00:00
Mario
bc3113ae16 Merge branch 'dev' into 7.8RC 2022-10-10 16:50:04 +00:00
Mario
fb475da008 update changelog 2022-10-10 16:37:24 +00:00
Mario
d5fc3ad646 Merge branch 'dev' into 7.8RC 2022-10-10 16:29:50 +00:00
Mario
8b7da6e318 spanish translations as per Manuel 2022-10-10 15:06:48 +00:00
Mario
ed208c4bcc update changelog 2022-10-10 15:02:37 +00:00
Mario
6ab65519a0 when updating hubloc_connected also update hubloc_updated
(cherry picked from commit 4549bc89ec)
2022-10-05 10:49:19 +02:00
Mario
4549bc89ec when updating hubloc_connected also update hubloc_updated 2022-10-05 08:41:31 +00:00
Mario
a0430f91bd fix owa in case of hub reinstalls 2022-09-30 10:25:46 +00:00
Mario
624bb1db8d Merge branch 'dev' into 7.8RC 2022-09-30 07:56:24 +00:00
Mario
9f522bbe6c update strings 2022-09-30 07:54:46 +00:00
Mario
931da3b4f7 Merge branch 'dev' into 7.8RC 2022-09-30 07:38:47 +00:00
Mario
5a25fd54a4 fix issue #1694 2022-09-30 07:14:47 +00:00
Mario
9f0f4c50a4 update htconfig.tpl 2022-09-30 06:43:53 +00:00
Mario
0bf3d31578 make it an info 2022-09-29 15:36:02 +00:00
Mario Vavti
8ca293c3e4 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2022-09-29 16:59:07 +02:00
Mario Vavti
ba0c877ffc fix menu item display issue 2022-09-29 16:56:54 +02:00
Mario
b8e00c2dc9 remove custom navbar override from repo 2022-09-29 14:19:14 +00:00
Mario
2dd48898a8 Merge branch 'dev' into 'dev'
GERMAN TRANSLATION - fix for minutes, hours, years,... by polls in .po file and translation more competed  pdpr1 and SiteTOS added

See merge request hubzilla/core!2027
2022-09-29 14:16:22 +00:00
Rock
66fc807655 GERMAN TRANSLATION - fix for minutes, hours, years,... by polls in .po file and translation more competed pdpr1 and SiteTOS added 2022-09-29 14:16:22 +00:00
Mario
653eb2909b Merge branch 'dev' into 7.8RC 2022-09-29 09:03:29 +00:00
Mario
72520a2dd9 fix hq widget displaying superblocked items 2022-09-29 08:58:36 +00:00
Mario
a7d4666a70 Merge branch 'dev' into 7.8RC 2022-09-28 15:21:34 +00:00
Mario
13476d5003 remove unnecessary check 2022-09-28 15:21:11 +00:00
Mario
879cdedec3 Merge branch 'dev' into 7.8RC 2022-09-28 10:35:36 +00:00
Mario
05bd2a1f9e one more hub reinstall fix 2022-09-28 10:35:09 +00:00
Mario
c49d1547c4 Merge branch 'dev' into 7.8RC 2022-09-28 10:27:58 +00:00
Mario
ad35363c2e hub reinstall issues 2022-09-28 10:27:35 +00:00
Mario
b3f70140e5 Merge branch 'dev' into 7.8RC 2022-09-27 08:59:44 +00:00
Mario
2f21dc50b4 fix mod poke 2022-09-27 08:59:08 +00:00
Mario
cbd8c2483b fix versionà 2022-09-26 08:33:47 +00:00
Mario
03475bfb15 Ãfix regression 2022-09-26 08:31:57 +00:00
Mario
bb9411e7dc update dev version 2022-09-26 07:16:11 +00:00
Mario
bce4e2d022 update version and strings 2022-09-26 07:13:01 +00:00
Mario
7cfc14fef7 emit a notice if an item was deleted - issue #1691 2022-09-22 12:50:11 +00:00
Mario
f220cf3173 fix issue #1687 2022-09-22 12:02:21 +00:00
Mario
725359b1aa fix issue #1690 2022-09-22 10:55:58 +00:00
Mario
937d6cb1ef php8: fix warnings 2022-09-22 06:31:35 +00:00
Mario
118a5edebc fix warnings and regressions 2022-09-15 09:19:55 +00:00
Mario
1b4333e8d9 chek permissions in get_things() - partly fixes issue #1686 a lot more work is requird though 2022-09-14 18:35:36 +00:00
Mario
d66a0b50e9 address issue #1688 2022-09-14 17:43:12 +00:00
Mario
1d56b9a1bb php8: warning fixes 2022-09-14 12:31:19 +00:00
Mario
96535ee4df make actor_store() fetch the actor object if none is provided, remove announce from the is_response array and provide a function to find the attributedTo url 2022-09-13 11:20:35 +00:00
Mario
b55f314d7e php8: fix warnings 2022-09-11 18:26:27 +00:00
Mario
480862d714 php8: fix more warnings 2022-09-11 14:58:40 +00:00
Mario
990a3af2a7 php8: random cleanup and warning fixes 2022-09-08 20:02:22 +00:00
Mario
1f5a23143a remove debug code 2022-09-07 18:07:38 +00:00
Mario
fcfb9e9758 fix random php warnings 2022-09-07 12:50:46 +00:00
Mario
9beee689ce fix display of star and dreport links 2022-09-06 11:32:27 +00:00
Mario
2c388c3833 add missing modal 2022-09-06 10:52:59 +00:00
Mario
1a75066616 revert: do not wrap multi line code blocks into pre tag 2022-09-06 10:27:01 +00:00
Mario
3dfb0bcae9 do not wrap multi line code blocks into pre tag 2022-09-06 09:21:39 +00:00
Mario
9ac0b77e92 fix missing closing div tag if there are no recent channel activities to display 2022-09-05 08:04:37 +00:00
Mario
6421a32520 fix issue where an unkown diaspora author was not imported if the comment arrived via a relayed activity and a minor css fix 2022-08-30 13:51:59 +00:00
Mario
fdcae52740 do not escape tags here since it will destroy additional query params 2022-08-21 18:21:05 +00:00
Mario
a8752844ef Activity: check for other forms of as:Public, Search: make sure to run htmlspecialchars_decode on the AP url so that previously encoded chars will be decoded again 2022-08-21 16:02:51 +00:00
Mario
e04ce5028e more css fixes 2022-08-20 15:53:09 +00:00
Mario
f2c4d80ac0 more css fixes 2022-08-20 15:10:16 +00:00
Mario
d8a6226805 fix syntax error 2022-08-20 11:26:28 +00:00
Mario
fedf60a32c redbasic dark: fixes 2022-08-20 11:23:46 +00:00
Mario
b3548fefc1 bump version 2022-08-20 10:07:57 +00:00
Mario
febd64c527 pdledit_gui: fix offcanvas 2022-08-20 10:06:04 +00:00
Mario
d67a5c5070 redbasic dark schema major cleanup 2022-08-20 09:56:23 +00:00
Mario
aefe7ddd8f redbasic: make use of css variables and implement link_hover_colour 2022-08-20 09:31:30 +00:00
Mario
254dea7558 more css fixes 2022-08-19 15:02:06 +00:00
Mario
b1550f7922 more css fixes 2022-08-19 14:34:09 +00:00
Mario
2d07c3e45d more bs upgrade fixes 2022-08-19 13:39:31 +00:00
Mario
e5f3406cb5 time for a new screenshot 2022-08-19 13:30:38 +00:00
Mario
185ddf1eaf update to bootstrap 5.2 and fixes 2022-08-19 13:15:48 +00:00
Mario Vavti
2734335869 version 2022-08-07 14:16:56 +02:00
Mario Vavti
0132c4e36e Merge branch 'dev' 2022-08-07 14:16:31 +02:00
Mario Vavti
7dee47183d changelog 2022-08-07 14:16:00 +02:00
Mario Vavti
9c4988c297 Merge branch 'dev' 2022-08-07 14:07:10 +02:00
Mario Vavti
3bfbc70587 check against null 2022-08-07 14:06:08 +02:00
Mario Vavti
34858fce1c Merge branch 'dev' 2022-08-07 12:17:56 +02:00
Mario Vavti
b47dab0ee9 update widget description 2022-08-05 12:45:43 +02:00
Mario Vavti
6eeb033b96 only decode attachment and iconfig for nonresponse activities 2022-08-04 12:42:35 +02:00
Mario Vavti
0679cb8e00 fix wrong attribution in unseen like notifications 2022-08-04 12:13:00 +02:00
Mario
3abc9ee387 fix regression in dark schema
(cherry picked from commit 2e9211cf41)
2022-07-27 09:29:22 +02:00
Mario
2e9211cf41 fix regression in dark schema 2022-07-27 07:27:51 +00:00
Mario
40377796ed Merge branch '7.6RC' 2022-07-26 18:00:00 +00:00
Mario
fedad7f31a version 7.6 2022-07-26 17:59:11 +00:00
Mario
d2a34e0107 Merge branch 'dev' into 7.6RC 2022-07-26 17:20:30 +00:00
Vinzenz Vietzke
769c822568 StartSSL is defunct since 2018
https://www.thesslstore.com/blog/startcom-ssl-shutting-down-2018/
2022-07-26 17:19:16 +00:00
Mario
c452a621fe Merge branch 'remove-dead-startssl' into 'master'
StartSSL is defunct since 2018

See merge request hubzilla/core!2022
2022-07-26 17:18:26 +00:00
Mario
231ab95ef6 update changelog 2022-07-26 17:16:13 +00:00
Mario
7c01b59ffb version 2022-07-26 15:38:57 +00:00
Mario
e79668ddf4 fix lang tests if result is ambigous 2022-07-26 15:37:17 +00:00
Mario
dc6b6fc353 add "falsey" test 2022-07-26 15:22:05 +00:00
Vinzenz Vietzke
34ea58cf38 StartSSL is defunct since 2018
https://www.thesslstore.com/blog/startcom-ssl-shutting-down-2018/
2022-07-25 12:14:43 +00:00
Mario
199168c318 bump dev version 2022-07-19 12:44:46 +00:00
Mario
063d4bbd7d composer autoload 2022-07-19 12:41:53 +00:00
Mario
29fd9b9d64 version and strings 2022-07-19 12:40:08 +00:00
Mario
c301baafb5 check if the webpages app is installed 2022-07-18 17:52:00 +00:00
Mario
4282672201 bump version 2022-07-16 14:52:10 +00:00
Mario
ae705dd865 HQ dashboard - missing files 2022-07-16 14:49:56 +00:00
Mario
f0fa2ce171 bump version 2022-07-15 17:51:01 +00:00
Mario
d6a9a9927c HQ dashboard - initial checkin 2022-07-15 17:50:02 +00:00
Mario
40b4636858 fix vcard-card background for dark schema 2022-07-03 09:49:09 +00:00
Mario
97fe499b63 Merge branch 'redbasic/dark-fixes' into 'dev'
redbasic/dark: make category pills readable.

See merge request hubzilla/core!2021
2022-07-03 09:42:06 +00:00
Mario
e0915cffda es: update plural function 2022-06-23 17:10:35 +00:00
Mario
7602de85c3 make sure the document is loaded 2022-06-23 17:01:43 +00:00
Harald Eilertsen
0787817eb8 redbasic/dark: make category pills readable. 2022-06-21 19:24:21 +02:00
Mario
e030648957 Merge branch 'dev' of https://codeberg.org/hubzilla/hubzilla into dev 2022-06-21 08:57:43 +00:00
hubzilla
b815935fd7 Merge pull request 'Fixing some error in Spanish translation' (#12) from mjfriaza/hubzilla:dev into dev
Reviewed-on: https://codeberg.org/hubzilla/hubzilla/pulls/12
2022-06-21 10:57:12 +02:00
Mario
a5000ba311 Merge branch 'dev' into 'dev'
Fix Opengraph images inside zmg opening tag

See merge request hubzilla/core!2020
2022-06-21 08:52:47 +00:00
Max Kostikov
5e2bb874c8 Fix Opengraph images inside zmg opening tag 2022-06-14 23:19:09 +02:00
mjfriaza
fcb5a7f645 Revert "Fixing some error in Spanish translation"
This reverts commit 1d99c3d3f7.
2022-06-12 18:18:55 +02:00
mjfriaza
b8c6520abb Fix two errors in Spanish translation 2022-06-12 17:21:14 +02:00
mjfriaza
1d99c3d3f7 Fixing some error in Spanish translation 2022-06-05 17:29:44 +02:00
Mario
5e112b395d oembed: implement a max oembed size which defaults to 1MB and do not try to oembed text previews 2022-06-03 08:51:54 +00:00
Mario
d1a8e7813a Revert "composer updates"
This reverts commit 47448b11cd.
2022-06-02 08:00:45 +00:00
Mario
a0582fec12 Revert "composer update"
This reverts commit 2cd3a7b3f0.
2022-06-02 08:00:31 +00:00
Mario
2cd3a7b3f0 composer update 2022-06-02 07:56:13 +00:00
Mario
47448b11cd composer updates 2022-06-02 07:43:33 +00:00
Mario
e63f043841 Merge branch '7.4RC' 2022-06-01 07:00:21 +00:00
Mario
33dd0c83e3 version 7.4 2022-06-01 06:59:23 +00:00
Mario
32dad136f8 Merge branch 'dev' into 7.4RC 2022-06-01 06:58:19 +00:00
Mario
073ed52538 update changelog 2022-06-01 06:58:05 +00:00
Mario
eef828cf3e fix version after merge 2022-05-31 09:38:54 +00:00
Mario
d0b5930a3a Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2022-05-31 08:42:54 +00:00
Mario
c66ad9ccc8 update changelog 2022-05-31 08:42:27 +00:00
Max Kostikov
9959a15c8e Merge branch 'dev' into 'dev'
Update Russian translation

See merge request hubzilla/core!2019
2022-05-28 13:31:24 +00:00
Max Kostikov
f0e4b4dc84 Update Russian translation 2022-05-28 15:28:40 +02:00
Mario
f62f808368 bump dev version 2022-05-25 08:45:21 +00:00
Mario
530a521679 version and strings 2022-05-25 08:41:25 +00:00
Mario
50782dfb83 prevent php error and add some doco 2022-05-25 08:34:29 +00:00
Mario
27a142d5c5 cleanup 2022-05-25 08:17:37 +00:00
Mario
6d00b2e63d bump php version requirement 2022-05-25 08:14:59 +00:00
hubzilla
7be1415a3a Merge pull request 'Update Spanish' (#11) from mjfriaza/hubzilla:dev into dev
Reviewed-on: https://codeberg.org/hubzilla/hubzilla/pulls/11
2022-05-25 09:54:22 +02:00
Mario
0a30b12f7d move wiki related templates to addon 2022-05-25 07:02:15 +00:00
Mario
3058cbfbb2 categories widgets cleanup 2022-05-24 09:31:30 +00:00
Mario
ae780c977b move article and card categories widgets to addons 2022-05-24 09:18:41 +00:00
Mario
e146a67f4b fix photo permission if a photo description is available and use the filename as default photo description if uploading via the editor 2022-05-23 18:56:09 +00:00
Mario
162d86983a streamline inbound attachment handling and fix regression from issue #1679 2022-05-23 09:26:29 +00:00
Mario
8534366a31 move photo flag feature entry to core 2022-05-21 08:25:14 +00:00
Mario
d1c6617dc9 missing files after composer updates 2022-05-20 09:21:23 +00:00
Mario
6f994709b9 do not show deprecated warnings by default 2022-05-19 08:27:09 +00:00
Mario
55d833a9c8 update composer libs 2022-05-19 08:18:15 +00:00
Mario
8ba4745097 update to remove core apps (wiki, cards, articles) which have been moved to addons 2022-05-19 08:04:39 +00:00
Mario
940a0c8b10 add a hidden config for the hs2019 http sig algo 2022-05-19 07:36:57 +00:00
Mario
8928b24e23 rendering fixes 2022-05-19 07:22:10 +00:00
Mario
ae9a9191f3 implement starring of pubstream items 2022-05-18 08:47:45 +00:00
mjfriaza
cb553bd016 Update Spanish 2022-05-17 14:01:28 +02:00
mjfriaza
a75c61d71e Merge remote-tracking branch 'upstream/dev' into dev 2022-05-17 13:44:06 +02:00
Mario
c1dc16a89d make sure we use source.content when rendering events to correctly render observer related content. fix wrong media types. 2022-05-16 20:44:53 +00:00
Mario
66436ce4a2 fix php errors 2022-05-14 19:04:05 +00:00
Mario
62b1ff4ba1 add the title in forum post reshares 2022-05-14 18:30:39 +00:00
Mario
304d136437 do not set allowed to true if verb is ACTIVITY_SHARE and slightly changed logic for conv fetches 2022-05-13 19:13:47 +00:00
Mario
1b4268b9b0 do not stringify integer value 2022-05-11 11:52:22 +00:00
Mario
a7968e6525 update queries in mod search - fixes #1677 2022-05-11 11:50:29 +00:00
Mario
e59cc3d404 deal with pleroma reactions 2022-05-10 12:15:29 +00:00
Mario
3a2d126877 use rev instead of _updated and the unix timestamp is less likely to cause issues in the future 2022-05-09 08:27:50 +00:00
Mario
ee3d6fcfee use addr for webfinger and name for the real name in the userinfo array 2022-05-09 08:23:55 +00:00
Mario
09d929bd56 add the update date to the icon url. some platforms will not update if the icon url remains static 2022-05-07 13:42:14 +00:00
Mario
bd55ae15f2 cleanup channel apps 2022-05-07 07:09:31 +00:00
Mario
2ca80118bf more cleanup 2022-05-06 19:10:28 +00:00
Mario
04eb20ac35 some cleanup after moving articles and cards to addons 2022-05-06 14:58:27 +00:00
Mario
f299391aa1 fix core issue #1676 and a liked/disliked/commented confusion 2022-05-06 08:24:17 +00:00
Mario
c334fc9d22 move wiki to addons 2022-05-06 07:29:59 +00:00
Mario
8520088376 move articles to addon - also remove the pdl 2022-05-04 19:26:45 +00:00
Mario
9ada8518dc move articles to addon 2022-05-04 19:26:05 +00:00
Mario
f0c09b374c move cards to addon 2022-05-04 18:46:45 +00:00
Mario Vavti
c5f33baf27 version 7.2.2 2022-04-26 11:12:43 +02:00
Mario Vavti
2efcdd92e0 Merge branch 'dev' 2022-04-26 11:11:53 +02:00
Mario Vavti
38fda98b6d changelog and version 2022-04-26 11:11:17 +02:00
Mario Vavti
f9fd195c24 Merge branch 'dev' 2022-04-26 11:08:10 +02:00
Mario Vavti
01e82090b2 hubloc in AS has been moved from data to meta a while ago 2022-04-26 11:07:23 +02:00
Mario Vavti
39602ede37 version bump 2022-04-25 22:53:04 +02:00
Mario Vavti
98a311ae40 version 7.2.1 2022-04-25 22:23:47 +02:00
Mario Vavti
5c398b3e8f Merge branch 'dev' 2022-04-25 22:21:12 +02:00
Mario Vavti
83e585ee9b more changelog 2022-04-25 22:19:20 +02:00
Mario Vavti
e386499bfa Merge branch 'dev' 2022-04-25 22:16:39 +02:00
Mario Vavti
4552630bf8 changelog 2022-04-25 22:15:31 +02:00
Mario Vavti
2d8065a780 whitespace 2022-04-25 21:34:47 +02:00
Mario Vavti
b94da93c74 if we have not been provided a profile id set the profile id to the default profile - fixes #1671 2022-04-25 21:34:05 +02:00
Mario Vavti
695045f197 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2022-04-23 20:53:05 +02:00
Mario Vavti
376733bd08 fix regression with incoming poll answers from activitypub 2022-04-23 20:52:45 +02:00
Mario
4c7c5137c5 check if addons have been removed from the filesystem and also remove them from the db if that is the case 2022-04-22 07:42:31 +00:00
Mario
930b9820f2 Revert "move AP addressing to pubcrawl"
This reverts commit 1390e1db39
2022-04-07 07:28:43 +00:00
Mario Vavti
b2fa63f2c8 move AP addressing to pubcrawl
(cherry picked from commit 1390e1db39)
2022-04-07 09:27:12 +02:00
Mario Vavti
1390e1db39 move AP addressing to pubcrawl 2022-04-07 09:20:06 +02:00
Mario
e7768ae954 fixes in regard to hub re-installs: dismiss deleted hublocs, make sure we use the latest hubloc entry for addressing, in Queue::deliver() prefer primaries since their info is probably more accurate
(cherry picked from commit 38d977e546)
2022-04-01 11:56:07 +02:00
Mario
38d977e546 fixes in regard to hub re-installs: dismiss deleted hublocs, make sure we use the latest hubloc entry for addressing, in Queue::deliver() prefer primaries since their info is probably more accurate 2022-04-01 09:50:12 +00:00
Mario
3e38a24f0a fix PHP error 2022-03-31 10:07:15 +00:00
mjfriaza
481ecee9e8 Update Spanish 2021-06-01 11:57:11 +02:00
3018 changed files with 384258 additions and 228581 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

33
.gitignore vendored
View File

@@ -49,6 +49,8 @@ doc/html/
# external repositories for themes/addons
extend/
# files generated by phpunit
tests/.cache
tests/.phpunit.result.cache
tests/results/
## exclude IDE files
@@ -78,5 +80,36 @@ composer.phar
vendor/**/tests/
vendor/**/Test/
vendor/sabre/*/examples/
# Exclude dev dependencies
vendor/bin/pdepend
vendor/bin/php-parse
vendor/bin/phpcbf
vendor/bin/phpcs
vendor/bin/phpmd
vendor/bin/phpunit
vendor/composer/pcre/
vendor/composer/xdebug-handler/
vendor/dms/
vendor/doctrine/
vendor/myclabs/
vendor/nikic/
vendor/pdepend/
vendor/phar-io/
vendor/php-mock/
vendor/phpmd/
vendor/phpunit/
vendor/psr/container/
vendor/sebastian/
vendor/squizlabs/
vendor/symfony/config/
vendor/symfony/dependency-injection/
vendor/symfony/deprecation-contracts/
vendor/symfony/filesystem/
vendor/symfony/polyfill-ctype/
vendor/symfony/polyfill-mbstring/
vendor/symfony/polyfill-php80/
vendor/symfony/service-contracts/
vendor/theseer/
# /info is a directory containing site-specific HTML documents
/info/

View File

@@ -1,10 +1,3 @@
# Select image from https://hub.docker.com/_/php/
#image: php:7.3
# Use a prepared Hubzilla image to optimise pipeline duration
# image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
image: php:8.0
stages:
- test
- deploy
@@ -24,6 +17,7 @@ variables:
# Ignore a Composer warning
COMPOSER_ALLOW_SUPERUSER: 1
# Configure MySQL/MariaDB service (https://hub.docker.com/_/mysql/, https://hub.docker.com/_/mariadb/)
DB_HOST: mysql
MYSQL_DATABASE: hello_world_test
MYSQL_ROOT_PASSWORD: mysql
# Configure PostgreSQL service (https://hub.docker.com/_/postgres/)
@@ -33,59 +27,69 @@ variables:
before_script:
# pecl and composer do not work with PHP production restrictions (from Hubzilla Docker image)
- if [ -f /usr/local/etc/php/conf.d/z_prod.ini ]; then mv /usr/local/etc/php/conf.d/z_prod.ini /usr/local/etc/php/conf.d/z_prod.ini.off; fi
# Install & enable Xdebug for code coverage reports
- pecl install xdebug
- apt-get update
- apt-get install zip unzip libjpeg-dev libpng-dev -yqq
- docker-php-ext-enable xdebug
- docker-php-ext-install gd
# Install composer
- curl -sS https://getcomposer.org/installer | php
# Install dev libraries from composer
- php ./composer.phar install --no-progress
# php.ini settings
- echo 'xdebug.mode=coverage' >> /usr/local/etc/php/php.ini
# hidden job definition with template for PHP
.job_template_php: &job_definition_php
stage: test
script:
- vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-text
# Install & enable Xdebug for code coverage reports
- apt-get update
- apt-get install -yqq libicu-dev libjpeg-dev libpng-dev libpq-dev libyaml-dev libzip-dev mariadb-client postgresql-client unzip zip
- pecl install xdebug yaml
- docker-php-ext-enable xdebug yaml
- docker-php-ext-install gd bcmath intl pdo_mysql pdo_pgsql zip
# Install composer
- curl -sS https://getcomposer.org/installer | php
# Install dev libraries from composer
- php ./composer.phar install --no-progress
# php.ini settings
- echo 'xdebug.mode=coverage' >> /usr/local/etc/php/php.ini
# hidden job definition with template for MySQL/MariaDB
#.job_template_mysql: &job_definition_mysql
# stage: test
# script:
# - echo "USE $MYSQL_DATABASE; $(cat ./install/schema_mysql.sql)" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
# - echo "SHOW DATABASES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
# - echo "USE $MYSQL_DATABASE; SHOW TABLES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
# - vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-text
.job_template_mysql: &job_definition_mysql
stage: test
variables:
HZ_TEST_DB_HOST: $DB_HOST
HZ_TEST_DB_TYPE: mysql
HZ_TEST_DB_USER: root
HZ_TEST_DB_PASS: $MYSQL_ROOT_PASSWORD
HZ_TEST_DB_DATABASE: $MYSQL_DATABASE
script:
# Import hubzilla's DB schema
- echo "USE $MYSQL_DATABASE; $(cat ./install/schema_mysql.sql)" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host="$DB_HOST" "$MYSQL_DATABASE"
# Show databases and relations/tables of hubzilla's database
- echo "SHOW DATABASES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host="$DB_HOST" "$MYSQL_DATABASE"
- echo "USE $MYSQL_DATABASE; SHOW TABLES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host="$DB_HOST" "$MYSQL_DATABASE"
# Run the actual tests
- touch dbfail.out
- vendor/bin/phpunit --configuration tests/phpunit.xml --verbose --stop-on-error --coverage-text --colors=never --log-junit tests/results/junit.xml || exit_code=$?
- if [ $exit_code -ne 0 ]; then echo "Test barfed!"; cat dbfail.out; exit $exit_code; fi
coverage: '/^\s*Lines:\s*\d+.\d+\%/'
# hidden job definition with template for PostgreSQL
#.job_template_postgres: &job_definition_postgres
# stage: test
# services:
# - postgres:latest
# script:
# - export PGPASSWORD=$POSTGRES_PASSWORD
# - psql --version
# - psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT VERSION();"
# Import hubzilla's DB schema
# - psql -h "postgres" -U "$POSTGRES_USER" -v ON_ERROR_STOP=1 --quiet "$POSTGRES_DB" < ./install/schema_postgres.sql
# Show databases and relations/tables of hubzilla's database
#- psql -h "postgres" -U "$POSTGRES_USER" -l
#- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt;"
# Run the actual tests
# - vendor/bin/phpunit --configuration tests/phpunit-pgsql.xml --testdox
.job_template_postgres: &job_definition_postgres
stage: test
variables:
HZ_TEST_DB_HOST: postgres
HZ_TEST_DB_TYPE: postgres
HZ_TEST_DB_USER: $POSTGRES_USER
HZ_TEST_DB_PASS: $POSTGRES_PASSWORD
HZ_TEST_DB_DATABASE: $POSTGRES_DB
script:
- export PGPASSWORD=$POSTGRES_PASSWORD
- psql --version
- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT VERSION();"
# Import hubzilla's DB schema
- psql -h "postgres" -U "$POSTGRES_USER" -v ON_ERROR_STOP=1 --quiet "$POSTGRES_DB" < ./install/schema_postgres.sql
# Show databases and relations/tables of hubzilla's database
- psql -h "postgres" -U "$POSTGRES_USER" -l
- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt;"
# Run the actual tests
- touch dbfail.out
- vendor/bin/phpunit --configuration tests/phpunit.xml --verbose --stop-on-error --coverage-text --colors=never --log-junit tests/results/junit.xml || exit_code=$?
- if [ $exit_code -ne 0 ]; then echo "Test barfed!"; cat dbfail.out; exit $exit_code; fi
coverage: '/^\s*Lines:\s*\d+.\d+\%/'
# hidden job definition with artifacts config template
.artifacts_template:
artifacts: &artifacts_template
.artifacts_template: &artifacts_template
artifacts:
expire_in: 1 week
# Gitlab should show the results, but has problems parsing PHPUnit's junit file.
reports:
@@ -96,54 +100,30 @@ before_script:
- tests/results/
# PHP8.0
php8.0:
<<: *job_definition_php
# PHP8.1 with MySQL 8.0
php8.1_mysql8.0.22:
image: php:8.1
services:
- mysql:8.0
<<: *job_definition_mysql
<<: *artifacts_template
# PHP8.0 with MySQL 5.7
#php8.0_mysql5.7:
# <<: *job_definition_mysql
# services:
# - mysql:5.7
# PHP8.1 with MariaDB 10.6
php8.1_mariadb10.6:
image: php:8.1
services:
- name: mariadb:10.6
alias: mysql
<<: *job_definition_mysql
<<: *artifacts_template
# PHP8.0 with MySQL 8 (latest)
#php8.0_mysql8:
# <<: *job_definition_mysql
# services:
# - name: mysql:8
# command: ["--default-authentication-plugin=mysql_native_password"]
# PHP8.0 with MariaDB 10.2
#php8.0_mariadb10.2:
# <<: *job_definition_mysql
# services:
# - name: mariadb:10.2
# alias: mysql
# PHP8.0 with MariaDB 10.3 (latest)
#php8.0_mariadb10.3:
# <<: *job_definition_mysql
# image: php:8.0
#image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
# services:
# - name: mariadb:10.3
# alias: mysql
# PHP7.3 with PostgreSQL latest (11)
#php7.3_postgres11:
# <<: *job_definition_postgres
# artifacts: *artifacts_template
# PHP7.3 with PostgreSQL latest (11)
#php7.3_postgres11:
# <<: *job_definition_postgres
# image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
# artifacts: *artifacts_template
# PHP8.1 with PostgreSQL 12
php8.1_postgres12:
image: php:8.1
services:
- postgres:12-alpine
<<: *job_definition_postgres
<<: *artifacts_template
# Generate Doxygen API Documentation and deploy it as GitLab pages

View File

@@ -25,10 +25,10 @@ AddType audio/ogg .oga
# in CGI mode.
RewriteCond %{REQUEST_URI} ^/\.well\-known/.*
RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
RewriteRule ^(.*)$ index.php?q=$1 "[E=REMOTE_USER:%{HTTP:Authorization},L,QSA,B= ?]"
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
RewriteRule ^(.*)$ index.php?q=$1 "[E=REMOTE_USER:%{HTTP:Authorization},L,QSA,B= ?]"
</IfModule>

635
CHANGELOG
View File

@@ -1,3 +1,638 @@
Hubzilla 9.0.2 (2024-06-07)
- Fix buttons in event viewer
- Fix some PHP warnings and errors
- Fix issue when inReplyTo field is an array
- Fix possible queueworker crash
- Fix missing pdl file for mod home
- Reduced default directory result set
- Fix fatal error in likebanner addon
- Fix fatal error in hilite addon
Hubzilla 9.0.1 (2024-03-26)
- Fix an issue where after an update initiated from a modal the modal backdrop would remain
- Fix bootstrap namespace in conv list templates
- Fix link to delivery report in conv list templates
- Slightly improved handling of linefeeds in some bbcode block elements and added tests
- Fix categories_widget() cache not being observer aware
- Allow to run additional site specific commands at the end of util/udall in util/udall_extra
- Fix linefeeds in table and list content removed
- Pubcrawl: do not attrmpt to sign wall to wall messages - they will appear misattributed in mastodons
- Pubcrawl: default to Note activity type for now
Hubzilla 9.0 (2024-03-22)
- Refactor browser to browser encryption based on sodium plus library
- Added developer docs for the refactored test system
- Move escape_tags() to Lib/Text::escape_tags() and add test
- Messages are now sent as articles instead of notes - this can be configured for activitypub
- Implement support for custom emojis
- Add test for Lib/Activity::get_textfield()
- Refactor mod things to be AS2 compliant
- Implement basic bbcode tests and minor refactor
- Refactor profile activities to be AS2 complient
- Removed poke and moods app
- Cleanup deprecated/unused activity types
- Update doxygen config for generating online API docs
- Make DBA driver transaction aware
- Deprecate internal usage of ActivityStreams1 in favor of ActivityStreams2
- Introduce Lib/Activity::get_actor() force flag to omit cache
- Refactor mod contactedit refresh
- Require intl PHP extension
- Improved checks in Web/HTTPSig::find_headers()
- Implement custom sass bootstrap builds for channels and site
- Mark items verified in zot delivery if either JSalmon, LDSignature or EddsaSignature verified
- Added support for code blocks with language in markdown and html
- Improved conversation item design
- Start using uuid for internal reference instead of base64 encoded mid
- Store seen mids in session instead of cache
- Increase sess_data DB column to medium text
- Introduce Lib/Activity::init_background_fetch()
- Refactor zotconvo daemon
- Implement short time object cache to reduce network calls (performance)
- Refactor Lib/Activity::fetch_and_store_parents()
- Introduce the fetchparents daemon
- Refactor Libzot::process_delivery()
- Start processing source xchan in xchan_query()
- Added CI job for MariaDB 10.6
- Store the original announce actor (the one that pushed the item into our stream first) in source_xchan instead of owner_xchan to preserve the original owner
- Added optional circle person avatar
- Added min supported DB backends to administrator docs: MySql v >= 8.0.22, MariaDB v >= 10.6, PostgreSql v >= 12
- Added CI job for MySql 8.0
- Improved validate_email()
- Implement fep-8b32 - object integrity proofs
- Implement native repeats
- Updated spanish strings
- Add tests for check_account_email()
- Vastly improved unit tests including the database
- Require sodium PHP extension
- Require bcmath or gmp PHP extension
- Deprecate simplepie idna_convert()
- Update apache rewite rule to fix issue with recent apache versions - issue #1822
- Display selected mid in an open state - issue #1425
- Add bookmark and category to AP schema
Bugfixes
- Fix cover photos not uploaded into folder due to missing source option
- Fix regression where config returned default value in some cases
- Fix attachments listed in reverse order
- Fix unterminated entity reference error when dealing with domxpath and add a test
- Fix obsolete system language selector in admin/site
- Fix imagick readImageBlob() exception not handled
- Fix content not moved to new location if folder was renamed via webdav
- Fix bootstrap namespaces not up-to-date in htmlpurifier
- Fix inReplyTo field in Lib/Activity not dealing with arrays
- Fix round buttons not being round
- Fix import from ical if timezone was not set in the source data
- Fix hard linebreaks from markdown and html not preserved in bbcode conversion
- Fix indentation from markdown and html not preserved in bbcode conversion
- Fix images with alt text from markdown and not preserved in bbcode conversion
- Fix custom emoji reactions arriving from pleroma
- Fix issue where if an item is created and deleted again before the notifier has completed the queueworker will dismiss the delete because it looks like a duplicate entry
- Fix handling HTML entities via mbstring is deprecated
- Fix various PHP deprecation warnings
- Fix apache rewite rule to fix issue with recent apache versions - issue #1822
- Fix display selected mid in an open state - issue #1425
Addons
- Removed smileybutton addon
- Removed smiley_pack addon
- Pubcrawl: refactor presentation of encrypted messages
- Removed deprecated cryptojs addon
- Removed emojione addon
- New addon emoji which can provide different emoji sets via config.system.emoji_set variable - emojitwo (default), openmoji, mutant are currently supported
- Removed addon moremoods
- Removed addon morepokes
- Pubcrawl: implement actor_refetch hook
- Diaspora: implement actor_refetch hook
- Navbanner_options: fix PHP warnings
- Pubcrawl: add assertionMethod to encode_person()
- Socialauth: cleanup unused files
- Openstreetmap: adjust URLs
Hubzilla 8.8.8 (2024-02-29)
- Streams compatibility fixes
Hubzilla 8.8.7 (2024-01-19)
- Fix regression in Activity::actor_store()
Hubzilla 8.8.6 (2024-01-11)
- Provide more builtin jsonld files
- Development branch compatibility in Libsync
Hubzilla 8.8.5 (2024-01-01)
- Fix possible loop if DB is not reachable (introduced in 8.8.3)
- Fix some errors and deprecation warnings with PHP 8.2
- Deprecate simplepie idna_convert in favor of PHP native function
- Fix double processed quoted strings in get_tags()
Hubzilla 8.8.4 (2023-12-20)
- Fix regression introduced in version 8.8.3
- Add test for Lib/Config
- Add active addons and blocked sites to siteinfo
Hubzilla 8.8.3 (2023-12-17)
- Check return from Config::Load() and retry on failure
- Libzot::import() do not prozess items where we could not fetch the author
- Translation updates for Norwegian Bokmål (nb_NO)
- Add the app terms before syncing, otherwise the terms will be reset at the other end
- Addon statistics: deprecate nodeinfo 1.0 and implement nodeinfo 2.1
- Addon cards: fix PHP error
Hubzilla 8.8.2 (2023-12-06)
- Fix missing includes - issue #1820
- Addon logger_stats: improved performance reading big log files
Hubzilla 8.8.1 (2023-11-27)
- Fix error in cards addon
- Fix error in articles addon
- Fix double left and right template css
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
- Implement notification exception for forum posts repeated by group actors
- Updated es translations
- Rewrite totp multifactor auth and move it from addon to core (ported from streams)
- Implement page load progress indicator for pwa standalone mode
- Improved mod HQ logic to save some DB lookups
- Default owner_xchan to sender in Activity::store() except for fetched items
- Improved contact search
- Do not force new thread if announce comes from group actor
- Disable oembed in notes app
- Improved queue handling
- Slightly restructure conv item head
- Implemet author images in HQ widget
- Implement author filter in HQ widget
- Add config option db_skip_locked_supported which should be set if the DB backend supports skip locked
- Updated simple pie library
- Updated smarty library
- Updated forkawesome library
- Updated fullcalendar library
- Implement native dark/light mode in favour of dark/light schema
- Updated bootstrap library
Bugfixes
- Fix channel calendar location html not interpreted - issue #1728
- Fix max oembed size check if content length header is an array
- Fix group actor wall posts turned into direct messages when posting article or card
- Fix non zot profile mentions using zrl tag
- Fix message filter > and < not decoded
- Fix deleted hublocs included in author lookup
- Fix some more PHP warnings
- Fix syntax for get_compund_property()
- Fix xchan_pubforum not set on actor updates
- Fix duplicate directory entries for xchans with bogus second primary entry
- Fix missing created timestamp in like activity - issue #1729
- Fix messages not signed when posting from non primary locations
- Fix pinned post regression
- Fix autocomplete items not selectable on mobile
- Fix hubloc confusion in Libzot::fetch_conversation()
- Fix valid duplicate notification entries deduplicated
- Fix ics file import
- Fix recipients deduplication in some places
- Fix hashtag encoded with href instead of id
Addons
- Pubcrawl: re-implement encrypted content which got lost in transition
- Pubcrawl: flag fetched items
- Totp: removed from addons in favor of implementation in core
- Pubcrawl: fix delivery issues for relayed activities
- Cart: fix missing bootstrap namespace
- Gallery: do not inject gallery code in webpages
- Pubcrawl: fix sql error if mentions string is empty
- Cart: fix paypal order hash size
Hubzilla 8.0 (2023-01-13)
- Updated ru strings
- Implement ability to edit addon PDL with pdledit_gui and pdledit
- Implement queueworker auto sleep time
- Always add sys channel to receivers for public items
- Improved server sent events loop
- Exclude not tagable xchan networks handle_tag()
- Add mark html tag to the html2bbcode parser
- Embed or attach uploaded files depending on file type
- Changed logic to enable site only public stream - please revisit admin setting
- Updated nb-no strings
- Moved queueworker to core
- Provide a PDL file for mod invite and set the profile
- Disabled outdated context help
- Mark unseen items seen after a certain amount of time (default 90 days)
- Slightly restructure lib webfinger
- Improved redbasic dark schema
- Implement unseen thread and unseen items count in HQ widget
- In unseen items notifications just count the first 99 and display 99+ if there are more
Bugfixes
- Fix race conditions when processing multiple choice polls
- Fix affinity slider updates - issue #1714
- Fix issue where accounts created with a did2 could change their password
- Fix no message displayed if file not found in mod cloud
- Fix pubstream tagcloud unthreaded view
- Fix french invite template
- Fix comment permission issue in site only public stream
- Fix privacy tag not referring to latest hubloc entry
- Fix selected item not highlighted
- Fix poll issue when special chars and spaces are involved
- Fix prune_hub_reinstalls() to only care about zot6 hublocs
- Fix redis session PHP warnings
- Fix remote visitor photo uploads
- Fix mod shredwithme not showing any items
- Fix api_auth not referring to latest hubloc entry
- Fix category widget URLs
- Fix poller always polling broken feeds
- Fix sse event always triggered if public stream notification are off or the app is not installed
- Fix more PHP8 warnings
- Fix wrong variable in tag_deliver()
- Fix mod follow use trim() after punify() - issue #1698
Addons
- Cards: update widget info
- Articles: update widget info
- Wiki: update widget info
- Sse: filter apporvals
- Cards: use html_entity_decode before purify and html2plain for summary
- Articles: use html_entity_decode before purify and html2plain for summary
- Wiki: use html_entity_decode before purify and html2plain for summary
- Cards: fix comments not displayed if filter by category
- Articles: fix comments not displayed if filter by category
- Sse: respect the site public stream setting
- Queueworker: moved to core
- Pubcrawl: move db query out of foreach loop
- Pubcrawl: add mentions and thread owner to recipients for public items
Hubzilla 7.8.7 (2022-12-03)
- Fix regression when adding feed contacts
- Fix regression new channel calendar event not created
Hubzilla 7.8.6 (2022-11-14)
- Fix typo in boot.php
Hubzilla 7.8.5 (2022-11-13)
- Fix outbound edit activity not of type update
- Fix mod display not falling through to fetch public item
- Fix more PHP warnings
- Fix regression in items_fetch() which resulted in empty atom feed
- Pubcrawl: cleanup and slightly restructre mod inbox
Hubzilla 7.8.4 (2022-11-09)
- Fix new uuid created when editing a post
Hubzilla 7.8.3 (2022-11-07)
- Fix regression where auto created directories were not created with public permissions
- Fix regression where pinned/featured state of apps was not displayed correctly
Hubzilla 7.8.2 (2022-11-05)
- Pubcrawl: fix regression in inbox
- Fix display issue of shares coming from streams
- Throw a 404 if we could not determine which channel to load
- If we have a cached xchan/hubloc entry, make sure we fetch the latest
- Gallery: paint the background grid with css
Hubzilla 7.8.1 (2022-10-26)
- Silence tons of PHP warnings in core
- Catch decryption failure edgecase in receiver
- Deal with conversation privacy mismatches in Activity::store()
- Composer libs updates
- Fix timeago strings not always translated
- Fix edit link regression in cards addon
- Fix edit link regression in article addon
Hubzilla 7.8 (2022-10-10)
- Updated spanish translations
- Always update hubloc_updated timestamp if a hubloc is updated
- Do better with re-installs in various situations
- Update htconfig templates
- Emit an info if an item is deleted manually (issue #1691)
- Updated german translations
- Make Activity::actor_store() fetch the actor object if none is provided
- Check for various forms of as:Public for compatibility
- Cleanup dark schema
- Make use of CSS variables in redbasic
- Implement link hover color in redbasic
- Update to bootstrap version 5.2 which implements CSS variables
Bugfixes
- Fix stream filter for polls and events does not work anymore (issue #1694)
- Fix item menu display issue
- Fix HQ widget displaying superblocked items
- Fix mod poke
- Fix link to article or card not processed correctly if umlauts are involved (issue #1687)
- Fix mod siteinfo containing a dead link (issue #1690)
- Fix permission issue when displaying things (issue #1686).
- Fix check for existing profiles (issue #1688)
- Fix modal missing for conversation settings
- Fix missing closing div tag if there are no recent channel activities
- Fix issue where an unkown diaspora author was not imported if the comment arrived via a relayed activity
- Fix mangled xchan_url due to escape_tags()
- Fix the AP url not decode bin mod search
- Fix some php warnings
Addons
- Wiki: move create_missing_page() from widget to module
- Superblock: implement blocking for messages widget_item
- Diaspora: fix verification of relayed comments and likes
- Pubcrawl: make sure to store the attributedTo actor in announce activities
- Diaspora: fix issue where an unkown author was not imported if the comment arrived via a relayed activity
Hubzilla 7.6.1 (2022-08-07)
Bugfixes
- Fix attachments displayed in visible response activities
- Fix wrong attribution in unseen like notifications
Addons
- Cards: fix widget not implemented via pdl file (requires re-install)
- Articles: fix widget not implemented via pdl file (requires re-install)
- Wiki: fix widget not implemented via pdl file (requires re-install)
Hubzilla 7.6 (2022-07-26)
- Add filter rule to check for false condition
- Implement HQ dashboard to display recently created content for various modules
- Updated spanish translations
- Implement a max oembed size which defaults to 1MB
- Update composer libs
Addons
- Cart: do not attempt oembed
- Cards: implement channel_activities_widget for HQ dashboard
- Articles: implement channel_activities_widget for HQ dashboard
- Wiki: implement channel_activities_widget for HQ dashboard
Bugfixes
- Fix language filter filtering ambigous results
- Fix vcard-card background for dark schema
- Fix contact edit dialog not displayed in chrome browser
- Fix readability of category pills in dark schema
- Fix opengraph images inside zmg opening tag
- Fix oembed attempted for text previews
Hubzilla 7.4 (2022-06-01)
- Updated russian translations
- Raise min PHP version to 8.0
- Rewrite inbound attachment handling
- Move photo flag feature from addon to core
- Adjust default production php logging
- Update composer libs
- Add a hidden config to enable the hs2019 http signature algorithm
- Allow starring of pubstream items
- Update spanish translations
- Add the title in forum post reshares if applicable
- Implement inbound pleroma reactions
- Add real name info to the navbar template data
- Add the updated date to the icon url so that other platforms will pick it up on change
- Move wiki from core to addon
- Move articles from core to addon
- Move cards from core to addon
Addons
- Rendezvous: add missing default value to sql schema
- Wiki: moved from core to addons
- Articles: moved from core to addons
- Cards: moved from core to addons
- Photoflag: moved to core
- Sse: fix issue where notifications were emited for created tasks
Bugfixes
- Fix issue where inbound activitypub items lost image descriptions (issue 1679)
- Fix issue where observer tags were not rendered correctly in event items (issue 1674)
- Fix forum posts leaked into network stream
- Fix tags not found in search if not logged in (issue 1677)
- Fix dislikes causing stuck notifications (issue 1676)
Hubzilla 7.2.2 (2022-04-26)
- Fix item_verified not set due to data structure changes
Hubzilla 7.2.1 (2022-04-25)
- Fix changing profile image from new member widget - issue #1671
- Fix regression with incoming poll answers from activitypub introduced in 7.2
- Fix addons not removed from the DB when removed from the filesystem
- Fix regression in attaching images for activitypub introduced in 7.2
- Move activitypub addressing from core to the pubcrawl addon
- Fix hub re-install issues
- Fediwordle: slightly improved algorithm
Hubzilla 7.2 (2022-03-29)
- Streamline comment policy with downstream project
- Add new function is_local_url()

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,12 @@ 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'] ?? [];
$arr['group_deny'] = $arr['group_deny'] ?? [];
$this->allow_cid = perms2str((is_array($arr['contact_allow']))
? $arr['contact_allow'] : explode(',', $arr['contact_allow']));
$this->allow_gid = perms2str((is_array($arr['group_allow']))
@@ -156,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

@@ -7,6 +7,7 @@ class Addon {
static public function run($argc, $argv) {
call_hooks('daemon_addon', $argv);
return;
}

View File

@@ -19,8 +19,10 @@ class Cache_embeds {
$item = $c[0];
// bbcode conversion by default processes embeds that aren't already cached.
// Ignore the returned html output.
// Ignore the returned html output.
bbcode($item['body']);
return;
}
}

View File

@@ -11,6 +11,7 @@ class Cache_query {
if(! $argc == 3)
return;
$r = null;
$key = $argv[1];
$pid = get_config('procid', $key, false);
@@ -24,13 +25,17 @@ class Cache_query {
array_shift($argv);
array_shift($argv);
$arr = json_decode(base64_decode($argv[0]), true);
$r = call_user_func_array('q', $arr);
if($r)
if(is_array($r)) {
Cache::set($key, serialize($r));
}
del_config('procid', $key);
return;
}
}

View File

@@ -10,6 +10,9 @@ class Checksites {
logger('checksites: start');
$site_id = '';
$sql_options = '';
if (($argc > 1) && ($argv[1]))
$site_id = $argv[1];

View File

@@ -9,6 +9,7 @@ class Cli_suggest {
static public function run($argc,$argv) {
update_suggestions();
return;
}
}

View File

@@ -30,6 +30,7 @@ class Convo {
intval($channel_id),
dbesc($contact_hash)
);
if (!$r) {
return;
}
@@ -40,19 +41,26 @@ class Convo {
$messages = $obj->get();
if ($messages) {
foreach ($messages as $message) {
if (is_string($message)) {
$message = Activity::fetch($message, $channel);
}
// set client flag because comments will probably just be objects and not full blown activities
// and that lets us use implied_create
$AS = new ActivityStreams($message);
if ($AS->is_valid() && is_array($AS->obj)) {
$item = Activity::decode_note($AS);
Activity::store($channel, $contact['abook_xchan'], $AS, $item);
}
if (!$messages) {
return;
}
foreach ($messages as $message) {
if (is_string($message)) {
$message = Activity::fetch($message, $channel);
}
// set client flag because comments will probably just be objects and not full blown activities
// and that lets us use implied_create
$AS = new ActivityStreams($message);
if ($AS->is_valid() && is_array($AS->obj)) {
$item = Activity::decode_note($AS);
$item['item_fetched'] = true;
Activity::store($channel, $contact['abook_xchan'], $AS, $item);
}
}
return;
}
}

View File

@@ -3,6 +3,7 @@
namespace Zotlabs\Daemon;
use Zotlabs\Lib\Libsync;
use Zotlabs\Lib\Libzotdir;
class Cron {
@@ -19,6 +20,7 @@ class Cron {
}
}
/*
// Check for a lockfile. If it exists, but is over an hour old, it's stale. Ignore it.
$lockfile = 'store/[data]/cron';
if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 3600))
@@ -30,9 +32,21 @@ class Cron {
// Create a lockfile. Needs two vars, but $x doesn't need to contain anything.
$x = '';
file_put_contents($lockfile, $x);
*/
logger('cron: start');
// 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'));
@@ -50,7 +64,7 @@ class Cron {
require_once('include/account.php');
remove_expired_registrations();
$interval = get_config('system', 'delivery_interval', 3);
$interval = get_config('queueworker', 'queue_interval', 500000);
// expire any expired items
@@ -65,8 +79,10 @@ class Cron {
if ($rr['item_wall']) {
// The notifier isn't normally invoked unless item_drop is interactive.
Master::Summon(['Notifier', 'drop', $rr['id']]);
if ($interval)
@time_sleep_until(microtime(true) + (float)$interval);
if ($interval) {
usleep($interval);
}
}
}
}
@@ -96,8 +112,10 @@ class Cron {
if ($r) {
foreach ($r as $rr) {
Master::Summon(array('Directory', $rr['channel_id'], 'force'));
if ($interval)
@time_sleep_until(microtime(true) + (float)$interval);
if ($interval) {
usleep($interval);
}
}
}
@@ -106,13 +124,13 @@ class Cron {
$r = q("SELECT DISTINCT xchan, content FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
intval(PHOTO_CACHE),
db_utcnow(),
db_quoteinterval(get_config('system', 'active_expire_days', '30') . ' DAY')
db_quoteinterval(get_config('system', 'cache_expire_days', 7) . ' DAY')
);
if ($r) {
q("DELETE FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
intval(PHOTO_CACHE),
db_utcnow(),
db_quoteinterval(get_config('system', 'active_expire_days', '30') . ' DAY')
db_quoteinterval(get_config('system', 'cache_expire_days', 7) . ' DAY')
);
foreach ($r as $rr) {
$file = dbunescbin($rr['content']);
@@ -151,8 +169,10 @@ class Cron {
);
}
Master::Summon(array('Notifier', 'wall-new', $rr['id']));
if ($interval)
@time_sleep_until(microtime(true) + (float)$interval);
if ($interval) {
usleep($interval);
}
}
}
}
@@ -203,10 +223,10 @@ class Cron {
}
// pull in some public posts
// pull in some public posts if allowed
$disable_discover_tab = get_config('system', 'disable_discover_tab') || get_config('system', 'disable_discover_tab') === false;
if (!$disable_discover_tab)
$disable_externals = get_config('system', 'disable_discover_tab') || get_config('system', 'disable_discover_tab') === false || get_config('system', 'site_firehose');
if (!$disable_externals)
Master::Summon(['Externals']);
$restart = false;
@@ -228,7 +248,7 @@ class Cron {
set_config('system', 'lastcron', datetime_convert());
//All done - clear the lockfile
@unlink($lockfile);
//@unlink($lockfile);
return;
}

View File

@@ -49,10 +49,26 @@ class Cron_daily {
dbesc('sse_id.%')
);
// Clean up emdedded content cache
// Mark items seen after X days (default 90)
$r = dbq("select channel_id from channel where channel_removed = 0");
if ($r) {
foreach ($r as $rr) {
$mark_seen_days = get_pconfig($rr['channel_id'], 'system', 'mark_seen_days', 90);
q("UPDATE item SET item_unseen = 0 WHERE
uid = %d AND item_unseen = 1
AND created < %s - INTERVAL %s",
intval($rr['channel_id']),
db_utcnow(),
db_quoteinterval($mark_seen_days . ' DAY')
);
}
}
// Clean up cache
q("DELETE FROM cache WHERE updated < %s - INTERVAL %s",
db_utcnow(),
db_quoteinterval(get_config('system', 'active_expire_days', '30') . ' DAY')
db_quoteinterval(get_config('system', 'cache_expire_days', 7) . ' DAY')
);
//update statistics in config
@@ -78,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'));
@@ -103,5 +108,7 @@ class Cron_daily {
/**
* End Cron Daily
*/
return;
}
}

View File

@@ -22,12 +22,12 @@ class Cron_weekly {
mark_orphan_hubsxchans();
// Find channels that were removed in the last three weeks, but
// Find channels that were removed in the last three weeks, but
// haven't been finally cleaned up. These should be older than 10
// days to ensure that "purgeall" messages have gone out or bounced
// or timed out.
// days to ensure that "purgeall" messages have gone out or bounced
// or timed out.
$r = q("select channel_id from channel where channel_removed = 1 and
$r = q("select channel_id from channel where channel_removed = 1 and
channel_deleted > %s - INTERVAL %s and channel_deleted < %s - INTERVAL %s",
db_utcnow(), db_quoteinterval('21 DAY'),
db_utcnow(), db_quoteinterval('10 DAY')
@@ -59,5 +59,6 @@ class Cron_weekly {
* End Cron Weekly
*/
return;
}
}
}

View File

@@ -28,6 +28,8 @@ class Deliver {
}
return;
}
}

View File

@@ -12,8 +12,12 @@ class Deliver_hooks {
$r = q("select * from item where id = '%d'",
intval($argv[1])
);
if ($r)
if ($r) {
call_hooks('notifier_normal', $r[0]);
}
return;
}
}

View File

@@ -97,5 +97,7 @@ class Directory {
if ($pushall) {
Master::Summon(array('Notifier', 'refresh_all', $channel['channel_id']));
}
return;
}
}

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(),
@@ -44,8 +43,8 @@ class Expire {
logger('expire: start with pid ' . $pid, LOGGER_DEBUG);
$site_expire = intval(get_config('system', 'default_expire_days'));
$commented_days = intval(get_config('system', 'active_expire_days'));
$site_expire = intval(get_config('system', 'default_expire_days', 30));
$commented_days = intval(get_config('system', 'active_expire_days', 7));
logger('site_expire: ' . $site_expire);
@@ -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,12 +94,15 @@ 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);
}
del_config('procid', 'expire');
return;
}
}

View File

@@ -19,6 +19,7 @@ class Externals {
$importer = get_sys_channel();
$total = 0;
$attempts = 0;
$url = '';
logger('externals: startup', LOGGER_DEBUG);
@@ -67,9 +68,8 @@ class Externals {
datetime_convert('UTC', 'UTC', 'now - 30 days')
);
$contact = $r[0];
if ($contact) {
if ($r) {
$contact = $r[0];
$url = $contact['hubloc_id_url'];
}
}
@@ -133,7 +133,7 @@ class Externals {
continue;
}
$obj_id = isset($message['object']['id']) ?? $message['object'];
$obj_id = $message['object']['id'] ?? $message['object'];
Libzot::fetch_conversation($importer, $obj_id);
$total++;
@@ -143,7 +143,8 @@ class Externals {
$AS = new ActivityStreams($message);
if ($AS->is_valid() && is_array($AS->obj)) {
$item = Activity::decode_note($AS);
Activity::store($importer, $contact['abook_xchan'], $AS, $item);
$item['item_fetched'] = true;
Activity::store($importer, $contact['hubloc_hash'], $AS, $item);
$total++;
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace Zotlabs\Daemon;
use Zotlabs\Lib\Activity;
class Fetchparents {
static public function run($argc, $argv) {
logger('Fetchparents invoked: ' . print_r($argv, true));
if ($argc < 4) {
return;
}
$channels = explode(',', $argv[1]);
if (!$channels) {
return;
}
$observer_hash = $argv[2];
if (!$observer_hash) {
return;
}
$mid = $argv[3];
if (!$mid) {
return;
}
$force = $argv[4] ?? false;
foreach ($channels as $channel_id) {
$channel = channelx_by_n($channel_id);
Activity::fetch_and_store_parents($channel, $observer_hash, $mid, null, $force);
}
return;
}
}

View File

@@ -38,10 +38,9 @@ class Gprobe {
if ($url) {
$zf = Zotfinger::exec($url, null);
}
if (is_array($zf) && array_path_exists('signature/signer', $zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
Libzot::import_xchan($zf['data']);
if (is_array($zf) && array_path_exists('signature/signer', $zf) && $zf['signature']['signer'] === $url && intval($zf['signature']['header_valid'])) {
Libzot::import_xchan($zf['data']);
}
}
}

View File

@@ -11,6 +11,8 @@ class Importdoc {
self::update_docs_dir('doc/*');
return;
}
static public function update_docs_dir($s) {

View File

@@ -2,6 +2,8 @@
namespace Zotlabs\Daemon;
use Zotlabs\Lib\QueueWorker;
if (array_search(__file__, get_included_files()) === 0) {
require_once('include/cli_startup.php');
array_shift($argv);
@@ -9,6 +11,7 @@ if (array_search(__file__, get_included_files()) === 0) {
if ($argc)
Master::Release($argc, $argv);
return;
}
@@ -16,6 +19,10 @@ if (array_search(__file__, get_included_files()) === 0) {
class Master {
static public function Summon($arr) {
QueueWorker::Summon($arr);
return;
/*
$hookinfo = [
'argv' => $arr
];
@@ -32,11 +39,15 @@ class Master {
$phpbin = get_config('system', 'phpbin', 'php');
proc_run($phpbin, 'Zotlabs/Daemon/Master.php', $arr);
*/
}
static public function Release($argc, $argv) {
cli_startup();
QueueWorker::Release($argv);
return;
/*
$hookinfo = [
'argv' => $argv
];
@@ -54,5 +65,6 @@ class Master {
logger('Master: release: ' . json_encode($argv), LOGGER_ALL, LOG_DEBUG);
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
$cls::run($argc, $argv);
*/
}
}

View File

@@ -5,7 +5,6 @@ namespace Zotlabs\Daemon;
use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\Activity;
use Zotlabs\Lib\Queue;
use Zotlabs\Lib\LDSignatures;
require_once('include/html2plain.php');
require_once('include/conversation.php');
@@ -79,10 +78,7 @@ class Notifier {
static public $encoded_item = null;
static public $channel = null;
static public $private = false;
// $fragment can contain additional info to omit de-duplication in the queueworker.
// E.g. if an item is updated many times in a row from different sources (multiple vote updates) the
// update source mid or a timestamp or random string can be added.
static public $fragment = null;
static public function run($argc, $argv) {
@@ -107,10 +103,15 @@ class Notifier {
self::$encoded_item = null;
self::$channel = null;
self::$private = false;
self::$fragment = null;
$sys = get_sys_channel();
$normal_mode = true;
$upstream = false;
$uplink = false;
$target_item = null;
$parent_item = null;
$top_level_post = false;
$relay_to_owner = false;
if ($cmd === 'keychange') {
self::$channel = channelx_by_n($item_id);
@@ -227,8 +228,6 @@ class Notifier {
// Fetch the target item
self::$fragment = $argv[3] ?? '';
$r = q("SELECT * FROM item WHERE id = %d AND parent != 0",
intval($item_id)
);
@@ -271,14 +270,13 @@ class Notifier {
// Check for non published items, but allow an exclusion for transmitting hidden file activities
if (intval($target_item['item_unpublished']) || intval($target_item['item_delayed']) ||
intval($target_item['item_blocked']) ||
(intval($target_item['item_hidden']) && ($target_item['obj_type'] !== ACTIVITY_OBJ_FILE))) {
intval($target_item['item_blocked']) || intval($target_item['item_hidden'])) {
logger('notifier: target item not published, so not forwardable', LOGGER_DEBUG);
return;
}
// follow/unfollow is for internal use only
if (in_array($target_item['verb'], [ACTIVITY_FOLLOW, ACTIVITY_UNFOLLOW])) {
if (in_array($target_item['verb'], ['Follow', 'Ignore', ACTIVITY_FOLLOW, ACTIVITY_UNFOLLOW])) {
logger('not fowarding follow/unfollow note activity');
return;
}
@@ -300,6 +298,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;
@@ -337,14 +340,7 @@ class Notifier {
self::$encoded_item = json_decode($m, true);
}
else {
self::$encoded_item = array_merge(['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
]], Activity::encode_activity($target_item)
);
self::$encoded_item['signature'] = LDSignatures::sign(self::$encoded_item, self::$channel);
self::$encoded_item = Activity::build_packet(Activity::encode_activity($target_item), self::$channel, false);
}
logger('target_item: ' . print_r($target_item, true), LOGGER_DEBUG);
@@ -360,8 +356,6 @@ class Notifier {
// the hostname in the message_id and provides a second (fallback) opinion.
$relay_to_owner = (!$top_level_post && intval($target_item['item_origin']) && comment_local_origin($target_item));
$uplink = false;
$upstream = false;
// $cmd === 'relay' indicates the owner is sending it to the original recipients
// don't allow the item in the relay command to relay to owner under any circumstances, it will loop
@@ -379,6 +373,7 @@ class Notifier {
if (($relay_to_owner || $uplink) && ($cmd !== 'relay')) {
logger('notifier: followup relay', LOGGER_DEBUG);
// If the Parent item is an Announce the real owner is the parent author
$sendto = (($uplink) ? $parent_item['source_xchan'] : $parent_item['owner_xchan']);
self::$recipients = [$sendto];
self::$private = true;
@@ -411,9 +406,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']]));
}
@@ -505,6 +498,7 @@ class Notifier {
// public posts won't make it to the local public stream unless there's a recipient on this site.
// This code block sees if it's a public post and localhost is missing, and if so adds an entry for the local sys channel to the $hubs list
/* sys channel is now added in collect recipients
if (!self::$private) {
$found_localhost = false;
if ($hubs) {
@@ -525,6 +519,7 @@ class Notifier {
}
}
}
*/
if (!$hubs) {
logger('notifier: no hubs', LOGGER_NORMAL, LOG_NOTICE);
@@ -647,13 +642,14 @@ class Notifier {
// This shouldn't produce false positives on comment boosts that were generated on other platforms
// because we won't be delivering them.
if (isset($target_item) && isset($target_item['verb']) && $target_item['verb'] === 'Announce' && $target_item['author_xchan'] === $target_item['owner_xchan'] && ! intval($target_item['item_thread_top'])) {
if (isset($target_item['verb']) && $target_item['verb'] === 'Announce' && $target_item['author_xchan'] === $target_item['owner_xchan'] && ! intval($target_item['item_thread_top'])) {
continue;
}
$hash = new_uuid();
$env = (($hub_env && $hub_env[$hub['hubloc_site_id']]) ? $hub_env[$hub['hubloc_site_id']] : '');
$env = $hub_env[$hub['hubloc_site_id']] ?? '';
if ((self::$private) && (!$env)) {
continue;
}
@@ -690,11 +686,11 @@ class Notifier {
}
if ($normal_mode) {
if ($normal_mode && is_array($target_item)) {
// This wastes a process if there are no delivery hooks configured, so check this before launching the new process
$x = q("select * from hook where hook = 'notifier_normal'");
if ($x) {
Master::Summon(['Deliver_hooks', $target_item['id'], self::$fragment]);
Master::Summon(['Deliver_hooks', $target_item['id']]);
}
}

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) {
@@ -46,6 +42,7 @@ class Onepoll {
}
$contact = $contacts[0];
$importer_uid = $contact['abook_channel'];
$importer = channelx_by_n($importer_uid);
@@ -53,7 +50,7 @@ class Onepoll {
if (!$importer)
return;
logger("onepoll: poll: ({$contact['id']}) IMPORTER: {$importer['xchan_name']}, CONTACT: {$contact['xchan_name']}");
logger("onepoll: poll: ($contact_id) IMPORTER: {$importer['xchan_name']}, CONTACT: {$contact['xchan_name']}");
$last_update = ((($contact['abook_updated'] === $contact['abook_created']) || ($contact['abook_updated'] <= NULL_DATE))
? datetime_convert('UTC', 'UTC', 'now - 7 days')
@@ -63,12 +60,21 @@ class Onepoll {
if ($contact['xchan_network'] === 'rss') {
logger('onepoll: processing feed ' . $contact['xchan_name'], LOGGER_DEBUG);
$alive = handle_feed($importer['channel_id'], $contact_id, $contact['xchan_hash']);
if ($alive) {
q("update abook set abook_connected = '%s' where abook_id = %d",
if (!$alive) {
q("update abook set abook_updated = '%s' where abook_id = %d",
dbesc(datetime_convert()),
intval($contact['abook_id'])
);
return;
}
q("update abook set abook_updated = '%s', abook_connected = '%s' where abook_id = %d",
dbesc(datetime_convert()),
dbesc(datetime_convert()),
intval($contact['abook_id'])
);
return;
}
@@ -162,6 +168,7 @@ class Onepoll {
$AS = new ActivityStreams($message);
if ($AS->is_valid() && is_array($AS->obj)) {
$item = Activity::decode_note($AS);
$item['item_fetched'] = true;
Activity::store($importer, $contact['abook_xchan'], $AS, $item);
}
}

View File

@@ -17,21 +17,7 @@ class Poller {
}
}
$interval = intval(get_config('system', 'poll_interval'));
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);
$interval = get_config('queueworker', 'queue_interval', 500000);
logger('poller: start');
@@ -63,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,
@@ -72,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),
@@ -93,13 +84,24 @@ class Poller {
$min = intval(get_config('system', 'minimum_feedcheck_minutes'));
if (!$min)
$min = 60;
$x = datetime_convert('UTC', 'UTC', "now - $min minutes");
if ($c < $x) {
Master::Summon(['Onepoll', $contact['abook_id']]);
if ($interval)
@time_sleep_until(microtime(true) + (float)$interval);
if ($t !== $c) {
// if the last fetch failed only attempt fetch once a day
$min = 60 * 24;
}
$x = datetime_convert('UTC', 'UTC', "now - $min minutes");
if ($t < $x) {
Master::Summon(['Onepoll', $contact['abook_id']]);
if ($interval) {
usleep($interval);
}
}
continue;
}
if ($contact['xchan_network'] !== 'zot6')
@@ -158,20 +160,22 @@ class Poller {
continue;
Master::Summon(['Onepoll', $contact['abook_id']]);
if ($interval)
@time_sleep_until(microtime(true) + (float)$interval);
if ($interval) {
usleep($interval);
}
}
}
$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) {
@@ -181,19 +185,18 @@ class Poller {
if ($rr['ud_last'] > NULL_DATE)
if ($rr['ud_last'] > datetime_convert('UTC', 'UTC', 'now - 1 day'))
continue;
Master::Summon(['Onedirsync', $rr['ud_id']]);
if ($interval)
@time_sleep_until(microtime(true) + (float)$interval);
if ($interval) {
usleep($interval);
}
}
}
}
set_config('system', 'lastpoll', datetime_convert());
//All done - clear the lockfile
@unlink($lockfile);
return;
}
}

View File

@@ -7,77 +7,59 @@ use Zotlabs\Lib\Queue as LibQueue;
class Queue {
static public function run($argc, $argv) {
require_once('include/items.php');
require_once('include/bbcode.php');
if ($argc > 1)
$queue_id = $argv[1];
else
$queue_id = EMPTY_STR;
$queue_id = ($argc > 1) ? $argv[1] : '';
logger('queue: start');
// 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
$r = q("select outq_posturl from outq where outq_created < %s - INTERVAL %s",
db_utcnow(), db_quoteinterval('3 DAY')
$oldqItems = q("select outq_posturl, outq_hash from outq where outq_created < %s - INTERVAL %s",
db_utcnow(),
db_quoteinterval('3 DAY')
);
if ($r) {
foreach ($r as $rr) {
$h = parse_url($rr['outq_posturl']);
$desturl = $h['scheme'] . '://' . $h['host'] . (isset($h['port']) ? ':' . $h['port'] : '');
if ($oldqItems) {
foreach ($oldqItems as $qItem) {
$h = parse_url($qItem['outq_posturl']);
$site_url = $h['scheme'] . '://' . $h['host'] . ((!empty($h['port'])) ? ':' . $h['port'] : '');
q("update site set site_dead = 1 where site_dead = 0 and site_url = '%s' and site_update < %s - INTERVAL %s",
dbesc($desturl),
db_utcnow(), db_quoteinterval('1 MONTH')
dbesc($site_url),
db_utcnow(),
db_quoteinterval('1 MONTH')
);
}
$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)");
}
q("DELETE FROM outq WHERE outq_created < %s - INTERVAL %s",
db_utcnow(), db_quoteinterval('3 DAY')
);
$deliveries = [];
if ($queue_id) {
$r = q("SELECT * FROM outq WHERE outq_hash = '%s' LIMIT 1",
$qItems = q("SELECT * FROM outq WHERE outq_hash = '%s' LIMIT 1",
dbesc($queue_id)
);
logger('queue deliver: ' . $qItems[0]['outq_hash'] . ' to ' . $qItems[0]['outq_posturl'], LOGGER_DEBUG);
LibQueue::deliver($qItems[0]);
}
else {
// For the first 12 hours we'll try to deliver every 15 minutes
// After that, we'll only attempt delivery once per hour.
// This currently only handles the default queue drivers ('zot' or '') which we will group by posturl
// so that we don't start off a thousand deliveries for a couple of dead hubs.
// The zot driver will deliver everything destined for a single hub once contact is made (*if* contact is made).
// Other drivers will have to do something different here and may need their own query.
// Note: this requires some tweaking as new posts to long dead hubs once a day will keep them in the
// "every 15 minutes" category. We probably need to prioritise them when inserted into the queue
// or just prior to this query based on recent and long-term delivery history. If we have good reason to believe
// the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once
// or twice a day.
$sqlrandfunc = db_getfunc('rand');
$r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1",
$qItems = q("SELECT outq_hash FROM outq WHERE outq_scheduled < %s ",
db_utcnow()
);
while ($r) {
foreach ($r as $rv) {
LibQueue::deliver($rv);
}
$r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1",
db_utcnow()
);
}
}
if (!$r)
return;
foreach ($r as $rv) {
LibQueue::deliver($rv);
}
if ($qItems) {
foreach ($qItems as $qItem) {
$deliveries[] = $qItem['outq_hash'];
}
shuffle($deliveries);
do_delivery($deliveries, true);
}
}
}
}

View File

@@ -73,5 +73,7 @@ class Thumbnail {
|| (filectime(dbunescbin($attach['content']) . 'thumb') < (time() - 60)))) {
$default_controller->Thumb($attach, $preview_style, $preview_width, $preview_height);
}
return;
}
}

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,37 @@
<?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;
}
$channels = explode(',', $argv[1]);
if (!$channels) {
return;
}
$mid = $argv[2];
if (!$mid) {
return;
}
$force = $argv[3] ?? false;
foreach ($channels as $channel_id) {
$channel = channelx_by_n($channel_id);
Libzot::fetch_conversation($channel, $mid, $force);
}
return;
}
}

33
Zotlabs/Lib/ASCache.php Normal file
View File

@@ -0,0 +1,33 @@
<?php /** @file */
namespace Zotlabs\Lib;
/**
* A wrapper for the cache api
*/
class ASCache {
public static function isEnabled() {
return Config::Get('system', 'as_object_cache_enabled', true);
}
public static function getAge() {
return Config::Get('system', 'as_object_cache_time', '10 MINUTE');
}
public static function Get($key) {
if (!self::isEnabled()) {
return;
}
return Cache::get($key, self::getAge());
}
public static function Set($key, $value) {
if (!self::isEnabled()) {
return;
}
Cache::set($key, $value);
}
}

View File

@@ -24,6 +24,8 @@ class ASCollection {
$this->direction = $direction;
$this->limit = $limit;
$data = null;
if (is_array($obj)) {
$data = $obj;
}
@@ -147,4 +149,4 @@ class ASCollection {
}
logger('nextpage: ' . $this->nextpage, LOGGER_DEBUG);
}
}
}

View File

@@ -6,12 +6,17 @@ namespace Zotlabs\Lib;
class AbConfig {
static public function Load($chan,$xhash,$family = '') {
if($family)
$where = '';
if($family) {
$where = sprintf(" and cat = '%s' ",dbesc($family));
}
$r = q("select * from abconfig where chan = %d and xchan = '%s' $where",
intval($chan),
dbesc($xhash)
);
return $r;
}
@@ -21,7 +26,7 @@ class AbConfig {
intval($chan),
dbesc($xhash),
dbesc($family),
dbesc($key)
dbesc($key)
);
if($r) {
return ((preg_match('|^a:[0-9]+:{.*}$|s', $r[0]['v'])) ? unserialize($r[0]['v']) : $r[0]['v']);
@@ -41,19 +46,19 @@ class AbConfig {
dbesc($xhash),
dbesc($family),
dbesc($key),
dbesc($dbvalue)
dbesc($dbvalue)
);
}
else {
$r = q("update abconfig set v = '%s' where chan = %d and xchan = '%s' and cat = '%s' and k = '%s' ",
dbesc($dbvalue),
dbesc($dbvalue),
dbesc($chan),
dbesc($xhash),
dbesc($family),
dbesc($key)
);
}
if($r)
return $value;
return false;

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 = '';
@@ -23,10 +24,11 @@ class ActivityStreams {
public $origin = null;
public $owner = null;
public $signer = null;
public $ldsig = null;
public $sig = null;
public $sigok = false;
public $recips = null;
public $raw_recips = null;
public $saved_recips = null;
/**
* @brief Constructor for ActivityStreams.
@@ -35,12 +37,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;
@@ -70,9 +73,12 @@ class ActivityStreams {
}
}
// This indicates only that we have sucessfully decoded JSON.
$this->valid = true;
if (array_key_exists('type', $this->data) && array_key_exists('actor', $this->data) && array_key_exists('object', $this->data)) {
// Special handling for Mastodon "delete actor" activities which will often fail to verify
// because the key cannot be fetched. We will catch this condition elsewhere.
if (is_array($this->data) && array_key_exists('type', $this->data) && array_key_exists('actor', $this->data) && array_key_exists('object', $this->data)) {
if ($this->data['type'] === 'Delete' && $this->data['actor'] === $this->data['object']) {
$this->deleted = $this->data['actor'];
$this->valid = false;
@@ -81,8 +87,18 @@ class ActivityStreams {
}
// Attempt to assemble an Activity from what we were given.
if ($this->is_valid()) {
$this->id = $this->get_property_obj('id');
$this->id = $this->get_property_obj('id');
if (!$this->id) {
logger('Data with mmissing id: ' . print_r($this->data, true));
return;
}
// cache for future use
ASCache::Set($this->id, 'json:' . $this->raw);
$this->type = $this->get_primary_type();
$this->actor = $this->get_actor('actor', '', '');
$this->obj = $this->get_compound_property('object');
@@ -90,11 +106,19 @@ class ActivityStreams {
$this->origin = $this->get_compound_property('origin');
$this->recips = $this->collect_recips();
$this->ldsig = $this->get_compound_property('signature');
if ($this->ldsig) {
$this->signer = $this->get_actor('creator', $this->ldsig);
if ($this->signer && is_array($this->signer) && array_key_exists('publicKey', $this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
$this->sigok = LDSignatures::verify($this->data, $this->signer['publicKey']['publicKeyPem']);
$this->sig = $this->get_compound_property('proof');
if ($this->sig) {
$this->checkEddsaSignature(); // will set signer and sigok if everything works out
}
// Try LDSignatures if edsig failed
if (!$this->sigok) {
$this->sig = $this->get_compound_property('signature');
if ($this->sig) {
$this->signer = $this->get_actor('creator', $this->sig);
if ($this->signer && is_array($this->signer) && array_key_exists('publicKey', $this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
$this->sigok = LDSignatures::verify($this->data, $this->signer['publicKey']['publicKeyPem']);
}
}
}
@@ -106,25 +130,34 @@ class ActivityStreams {
}
}
// fetch recursive or embedded activities
// Fetch recursive or embedded activities
if ($this->obj && is_array($this->obj) && array_key_exists('object', $this->obj)) {
$this->obj['object'] = $this->get_compound_property($this->obj['object']);
$this->obj['object'] = $this->get_compound_property('object', $this->obj);
}
if ($this->obj && is_array($this->obj) && $this->obj['actor'])
// Enumerate and store actors in referenced objects
if ($this->obj && is_array($this->obj) && isset($this->obj['actor'])) {
$this->obj['actor'] = $this->get_actor('actor', $this->obj);
if ($this->tgt && is_array($this->tgt) && $this->tgt['actor'])
$this->tgt['actor'] = $this->get_actor('actor', $this->tgt);
$this->parent_id = $this->get_property_obj('inReplyTo');
if ((!$this->parent_id) && is_array($this->obj)) {
$this->parent_id = $this->obj['inReplyTo'];
}
if ((!$this->parent_id) && is_array($this->obj)) {
if ($this->tgt && is_array($this->tgt) && isset($this->tgt['actor'])) {
$this->tgt['actor'] = $this->get_actor('actor', $this->tgt);
}
// Determine if this is a followup or response activity
$this->parent_id = ((is_array($this->get_property_obj('inReplyTo'))) ? $this->get_property_obj('inReplyTo')['id'] : $this->get_property_obj('inReplyTo'));
if (!$this->parent_id && isset($this->obj['inReplyTo'])) {
$this->parent_id = ((is_array($this->obj['inReplyTo'])) ? $this->obj['inReplyTo']['id'] : $this->obj['inReplyTo']);
}
if (!$this->parent_id && isset($this->obj['id'])) {
$this->parent_id = $this->obj['id'];
}
}
}
@@ -141,36 +174,59 @@ class ActivityStreams {
$this->saved_recips = $arr;
}
/**
* @brief get single property from Activity object
*
* @param string $property
* @param mixed $default return value if property or object not set
* or object is a string id which could not be fetched.
* @return mixed
*/
public function objprop(string $property, mixed $default = false): mixed {
$x = $this->get_property_obj($property, $this->obj);
return (isset($x)) ? $x : $default;
}
/**
* @brief Collects all recipients.
*
* @param string $base
* @param mixed $base
* @param string $namespace (optional) default empty
* @return array
*/
function collect_recips($base = '', $namespace = '') {
$x = [];
public function collect_recips(mixed $base = '', string $namespace = ''): array {
$result = [];
$tmp = [];
$fields = ['to', 'cc', 'bto', 'bcc', 'audience'];
foreach ($fields as $f) {
$y = $this->get_compound_property($f, $base, $namespace);
if ($y) {
if (!is_array($this->raw_recips)) {
$this->raw_recips = [];
}
if (!is_array($y)) {
$y = [$y];
}
$this->raw_recips[$f] = $y;
$x = array_merge($x, $y);
foreach ($fields as $field) {
// don't expand these yet
$values = $this->get_property_obj($field, $base, $namespace);
if ($values) {
$values = force_array($values);
$tmp[$field] = $values;
$result = array_values(array_unique(array_merge($result, $values)));
}
// Merge the object recipients if they exist.
$values = $this->objprop($field);
if ($values) {
$values = force_array($values);
$tmp[$field] = ((isset($tmp[$field])) ? array_merge($tmp[$field], $values) : $values);
$result = array_values(array_unique(array_merge($result, $values)));
}
// remove duplicates
if (isset($tmp[$field])) {
$tmp[$field] = array_values(array_unique($tmp[$field]));
}
}
// not yet ready for prime time
// $x = $this->expand($x,$base,$namespace);
return $x;
$this->raw_recips = $tmp;
// not yet ready for prime time
// $result = $this->expand($result,$base,$namespace);
return $result;
}
function expand($arr, $base = '', $namespace = '') {
$ret = [];
@@ -274,12 +330,27 @@ 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);
if ($zf) {
$url = $zf['signature']['signer'];
$x = Activity::fetch($url, $channel);
}
}
}
return $x;
}
static function is_an_actor($s) {
@@ -290,7 +361,7 @@ class ActivityStreams {
if (!$s) {
return false;
}
return (in_array($s, ['Like', 'Dislike', 'Flag', 'Block', 'Announce', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact']));
return (in_array($s, ['Announce', 'Like', 'Dislike', 'Flag', 'Block', 'Accept', 'Reject', 'TentativeAccept', 'TentativeReject', 'emojiReaction', 'EmojiReaction', 'EmojiReact']));
}
/**
@@ -304,20 +375,25 @@ class ActivityStreams {
function get_actor($property, $base = '', $namespace = '') {
$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;
}
}
$actor = $this->get_compound_property($property, $base, $namespace, true);
if (is_array($actor) && self::is_an_actor($actor['type'])) {
if (array_key_exists('id', $actor) && (!array_key_exists('inbox', $actor))) {
$actor = $this->fetch_property($actor['id']);
}
return $actor;
}
return null;
return Activity::get_unknown_actor($this->data);
}
@@ -332,13 +408,26 @@ class ActivityStreams {
*/
function get_compound_property($property, $base = '', $namespace = '', $first = false) {
$x = $this->get_property_obj($property, $base, $namespace);
if ($this->is_url($x)) {
$y = $this->fetch_property($x);
$cached = ASCache::Get($x);
if ($cached) {
// logger('AS cached: ' . $x);
$y = unserialise($cached);
}
else {
// logger('AS fetching: ' . $x);
$y = $this->fetch_property($x);
if ($y) {
ASCache::Set($x, serialise($y));
}
}
if (is_array($y)) {
$x = $y;
}
}
// verify and unpack JSalmon signature if present
if (is_array($x) && array_key_exists('signed', $x)) {
@@ -438,4 +527,58 @@ class ActivityStreams {
}
public function checkEddsaSignature() {
$signer = $this->get_property_obj('verificationMethod', $this->sig);
$parseUrl = parse_url($signer);
if (isset($parseUrl['fragment'])) {
if (str_starts_with($parseUrl['fragment'], 'z6Mk')) {
$publicKey = $parseUrl['fragment'];
}
unset($parseUrl['fragment']);
}
if (isset($parseUrl['query'])) {
unset($parseUrl['query']);
}
$url = unparse_url($parseUrl);
$hublocs = Activity::get_actor_hublocs($url);
$hasStoredKey = false;
if ($hublocs) {
foreach ($hublocs as $hubloc) {
if ($publicKey && $hubloc['xchan_epubkey'] === $publicKey) {
$hasStoredKey = true;
break;
}
}
}
if (!$hasStoredKey) {
$this->signer = Activity::get_actor($url);
if (isset($this->signer['assertionMethod'])) {
if (!isset($this->signer['assertionMethod'][0])) {
$this->signer['assertionMethod'] = [$this->signer['assertionMethod']];
}
foreach($this->signer['assertionMethod'] as $am) {
if ($url === $am['controller'] &&
$am['type'] === 'Multikey' &&
str_starts_with($am['publicKeyMultibase'], 'z6Mk')
) {
$publicKey = $am['publicKeyMultibase'];
}
}
}
}
if ($publicKey) {
$this->sigok = (new JcsEddsa2022)->verify($this->data, $publicKey);
}
}
}

View File

@@ -159,7 +159,7 @@ class Apps {
foreach(self::$available_apps as $iapp) {
if($iapp['app_id'] == hash('whirlpool',$app['name'])) {
$notfound = false;
if(($iapp['app_version'] !== $app['version'])
if((isset($app['version']) && $iapp['app_version'] !== $app['version'])
|| ($app['plugin'] && (! $iapp['app_plugin']))) {
return intval($iapp['app_id']);
}
@@ -236,6 +236,7 @@ class Apps {
$ret['photo'] = $baseurl . '/' . get_default_profile_photo(80);
$ret['type'] = 'system';
$ret['plugin'] = '';
foreach($ret as $k => $v) {
if(strpos($v,'http') === 0) {
@@ -351,8 +352,6 @@ class Apps {
'Directory' => t('Directory'),
'Help' => t('Help'),
'Mail' => t('Mail'),
'Mood' => t('Mood'),
'Poke' => t('Poke'),
'Chat' => t('Chat'),
'Search' => t('Search'),
'Probe' => t('Probe'),
@@ -418,11 +417,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);
@@ -521,8 +537,13 @@ class Apps {
$hosturl = '';
if(local_channel()) {
if(self::app_installed(local_channel(),$papp) && !$papp['deleted'])
if(self::app_installed(local_channel(),$papp)) {
$installed = true;
}
if ($installed && isset($papp['deleted']) && $papp['deleted']) {
$installed = false;
}
$hosturl = z_root() . '/';
}
@@ -595,12 +616,12 @@ class Apps {
'$edit' => ((local_channel() && $installed && $mode == 'edit') ? t('Edit') : ''),
'$delete' => ((local_channel() && $mode == 'edit') ? t('Delete') : ''),
'$undelete' => ((local_channel() && $mode == 'edit') ? t('Undelete') : ''),
'$settings_url' => ((local_channel() && $installed && $mode == 'list') ? $papp['settings_url'] : ''),
'$deleted' => $papp['deleted'],
'$settings_url' => ((local_channel() && $installed && $mode == 'list' && isset($papp['settings_url'])) ? $papp['settings_url'] : ''),
'$deleted' => $papp['deleted'] ?? false,
'$feature' => ((isset($papp['embed']) || $mode == 'edit') ? false : true),
'$pin' => ((isset($papp['embed']) || $mode == 'edit') ? false : true),
'$featured' => ((strpos($papp['categories'], 'nav_featured_app') === false) ? false : true),
'$pinned' => ((strpos($papp['categories'], 'nav_pinned_app') === false) ? false : true),
'$featured' => ((isset($papp['categories']) && strpos($papp['categories'], 'nav_featured_app') !== false) ? true : false),
'$pinned' => ((isset($papp['categories']) && strpos($papp['categories'], 'nav_pinned_app') !== false) ? true : false),
'$mode' => $mode,
'$add' => t('Add to app-tray'),
'$remove' => t('Remove from app-tray'),
@@ -639,7 +660,7 @@ class Apps {
);
if($r) {
if($app['uid']) {
if($app['categories'] && (! $app['term'])) {
if((isset($app['categories']) && $app['categories']) && !(isset($app['term']) && $app['term'])) {
$r[0]['term'] = q("select * from term where otype = %d and oid = %d",
intval(TERM_OBJ_APP),
intval($r[0]['id'])
@@ -1184,7 +1205,7 @@ class Apps {
$ret['success'] = true;
$ret['app_id'] = $darray['app_id'];
}
if($arr['categories']) {
if(isset($arr['categories']) && $arr['categories']) {
$x = q("select id from app where app_id = '%s' and app_channel = %d limit 1",
dbesc($darray['app_id']),
intval($darray['app_channel'])
@@ -1282,7 +1303,7 @@ class Apps {
intval(TERM_OBJ_APP),
intval($x[0]['id'])
);
if($arr['categories']) {
if(isset($arr['categories']) && $arr['categories']) {
$y = explode(',',$arr['categories']);
if($y) {
foreach($y as $t) {

View File

@@ -5,50 +5,52 @@ 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);
public static function get($key, $age = '') {
// $hash = hash('whirlpool',$key);
$hash = uuid_from_url($key);
$r = q("SELECT v FROM cache WHERE k = '%s' AND updated > %s - INTERVAL %s LIMIT 1",
dbesc($hash),
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);
$hash = uuid_from_url($key);
$hash = hash('whirlpool',$key);
$r = q("SELECT * FROM cache WHERE k = '%s' limit 1",
$r = q("SELECT * FROM cache WHERE k = '%s' LIMIT 1",
dbesc($hash)
);
if($r) {
q("UPDATE cache SET v = '%s', updated = '%s' WHERE k = '%s'",
dbesc($value),
dbesc(datetime_convert()),
dbesc($hash));
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()));
dbesc(datetime_convert())
);
}
}
}

View File

@@ -2,6 +2,7 @@
namespace Zotlabs\Lib;
use App;
class Config {
@@ -14,20 +15,41 @@ class Config {
* @param string $family
* The category of the configuration value
*/
static public function Load($family) {
if(! array_key_exists($family, \App::$config))
\App::$config[$family] = array();
public static function Load($family, $recursionCounter = 0) {
if (! array_key_exists($family, App::$config)) {
App::$config[$family] = [];
}
if(! array_key_exists('config_loaded', \App::$config[$family])) {
// We typically continue when presented with minor DB issues,
// but loading the site configuration is more important.
// Check for query returning false and give it approx 30 seconds
// to recover if there's a problem. This is intended to fix a
// rare issue on Galera where temporary sync issues were causing
// the site encryption keys to be regenerated, which was causing
// communication issues for members.
// This code probably belongs at the database layer, but we don't
// necessarily want to shut the site down for problematic queries
// caused by bad data. That could be used in a denial of service
// attack. Those do need to be (and they are) logged.
if (! array_key_exists('config_loaded', App::$config[$family])) {
$r = q("SELECT * FROM config WHERE cat = '%s'", dbesc($family));
if($r !== false) {
if($r) {
foreach($r as $rr) {
$k = $rr['k'];
\App::$config[$family][$k] = $rr['v'];
}
if ($r === false && !App::$install) {
sleep(3);
$recursionCounter ++;
if ($recursionCounter > 10) {
system_unavailable();
}
\App::$config[$family]['config_loaded'] = true;
self::Load($family, $recursionCounter);
}
elseif (is_array($r)) {
foreach ($r as $rr) {
$k = $rr['k'];
App::$config[$family][$k] = $rr['v'];
}
App::$config[$family]['config_loaded'] = true;
}
}
}
@@ -46,19 +68,19 @@ class Config {
* @return mixed
* Return the set value, or false if the database update failed
*/
static public function Set($family, $key, $value) {
public static function Set($family, $key, $value) {
// manage array value
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
$dbvalue = ((is_array($value)) ? 'json:' . json_encode($value) : $value);
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
if(self::Get($family, $key) === false || (! self::get_from_storage($family, $key))) {
if (self::Get($family, $key) === false || (! self::get_from_storage($family, $key))) {
$ret = q("INSERT INTO config ( cat, k, v ) VALUES ( '%s', '%s', '%s' ) ",
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
if($ret) {
\App::$config[$family][$key] = $value;
if ($ret) {
App::$config[$family][$key] = $value;
$ret = $value;
}
return $ret;
@@ -70,8 +92,8 @@ class Config {
dbesc($key)
);
if($ret) {
\App::$config[$family][$key] = $value;
if ($ret) {
App::$config[$family][$key] = $value;
$ret = $value;
}
@@ -96,18 +118,34 @@ class Config {
* @param string $default (optional) default false
* @return mixed Return value or false on error or if not set
*/
static public function Get($family, $key, $default = false) {
if((! array_key_exists($family, \App::$config)) || (! array_key_exists('config_loaded', \App::$config[$family])))
self::Load($family);
public static function Get($family, $key, $default = false) {
if(array_key_exists('config_loaded', \App::$config[$family])) {
if(! array_key_exists($key, \App::$config[$family])) {
if ((! array_key_exists($family, App::$config)) || (! array_key_exists('config_loaded', App::$config[$family]))) {
self::Load($family);
}
if (array_key_exists('config_loaded', App::$config[$family])) {
if (! array_key_exists($key, App::$config[$family])) {
return $default;
}
return ((! is_array(\App::$config[$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$family][$key]))
? unserialize(\App::$config[$family][$key])
: \App::$config[$family][$key]
);
$value = App::$config[$family][$key];
if (! is_array($value)) {
if (substr($value, 0, 5) == 'json:') {
return json_decode(substr($value, 5), true);
} else if (preg_match('|^a:[0-9]+:{.*}$|s', $value)) {
// Unserialize in inherently unsafe. Try to mitigate by not
// allowing unserializing objects. Only kept for backwards
// compatibility. JSON serialization should be prefered.
return unserialize($value, array('allowed_classes' => false));
} else {
return $value;
}
}
else {
return $value;
}
}
return $default;
@@ -125,12 +163,13 @@ class Config {
* The configuration key to delete
* @return mixed
*/
static public function Delete($family, $key) {
public static function Delete($family, $key) {
$ret = false;
if(array_key_exists($family, \App::$config) && array_key_exists($key, \App::$config[$family]))
unset(\App::$config[$family][$key]);
if (array_key_exists($family, App::$config) && array_key_exists($key, App::$config[$family])) {
unset(App::$config[$family][$key]);
}
$ret = q("DELETE FROM config WHERE cat = '%s' AND k = '%s'",
dbesc($family),
@@ -153,7 +192,7 @@ class Config {
* The configuration key to query
* @return mixed
*/
static private function get_from_storage($family,$key) {
private static function get_from_storage($family, $key) {
$ret = q("SELECT * FROM config WHERE cat = '%s' AND k = '%s' LIMIT 1",
dbesc($family),
dbesc($key)
@@ -161,5 +200,4 @@ class Config {
return $ret;
}
}

View File

@@ -69,7 +69,8 @@ class Connect {
$xchan_hash = '';
$sql_options = (($protocol) ? " and xchan_network = '" . dbesc($protocol) . "' " : '');
$r = q("select * from xchan where ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s') $sql_options ",
// 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)
@@ -80,12 +81,13 @@ class Connect {
// reset results to the best record or the first if we don't have the best
// note: this is a single record and not an array of results
$r = Libzot::zot_record_preferred($r,'xchan_network');
$r = Libzot::zot_record_preferred($r, 'xchan_network');
}
$singleton = false;
$d = false;
$wf = false;
if (! $r) {
@@ -108,10 +110,12 @@ class Connect {
if ($wf || $d) {
$xchan_hash = (($wf) ? $wf : $url);
// something was discovered - find the record which was just created.
$r = q("select * from xchan where ( xchan_hash = '%s' or xchan_url = '%s' or xchan_addr = '%s' ) $sql_options",
dbesc(($wf) ? $wf : $url),
dbesc($xchan_hash),
dbesc($url),
dbesc($url)
);
@@ -119,7 +123,7 @@ class Connect {
// convert to a single record (once again preferring a zot solution in the case of multiples)
if ($r) {
$r = Libzot::zot_record_preferred($r,'xchan_network');
$r = Libzot::zot_record_preferred($r, 'xchan_network');
}
}

View File

@@ -6,23 +6,26 @@ class DReport {
private $location;
private $sender;
private $recipient;
private $name;
private $message_id;
private $message_uuid;
private $status;
private $date;
function __construct($location,$sender,$recipient,$message_id,$status = 'deliver') {
$this->location = $location;
$this->sender = $sender;
$this->recipient = $recipient;
$this->name = EMPTY_STR;
$this->message_id = $message_id;
$this->status = $status;
$this->date = datetime_convert();
function __construct($location, $sender, $recipient, $message_id, $message_uuid = '', $status = 'deliver') {
$this->location = $location;
$this->sender = $sender;
$this->recipient = $recipient;
$this->name = EMPTY_STR;
$this->message_id = $message_id;
$this->message_uuid = $message_uuid;
$this->status = $status;
$this->date = datetime_convert();
}
function update($status) {
$this->status = $status;
$this->date = datetime_convert();
$this->status = $status;
$this->date = datetime_convert();
}
function set_name($name) {
@@ -35,24 +38,26 @@ class DReport {
function set($arr) {
$this->location = $arr['location'];
$this->sender = $arr['sender'];
$this->recipient = $arr['recipient'];
$this->name = $arr['name'];
$this->message_id = $arr['message_id'];
$this->status = $arr['status'];
$this->date = $arr['date'];
$this->location = $arr['location'];
$this->sender = $arr['sender'];
$this->recipient = $arr['recipient'];
$this->name = $arr['name'];
$this->message_id = $arr['message_id'];
$this->message_uuid = $arr['message_uuid'] ?? '';
$this->status = $arr['status'];
$this->date = $arr['date'];
}
function get() {
return array(
'location' => $this->location,
'sender' => $this->sender,
'recipient' => $this->recipient,
'name' => $this->name,
'message_id' => $this->message_id,
'status' => $this->status,
'date' => $this->date
'location' => $this->location,
'sender' => $this->sender,
'recipient' => $this->recipient,
'name' => $this->name,
'message_id' => $this->message_id,
'message_uuid' => $this->message_uuid,
'status' => $this->status,
'date' => $this->date
);
}
@@ -94,19 +99,6 @@ class DReport {
if(! $c)
return false;
// legacy zot recipients add a space and their name to the xchan. remove it if true.
$legacy_recipient = strpos($dr['recipient'], ' ');
if($legacy_recipient !== false) {
$legacy_recipient_parts = explode(' ', $dr['recipient'], 2);
$rxchan = $legacy_recipient_parts[0];
}
else {
$rxchan = $dr['recipient'];
}
// is the recipient one of our connections, or do we want to store every report?
$pcf = get_pconfig($c[0]['channel_id'],'system','dreport_store_all');
@@ -117,7 +109,7 @@ class DReport {
// So if a remote site says they can't find us, that's no big surprise
// and just creates a lot of extra report noise
if(($dr['location'] !== z_root()) && ($dr['sender'] === $rxchan) && ($dr['status'] === 'recipient not found'))
if(($dr['location'] !== z_root()) && ($dr['sender'] === $dr['recipient']) && ($dr['status'] === 'recipient not found'))
return false;
// If you have a private post with a recipient list, every single site is going to report
@@ -126,14 +118,14 @@ class DReport {
// have a channel on that site.
$r = q("select hubloc_id from hubloc where hubloc_hash = '%s' and hubloc_url = '%s'",
dbesc($rxchan),
dbesc($dr['recipient']),
dbesc($dr['location'])
);
if((! $r) && ($dr['status'] === 'recipient_not_found'))
return false;
$r = q("select abook_id from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
dbesc($rxchan),
dbesc($dr['recipient']),
intval($c[0]['channel_id'])
);
if($r)

View File

@@ -122,8 +122,11 @@ class Enotify {
// e.g. "your post", "David's photo", etc.
$possess_desc = t('%s <!item_type!>');
$parent_mid = '';
$parent_item = [];
// @@TODO: consider using switch instead of those elseif
if ($params['type'] == NOTIFY_MAIL) {
if (isset($params['type']) && $params['type'] == NOTIFY_MAIL) {
logger('notification: mail');
$subject = sprintf( t('[$Projectname:Notify] New direct message received at %s'), $sitename);
@@ -135,18 +138,18 @@ class Enotify {
$itemlink = $siteurl . '/hq/' . gen_link_id($params['item']['mid']);
}
elseif ($params['type'] === NOTIFY_COMMENT) {
elseif (isset($params['type']) && $params['type'] === NOTIFY_COMMENT) {
//logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
$moderated = (($params['item']['item_blocked'] == ITEM_MODERATED) ? true : false);
$itemlink = $params['link'];
$action = t('commented on');
$action = (($moderated) ? t('requested to comment on') : t('commented on'));
if(array_key_exists('item',$params)) {
if(in_array($params['item']['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
if(in_array($params['item']['verb'], ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE, ACTIVITY_SHARE])) {
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE)) {
logger('notification: not a visible activity. Ignoring.');
@@ -154,11 +157,14 @@ class Enotify {
return;
}
if(activity_match($params['verb'], ACTIVITY_LIKE))
$action = t('liked');
if(activity_match($params['verb'], ['Like', ACTIVITY_LIKE]))
$action = (($moderated) ? t('requested to like') : t('liked'));
if(activity_match($params['verb'], ACTIVITY_DISLIKE))
$action = t('disliked');
if(activity_match($params['verb'], ['Dislike', ACTIVITY_DISLIKE]))
$action = (($moderated) ? t('requested to dislike') : t('disliked'));
if(activity_match($params['verb'], ACTIVITY_SHARE))
$action = t('repeated');
}
@@ -167,7 +173,7 @@ class Enotify {
}
$parent_mid = $params['parent_mid'];
$parent_mid = $params['parent_mid'] ?? '';
// Check to see if there was already a notify for this post.
// If so don't create a second notification
@@ -251,20 +257,20 @@ class Enotify {
}
elseif ($params['type'] === NOTIFY_LIKE) {
elseif (isset($params['type']) && $params['type'] === NOTIFY_LIKE) {
// logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
$itemlink = $params['link'];
if (array_key_exists('item',$params) && activity_match($params['item']['verb'],ACTIVITY_LIKE)) {
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE)) {
if (array_key_exists('item',$params) && (activity_match($params['item']['verb'], ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE]))) {
if(! $always_show_in_notices || !($vnotify & VNOTIFY_LIKE) || !feature_enabled($recip['channel_id'], 'dislike')) {
logger('notification: not a visible activity. Ignoring.');
pop_lang();
return;
}
}
$parent_mid = $params['parent_mid'];
$parent_mid = $params['parent_mid'] ?? '';
// Check to see if there was already a notify for this post.
// If so don't create a second notification
@@ -291,22 +297,36 @@ class Enotify {
);
}
if (!$p) {
pop_lang();
return;
}
xchan_query($p);
//@@FIXME $p can be null (line 285)
$item_post_type = item_post_type($p[0]);
// $private = $p[0]['item_private'];
$parent_id = $p[0]['id'];
$parent_item = $p[0];
//$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'], ['Like', ACTIVITY_LIKE]))
$verb = (($moderated) ? t('requested to like') : t('liked'));
if(activity_match($params['item']['verb'], ['Dislike', 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']))
$dest_str = sprintf(t('%1$s liked [zrl=%2$s]your %3$s[/zrl]'),
$dest_str = sprintf(t('%1$s %2$s [zrl=%3$s]your %4$s[/zrl]'),
'[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]',
$verb,
$itemlink,
$item_post_type);
$item_post_type
);
else {
pop_lang();
return;
@@ -328,7 +348,7 @@ class Enotify {
elseif($params['type'] === NOTIFY_WALL) {
elseif(isset($params['type']) && $params['type'] === NOTIFY_WALL) {
$subject = sprintf( t('[$Projectname:Notify] %s posted to your profile wall') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s posted to your profile wall at %2$s') , $sender['xchan_name'], $sitename);
@@ -343,7 +363,7 @@ class Enotify {
$itemlink = $params['link'];
}
elseif ($params['type'] === NOTIFY_TAGSELF) {
elseif (isset($params['type']) && $params['type'] === NOTIFY_TAGSELF) {
$p = q("select id from notify where link = '%s' and uid = %d limit 1",
dbesc($params['link']),
@@ -367,7 +387,7 @@ class Enotify {
$itemlink = $params['link'];
}
elseif ($params['type'] === NOTIFY_POKE) {
elseif (isset($params['type']) && $params['type'] === NOTIFY_POKE) {
$subject = sprintf( t('[$Projectname:Notify] %1$s poked you') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s poked you at %2$s') , $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s [zrl=%2$s]poked you[/zrl].') ,
@@ -384,7 +404,7 @@ class Enotify {
$itemlink = $params['link'];
}
elseif ($params['type'] === NOTIFY_TAGSHARE) {
elseif (isset($params['type']) && $params['type'] === NOTIFY_TAGSHARE) {
$subject = sprintf( t('[$Projectname:Notify] %s tagged your post') , $sender['xchan_name']);
$preamble = sprintf( t('%1$s tagged your post at %2$s'),$sender['xchan_name'], $sitename);
$epreamble = sprintf( t('%1$s tagged [zrl=%2$s]your post[/zrl]') ,
@@ -397,7 +417,7 @@ class Enotify {
$itemlink = $params['link'];
}
elseif ($params['type'] === NOTIFY_INTRO) {
elseif (isset($params['type']) && $params['type'] === NOTIFY_INTRO) {
$subject = sprintf( t('[$Projectname:Notify] Introduction received'));
$preamble = sprintf( t('You\'ve received an new connection request from \'%1$s\' at %2$s'), $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('You\'ve received [zrl=%1$s]a new connection request[/zrl] from %2$s.'),
@@ -411,7 +431,7 @@ class Enotify {
$itemlink = $params['link'];
}
elseif ($params['type'] === NOTIFY_SUGGEST) {
elseif (isset($params['type']) && $params['type'] === NOTIFY_SUGGEST) {
$subject = sprintf( t('[$Projectname:Notify] Friend suggestion received'));
$preamble = sprintf( t('You\'ve received a friend suggestion from \'%1$s\' at %2$s'), $sender['xchan_name'], $sitename);
$epreamble = sprintf( t('You\'ve received [zrl=%1$s]a friend suggestion[/zrl] for %2$s from %3$s.'),
@@ -429,11 +449,11 @@ class Enotify {
$itemlink = $params['link'];
}
elseif ($params['type'] === NOTIFY_CONFIRM) {
elseif (isset($params['type']) && $params['type'] === NOTIFY_CONFIRM) {
// ?
}
elseif ($params['type'] === NOTIFY_SYSTEM) {
elseif (isset($params['type']) && $params['type'] === NOTIFY_SYSTEM) {
// ?
}
@@ -466,6 +486,8 @@ class Enotify {
require_once('include/html2bbcode.php');
/*
do {
$dups = false;
$hash = random_string();
@@ -474,10 +496,12 @@ class Enotify {
if ($r)
$dups = true;
} while ($dups === true);
*/
$datarray = [];
$datarray['hash'] = $hash;
$datarray['hash'] = $params['item']['uuid'] ?? new_uuid();
$datarray['sender_hash'] = $sender['xchan_hash'];
$datarray['xname'] = $sender['xchan_name'];
$datarray['url'] = $sender['xchan_url'];
@@ -488,12 +512,13 @@ class Enotify {
$datarray['link'] = $itemlink;
$datarray['parent'] = $parent_mid;
$datarray['parent_item'] = $parent_item;
$datarray['ntype'] = $params['type'];
$datarray['verb'] = $params['verb'];
$datarray['otype'] = $params['otype'];
$datarray['ntype'] = $params['type'] ?? 0;
$datarray['verb'] = $params['verb'] ?? '';
$datarray['otype'] = $params['otype'] ?? '';
$datarray['abort'] = false;
$datarray['seen'] = 0;
$datarray['item'] = $params['item'];
$datarray['item'] = $params['item'] ?? [];
call_hooks('enotify_store', $datarray);
@@ -504,7 +529,6 @@ class Enotify {
// create notification entry in DB
$seen = 0;
// Mark some notifications as seen right away
// Note! The notification have to be created, because they are used to send emails
@@ -514,7 +538,7 @@ class Enotify {
if (!$always_show_in_notices) {
if (($params['type'] === NOTIFY_WALL) || ($params['type'] === NOTIFY_MAIL) || ($params['type'] === NOTIFY_INTRO)) {
$seen = 1;
$datarray['seen'] = 1;
}
}
@@ -530,14 +554,15 @@ class Enotify {
intval($datarray['uid']),
dbesc($datarray['link']),
dbesc($datarray['parent']),
intval($seen),
intval($datarray['seen']),
intval($datarray['ntype']),
dbesc($datarray['verb']),
dbesc($datarray['otype'])
);
$r = q("select id from notify where hash = '%s' and uid = %d limit 1",
dbesc($hash),
$r = q("select id from notify where hash = '%s' and ntype = %d and uid = %d limit 1",
dbesc($datarray['hash']),
intval($datarray['ntype']),
intval($recip['channel_id'])
);
if ($r) {
@@ -606,8 +631,8 @@ class Enotify {
$datarray['preamble'] = $preamble;
$datarray['sitename'] = $sitename;
$datarray['siteurl'] = $siteurl;
$datarray['type'] = $params['type'];
$datarray['parent'] = $params['parent_mid'];
$datarray['type'] = $params['type'] ?? '';
$datarray['parent'] = $params['parent_mid'] ?? '';
$datarray['source_name'] = $sender['xchan_name'];
$datarray['source_link'] = $sender['xchan_url'];
$datarray['source_photo'] = $sender['xchan_photo_s'];
@@ -674,7 +699,6 @@ class Enotify {
'$source_name' => $datarray['source_name'],
'$source_link' => $datarray['source_link'],
'$source_photo' => $datarray['source_photo'],
'$username' => $datarray['to_name'],
'$hsitelink' => $datarray['hsitelink'],
'$hitemlink' => $datarray['hitemlink'],
'$thanks' => $datarray['thanks'],
@@ -696,7 +720,6 @@ class Enotify {
'$source_name' => $datarray['source_name'],
'$source_link' => $datarray['source_link'],
'$source_photo' => $datarray['source_photo'],
'$username' => $datarray['to_name'],
'$tsitelink' => $datarray['tsitelink'],
'$titemlink' => $datarray['titemlink'],
'$thanks' => $datarray['thanks'],
@@ -808,10 +831,10 @@ class Enotify {
localize_item($item);
if($item['shortlocalize']) {
if(isset($item['shortlocalize'])) {
$itemem_text = $item['shortlocalize'];
}
elseif($item['localize']) {
elseif(isset($item['localize'])) {
$itemem_text = $item['localize'];
}
else {
@@ -820,10 +843,6 @@ class Enotify {
: (($item['obj_type'] === 'Answer') ? sprintf( t('voted on %s\'s poll'), '[bdi]' . $item['owner']['xchan_name'] . '[/bdi]') : sprintf( t('commented on %s\'s post'), '[bdi]' . $item['owner']['xchan_name'] . '[/bdi]'))
);
if($item['verb'] === ACTIVITY_SHARE) {
$itemem_text = sprintf( t('repeated %s\'s post'), '[bdi]' . $item['author']['xchan_name'] . '[/bdi]');
}
if(in_array($item['obj_type'], ['Document', 'Video', 'Audio', 'Image'])) {
$itemem_text = t('shared a file with you');
}
@@ -844,27 +863,27 @@ class Enotify {
// convert this logic into a json array just like the system notifications
$who = (($item['verb'] === ACTIVITY_SHARE) ? 'owner' : 'author');
$body = html2plain(bbcode($item['body'], ['drop_media']), 75, true);
$body = html2plain(bbcode($item['body'], ['drop_media' => true, 'tryoembed' => false]), 75, true);
if ($body) {
$body = htmlentities($body, ENT_QUOTES, 'UTF-8', false);
}
$x = array(
'notify_link' => $item['llink'],
'name' => $item[$who]['xchan_name'],
'addr' => (($item[$who]['xchan_addr']) ? $item[$who]['xchan_addr'] : $item[$who]['xchan_url']),
'url' => $item[$who]['xchan_url'],
'photo' => $item[$who]['xchan_photo_s'],
'name' => $item['author']['xchan_name'],
'addr' => $item['author']['xchan_addr'] ? $item['author']['xchan_addr'] : $item['author']['xchan_url'],
'url' => $item['author']['xchan_url'],
'photo' => $item['author']['xchan_photo_s'],
'when' => (($edit) ? datetime_convert('UTC', date_default_timezone_get(), $item['edited']) : datetime_convert('UTC', date_default_timezone_get(), $item['created'])),
'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
'b64mid' => (($item['mid']) ? gen_link_id($item['mid']) : ''),
// 'b64mid' => (($item['mid']) ? gen_link_id($item['mid']) : ''),
'b64mid' => (($item['uuid']) ? $item['uuid'] : ''),
//'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? gen_link_id($item['thr_parent']) : gen_link_id($item['mid'])),
'thread_top' => (($item['item_thread_top']) ? true : false),
'message' => bbcode(escape_tags($itemem_text)),
'body' => $body,
// these are for the superblock addon
'hash' => $item[$who]['xchan_hash'],
'hash' => $item['author']['xchan_hash'],
'uid' => $item['uid'],
'display' => true
);
@@ -884,9 +903,6 @@ class Enotify {
if(strpos($message, $tt['xname']) === 0)
$message = substr($message, strlen($tt['xname']) + 1);
$mid = basename($tt['link']);
$b64mid = gen_link_id($mid);
$x = [
'notify_link' => (($tt['ntype'] === NOTIFY_MAIL) ? $tt['link'] : z_root() . '/notify/view/' . $tt['id']),
'name' => $tt['xname'],
@@ -894,7 +910,7 @@ class Enotify {
'photo' => $tt['photo'],
'when' => datetime_convert('UTC', date_default_timezone_get(), $tt['created']),
'hclass' => (($tt['seen']) ? 'notify-seen' : 'notify-unseen'),
'b64mid' => (($tt['otype'] == 'item') ? $b64mid : ''),
'b64mid' => (($tt['otype'] == 'item') ? $tt['hash'] : ''),
'notify_id' => (($tt['otype'] == 'item') ? $tt['id'] : ''),
'message' => $message
];

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

@@ -0,0 +1,92 @@
<?php
namespace Zotlabs\Lib;
use Mmccook\JsonCanonicalizator\JsonCanonicalizatorFactory;
use StephenHill\Base58;
class JcsEddsa2022 {
public function __construct() {
return $this;
}
public function sign($data, $channel): array {
$base58 = new Base58();
$pubkey = (new Multibase())->publicKey($channel['channel_epubkey']);
$options = [
'type' => 'DataIntegrityProof',
'cryptosuite' => 'eddsa-jcs-2022',
'created' => datetime_convert('UTC', 'UTC', 'now', ATOM_TIME),
'verificationMethod' => channel_url($channel) . '#' . $pubkey,
'proofPurpose' => 'assertionMethod',
];
$optionsHash = $this->hash($this->signableOptions($options), true);
$dataHash = $this->hash($this->signableData($data), true);
$options['proofValue'] = 'z' . $base58->encode(sodium_crypto_sign_detached($optionsHash . $dataHash,
sodium_base642bin($channel['channel_eprvkey'], SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING)));
return $options;
}
public function verify($data, $publicKey) {
$base58 = new Base58();
$encodedSignature = $data['proof']['proofValue'] ?? '';
if (!str_starts_with($encodedSignature,'z')) {
return false;
}
$encodedSignature = substr($encodedSignature, 1);
$optionsHash = $this->hash($this->signableOptions($data['proof']), true);
$dataHash = $this->hash($this->signableData($data),true);
try {
$result = sodium_crypto_sign_verify_detached($base58->decode($encodedSignature), $optionsHash . $dataHash,
(new Multibase())->decode($publicKey, true));
}
catch (\Exception $e) {
logger('verify exception:' . $e->getMessage());
}
logger('SignatureVerify (eddsa-jcs-2022) ' . (($result) ? 'true' : 'false'));
return $result;
}
public function signableData($data) {
$signableData = [];
if ($data) {
foreach ($data as $k => $v) {
if (!in_array($k, ['proof', 'signature'])) {
$signableData[$k] = $v;
}
}
}
return $signableData;
}
public function signableOptions($options) {
$signableOptions = [];
if ($options) {
foreach ($options as $k => $v) {
if ($k !== 'proofValue') {
$signableOptions[$k] = $v;
}
}
}
return $signableOptions;
}
public function hash($obj, $binary = false) {
return hash('sha256', $this->canonicalize($obj), $binary);
}
public function canonicalize($data) {
$canonicalization = JsonCanonicalizatorFactory::getInstance();
return $canonicalization->canonicalize($data);
}
}

View File

@@ -135,14 +135,13 @@ class Libsync {
$info['collection_members'] = $r;
}
$interval = ((get_config('system', 'delivery_interval') !== false)
? intval(get_config('system', 'delivery_interval')) : 2);
$interval = get_config('queueworker', 'queue_interval', 500000);
logger('Packet: ' . print_r($info, true), LOGGER_DATA, LOG_DEBUG);
$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,
@@ -155,19 +154,26 @@ class Libsync {
]);
/*
$x = q("select count(outq_hash) as total from outq where outq_delivered = 0");
if (intval($x[0]['total']) > intval(get_config('system', 'force_queue_threshold', 3000))) {
logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO);
Queue::update($hash);
continue;
}
*/
Master::Summon(['Deliver', $hash]);
$total = $total - 1;
if ($interval && $total)
@time_sleep_until(microtime(true) + (float)$interval);
/*
$total = $total - 1;
*/
if ($interval) {
usleep($interval);
}
}
}
@@ -192,7 +198,10 @@ class Libsync {
dbesc($sender)
);
$DR = new DReport(z_root(), $sender, $d, 'sync');
$mid = 'sync';
$DR = new DReport(z_root(), $sender, $d, $mid);
if (!$r) {
$DR->update('recipient not found');
@@ -202,6 +211,7 @@ class Libsync {
$channel = $r[0];
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
$max_friends = service_class_fetch($channel['channel_id'], 'total_channels');
@@ -293,8 +303,10 @@ class Libsync {
if (array_key_exists('event_item', $arr) && $arr['event_item'])
sync_items($channel, $arr['event_item'], ((array_key_exists('relocate', $arr)) ? $arr['relocate'] : null));
if (array_key_exists('item', $arr) && $arr['item'])
if (array_key_exists('item', $arr) && $arr['item']) {
sync_items($channel, $arr['item'], ((array_key_exists('relocate', $arr)) ? $arr['relocate'] : null));
$mid = $arr['item'][0]['message_id'] . '#sync';
}
// deprecated, maintaining for a few months for upward compatibility
// this should sync webpages, but the logic is a bit subtle
@@ -313,10 +325,7 @@ class Libsync {
if (array_key_exists('channel', $arr) && is_array($arr['channel']) && count($arr['channel'])) {
$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
@@ -327,6 +336,8 @@ class Libsync {
}
$columns = db_columns('channel');
$disallowed = [
'channel_id', 'channel_account_id', 'channel_primary', 'channel_prvkey',
'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted',
@@ -337,16 +348,21 @@ class Libsync {
'channel_a_delegate'
];
$clean = [];
foreach ($arr['channel'] as $k => $v) {
if (in_array($k, $disallowed))
continue;
$clean[$k] = $v;
if (empty($channel['channel_epubkey']) && empty($channel['channel_eprvkey'])) {
$eckey = sodium_crypto_sign_keypair();
$channel['channel_epubkey'] = sodium_bin2base64(sodium_crypto_sign_publickey($eckey), SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
$channel['channel_eprvkey'] = sodium_bin2base64(sodium_crypto_sign_secretkey($eckey), SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
}
if (count($clean)) {
foreach ($clean as $k => $v) {
dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v) . "' where channel_id = " . intval($channel['channel_id']));
foreach ($arr['channel'] as $k => $v) {
if (in_array($k, $disallowed)) {
continue;
}
if (!in_array($k, $columns)) {
continue;
}
$r = dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v)
. "' where channel_id = " . intval($channel['channel_id']));
}
}
@@ -740,13 +756,12 @@ class Libsync {
*/
call_hooks('process_channel_sync_delivery', $addon);
$DR = new DReport(z_root(), $d, $d, 'sync', 'channel sync delivered');
$DR = new DReport(z_root(), $d, $d, $mid, 'channel sync processed');
$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
$result[] = $DR->get();
}
return $result;
}
@@ -755,13 +770,19 @@ class Libsync {
*
* @param array $sender
* @param array $arr
* @param boolean $absolute (optional) default false
* @return array
*/
static function sync_locations($sender, $arr, $absolute = false) {
static function sync_locations($sender, $arr) {
$ret = [];
$ret = [
'change_message' => '',
'changed' => false,
'message' => ''
];
$what = '';
$changed = false;
// If a sender reports that the channel has been deleted, delete its hubloc
if (isset($arr['deleted_locally']) && intval($arr['deleted_locally'])) {
@@ -772,12 +793,9 @@ class Libsync {
);
}
if ($arr['locations']) {
if (isset($arr['locations']) && $arr['locations']) {
if ($absolute)
Libzot::check_location_move($sender['hash'], $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'])
);
@@ -849,7 +867,9 @@ class Libsync {
);
}
// update connection timestamp if this is the site we're talking to
// Update connection timestamp if this is the site we're talking to.
// Also mark all entries from the current site with different sitekeys
// deleted (the site has been re-installed)
// This only happens when called from import_xchan
$current_site = false;
@@ -863,6 +883,12 @@ class Libsync {
intval($r[0]['hubloc_id']),
dbesc($t)
);
q("update hubloc set hubloc_error = 1, hubloc_deleted = 1 where hubloc_url = '%s' and hubloc_sitekey != '%s'",
dbesc($r[0]['hubloc_url']),
dbesc($r[0]['hubloc_sitekey'])
);
$current_site = true;
}
@@ -912,14 +938,7 @@ class Libsync {
$what .= 'primary_hub ';
$changed = true;
}
elseif ($absolute) {
// Absolute sync - make sure the current primary is correctly reflected in the xchan
$pr = hubloc_change_primary($r[0]);
if ($pr) {
$what .= 'xchan_primary ';
$changed = true;
}
}
if (intval($r[0]['hubloc_deleted']) && (!intval($location['deleted']))) {
q("update hubloc set hubloc_deleted = 0, hubloc_updated = '%s' where hubloc_id_url = '%s'",
dbesc(datetime_convert()),
@@ -988,9 +1007,9 @@ class Libsync {
}
}
// get rid of any hubs we have for this channel which weren't reported.
// get rid of any hublocs we have for this channel which weren't reported.
if ($absolute && $xisting) {
if ($xisting) {
foreach ($xisting as $x) {
if (!array_key_exists('updated', $x)) {
logger('Deleting unreferenced hub location ' . $x['hubloc_addr']);

File diff suppressed because it is too large Load Diff

View File

@@ -145,8 +145,8 @@ class Libzotdir {
if(! $directory_sort_order)
$directory_sort_order = 'date';
$current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : $directory_sort_order);
$suggest = (($_REQUEST['suggest']) ? '&suggest=' . $_REQUEST['suggest'] : '');
$current_order = $_REQUEST['order'] ?? $directory_sort_order;
$suggest = ((isset($_REQUEST['suggest'])) ? '&suggest=' . $_REQUEST['suggest'] : '');
$url = 'directory?f=';
@@ -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,39 +482,48 @@ 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)
return false;
$arr = array();
$arr = [];
$arr['xprof_hash'] = $hash;
$arr['xprof_dob'] = (($profile['birthday'] === '0000-00-00') ? $profile['birthday'] : datetime_convert('','',$profile['birthday'],'Y-m-d')); // !!!! check this for 0000 year
$arr['xprof_age'] = (($profile['age']) ? intval($profile['age']) : 0);
$arr['xprof_desc'] = (($profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_gender'] = (($profile['gender']) ? htmlspecialchars($profile['gender'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_marital'] = (($profile['marital']) ? htmlspecialchars($profile['marital'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_sexual'] = (($profile['sexual']) ? htmlspecialchars($profile['sexual'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_locale'] = (($profile['locale']) ? htmlspecialchars($profile['locale'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_region'] = (($profile['region']) ? htmlspecialchars($profile['region'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_postcode'] = (($profile['postcode']) ? htmlspecialchars($profile['postcode'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_country'] = (($profile['country']) ? htmlspecialchars($profile['country'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_about'] = (($profile['about']) ? htmlspecialchars($profile['about'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_homepage'] = (($profile['homepage']) ? htmlspecialchars($profile['homepage'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_hometown'] = (($profile['hometown']) ? htmlspecialchars($profile['hometown'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_hash'] = $hash;
$arr['xprof_dob'] = '0000-00-00';
if (isset($profile['birthday'])) {
$arr['xprof_dob'] = (($profile['birthday'] === '0000-00-00')
? $profile['birthday']
: datetime_convert('', '', $profile['birthday'], 'Y-m-d')); // !!!! check this for 0000 year
}
$arr['xprof_age'] = ((isset($profile['age']) && $profile['age']) ? intval($profile['age']) : 0);
$arr['xprof_desc'] = ((isset($profile['description']) && $profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_gender'] = ((isset($profile['gender']) && $profile['gender']) ? htmlspecialchars($profile['gender'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_marital'] = ((isset($profile['marital']) && $profile['marital']) ? htmlspecialchars($profile['marital'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_sexual'] = ((isset($profile['sexual']) && $profile['sexual']) ? htmlspecialchars($profile['sexual'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_locale'] = ((isset($profile['locale']) && $profile['locale']) ? htmlspecialchars($profile['locale'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_region'] = ((isset($profile['region']) && $profile['region']) ? htmlspecialchars($profile['region'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_postcode'] = ((isset($profile['postcode']) && $profile['postcode']) ? htmlspecialchars($profile['postcode'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_country'] = ((isset($profile['country']) && $profile['country']) ? htmlspecialchars($profile['country'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_about'] = ((isset($profile['about']) && $profile['about']) ? htmlspecialchars($profile['about'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_homepage'] = ((isset($profile['homepage']) && $profile['homepage']) ? htmlspecialchars($profile['homepage'], ENT_COMPAT,'UTF-8',false) : '');
$arr['xprof_hometown'] = ((isset($profile['hometown']) && $profile['hometown']) ? htmlspecialchars($profile['hometown'], ENT_COMPAT,'UTF-8',false) : '');
$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;
@@ -580,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'];
}
@@ -600,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'];
@@ -607,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;
@@ -621,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'])
);
}
}
@@ -633,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'));
@@ -647,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

@@ -8,7 +8,7 @@ class MessageFilter {
public static function evaluate($item, $incl, $excl) {
$text = prepare_text($item['body'],((isset($item['mimetype'])) ? $item['mimetype'] : 'text/x-multicode'));
$text = prepare_text($item['body'],((isset($item['mimetype'])) ? $item['mimetype'] : 'text/bbcode'));
$text = html2plain(($item['title']) ? $item['title'] . ' ' . $text : $text);
$lang = null;
@@ -25,11 +25,23 @@ class MessageFilter {
if ($exclude) {
foreach ($exclude as $word) {
$word = trim($word);
$word = html_entity_decode(trim($word));
if (! $word) {
continue;
}
if (substr($word, 0, 1) === '#' && $tags) {
if (isset($lang) && ((strpos($word, 'lang=') === 0) || (strpos($word, 'lang!=') === 0))) {
if (!strlen($lang)) {
// Result is ambiguous. As we are matching deny rules only at this time, continue tests.
// Any matching deny rule concludes testing.
continue;
}
if (strpos($word, 'lang=') === 0 && strcasecmp($lang, trim(substr($word, 5))) == 0) {
return false;
} elseif (strpos($word, 'lang!=') === 0 && strcasecmp($lang, trim(substr($word, 6))) != 0) {
return false;
}
}
elseif (substr($word, 0, 1) === '#' && $tags) {
foreach ($tags as $t) {
if ((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
return false;
@@ -51,10 +63,6 @@ class MessageFilter {
}
} elseif ((strpos($word, '/') === 0) && preg_match($word, $text)) {
return false;
} elseif ((strpos($word, 'lang=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 5))) == 0)) {
return false;
} elseif ((strpos($word, 'lang!=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 6))) != 0)) {
return false;
} elseif (stristr($text, $word) !== false) {
return false;
}
@@ -65,11 +73,23 @@ class MessageFilter {
if ($include) {
foreach ($include as $word) {
$word = trim($word);
$word = html_entity_decode(trim($word));
if (! $word) {
continue;
}
if (substr($word, 0, 1) === '#' && $tags) {
if (isset($lang) && ((strpos($word, 'lang=') === 0) || (strpos($word, 'lang!=') === 0))) {
if (!strlen($lang)) {
// Result is ambiguous. However we are checking allow rules
// and an ambiguous language is always permitted.
return true;
}
if (strpos($word, 'lang=') === 0 && strcasecmp($lang, trim(substr($word, 5))) == 0) {
return true;
} elseif (strpos($word, 'lang!=') === 0 && strcasecmp($lang, trim(substr($word, 6))) != 0) {
return true;
}
}
elseif (substr($word, 0, 1) === '#' && $tags) {
foreach ($tags as $t) {
if ((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word, 1)) || (substr($word, 1) === '*'))) {
return true;
@@ -91,10 +111,6 @@ class MessageFilter {
}
} elseif ((strpos($word, '/') === 0) && preg_match($word, $text)) {
return true;
} elseif ((strpos($word, 'lang=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 5))) == 0)) {
return true;
} elseif ((strpos($word, 'lang!=') === 0) && ($lang) && (strcasecmp($lang, trim(substr($word, 6))) != 0)) {
return true;
} elseif (stristr($text, $word) !== false) {
return true;
}
@@ -123,7 +139,8 @@ class MessageFilter {
* - ?foo {} baz which will check if 'baz' is an array element in item.foo
* - ?foo {*} baz which will check if 'baz' is an array key in item.foo
* - ?foo which will check for a return of a true condition for item.foo;
*
* - ?!foo which will check for a return of a false condition for item.foo;
*
* The values 0, '', an empty array, and an unset value will all evaluate to false.
*
* @param string $s
@@ -205,6 +222,15 @@ class MessageFilter {
return false;
}
// Ordering of this check (for falsiness) with relation to the following one (check for truthiness) is important.
if (preg_match('/\!(.*?)$/', $s, $matches)) {
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
if (!$x) {
return true;
}
return false;
}
if (preg_match('/(.*?)$/', $s, $matches)) {
$x = ((array_key_exists(trim($matches[1]),$item)) ? $item[trim($matches[1])] : EMPTY_STR);
if ($x) {

34
Zotlabs/Lib/Multibase.php Normal file
View File

@@ -0,0 +1,34 @@
<?php
namespace Zotlabs\Lib;
use StephenHill\Base58;
class Multibase {
protected $key = null;
public function __construct() {
return $this;
}
public function publicKey($key) {
$base58 = new Base58();
$raw = hex2bin('ed01') . sodium_base642bin($key, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
return 'z' . $base58->encode($raw);
}
public function secretKey($key) {
$base58 = new Base58();
$raw = hex2bin('8026') . sodium_base642bin($key, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
return 'z' . $base58->encode($raw);
}
public function decode($key, $binary = false) {
$base58 = new Base58();
$key = substr($key,1);
$raw = $base58->decode($key);
$binaryKey = substr($raw, 2);
return $binary ? $binaryKey : sodium_bin2base64($binaryKey, SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING);
}
}

View File

@@ -1,322 +0,0 @@
<?php
namespace Zotlabs\Lib;
use Zotlabs\Lib\Libsync;
define ( 'NWIKI_ITEM_RESOURCE_TYPE', 'nwiki' );
class NativeWiki {
public static function listwikis($channel, $observer_hash) {
$sql_extra = item_permissions_sql($channel['channel_id'], $observer_hash);
$wikis = q("SELECT * FROM item
WHERE resource_type = '%s' AND mid = parent_mid AND uid = %d AND item_deleted = 0 $sql_extra",
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
intval($channel['channel_id'])
);
if($wikis) {
foreach($wikis as &$w) {
$w['json_allow_cid'] = acl2json($w['allow_cid']);
$w['json_allow_gid'] = acl2json($w['allow_gid']);
$w['json_deny_cid'] = acl2json($w['deny_cid']);
$w['json_deny_gid'] = acl2json($w['deny_gid']);
$w['rawName'] = get_iconfig($w, 'wiki', 'rawName');
$w['htmlName'] = escape_tags($w['rawName']);
//$w['urlName'] = urlencode(urlencode($w['rawName']));
$w['urlName'] = self::name_encode($w['rawName']);
$w['mimeType'] = get_iconfig($w, 'wiki', 'mimeType');
$w['typelock'] = get_iconfig($w, 'wiki', 'typelock');
$w['lockstate'] = (($w['allow_cid'] || $w['allow_gid'] || $w['deny_cid'] || $w['deny_gid']) ? 'lock' : 'unlock');
}
}
// TODO: query db for wikis the observer can access. Return with two lists, for read and write access
return array('wikis' => $wikis);
}
public static function create_wiki($channel, $observer_hash, $wiki, $acl) {
$resource_id = new_uuid();
$uuid = new_uuid();
$ac = $acl->get();
$mid = z_root() . '/item/' . $uuid;
$arr = array(); // Initialize the array of parameters for the post
$item_hidden = ((intval($wiki['postVisible']) === 0) ? 1 : 0);
$wiki_url = z_root() . '/wiki/' . $channel['channel_address'] . '/' . $wiki['urlName'];
$arr['aid'] = $channel['channel_account_id'];
$arr['uuid'] = $uuid;
$arr['uid'] = $channel['channel_id'];
$arr['mid'] = $mid;
$arr['parent_mid'] = $mid;
$arr['item_hidden'] = $item_hidden;
$arr['resource_type'] = NWIKI_ITEM_RESOURCE_TYPE;
$arr['resource_id'] = $resource_id;
$arr['owner_xchan'] = $channel['channel_hash'];
$arr['author_xchan'] = $observer_hash;
$arr['plink'] = $mid;
$arr['llink'] = z_root() . '/display/' . gen_link_id($mid);
$arr['title'] = $wiki['htmlName']; // name of new wiki;
$arr['allow_cid'] = $ac['allow_cid'];
$arr['allow_gid'] = $ac['allow_gid'];
$arr['deny_cid'] = $ac['deny_cid'];
$arr['deny_gid'] = $ac['deny_gid'];
$arr['item_wall'] = 1;
$arr['item_origin'] = 1;
$arr['item_thread_top'] = 1;
$arr['item_private'] = intval($acl->is_private());
$arr['verb'] = ACTIVITY_CREATE;
$arr['obj_type'] = 'Document';
$arr['body'] = '[table][tr][td][h1]New Wiki[/h1][/td][/tr][tr][td][zrl=' . $wiki_url . ']' . $wiki['htmlName'] . '[/zrl][/td][/tr][/table]';
$arr['public_policy'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_wiki'),true);
// Save the wiki name information using iconfig. This is shareable.
if(! set_iconfig($arr, 'wiki', 'rawName', $wiki['rawName'], true)) {
return array('item' => null, 'success' => false);
}
if(! set_iconfig($arr, 'wiki', 'mimeType', $wiki['mimeType'], true)) {
return array('item' => null, 'success' => false);
}
set_iconfig($arr,'wiki','typelock',$wiki['typelock'],true);
$post = item_store($arr);
$item_id = $post['item_id'];
if($item_id) {
\Zotlabs\Daemon\Master::Summon(array('Notifier', 'activity', $item_id));
return array('item' => $post['item'], 'item_id' => $item_id, 'success' => true);
}
else {
return array('item' => null, 'success' => false);
}
}
public static function update_wiki($channel_id, $observer_hash, $arr, $acl) {
$w = self::get_wiki($channel_id, $observer_hash, $arr['resource_id']);
$item = $w['wiki'];
if(! $item) {
return array('item' => null, 'success' => false);
}
$x = $acl->get();
$item['allow_cid'] = $x['allow_cid'];
$item['allow_gid'] = $x['allow_gid'];
$item['deny_cid'] = $x['deny_cid'];
$item['deny_gid'] = $x['deny_gid'];
$item['item_private'] = intval($acl->is_private());
$update_title = false;
if($item['title'] !== $arr['updateRawName']) {
$update_title = true;
$item['title'] = $arr['updateRawName'];
}
$update = item_store_update($item);
$item_id = $update['item_id'];
// update acl for any existing wiki pages
q("update item set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d where resource_type = 'nwikipage' and resource_id = '%s'",
dbesc($item['allow_cid']),
dbesc($item['allow_gid']),
dbesc($item['deny_cid']),
dbesc($item['deny_gid']),
dbesc($item['item_private']),
dbesc($arr['resource_id'])
);
if($update['item_id']) {
info( t('Wiki updated successfully'));
if($update_title) {
// Update the wiki name information using iconfig.
if(! set_iconfig($update['item_id'], 'wiki', 'rawName', $arr['updateRawName'], true)) {
return array('item' => null, 'success' => false);
}
}
return array('item' => $update['item'], 'item_id' => $update['item_id'], 'success' => $update['success']);
}
else {
return array('item' => null, 'success' => false);
}
}
public static function sync_a_wiki_item($uid,$id,$resource_id) {
$r = q("SELECT * from item WHERE uid = %d AND ( id = %d OR ( resource_type = '%s' and resource_id = '%s' )) ",
intval($uid),
intval($id),
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
dbesc($resource_id)
);
if($r) {
$q = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s'",
dbesc($r[0]['resource_id'])
);
if($q) {
$r = array_merge($r,$q);
}
xchan_query($r);
$sync_item = fetch_post_tags($r);
if($sync_item) {
$pkt = [];
foreach($sync_item as $w) {
$pkt[] = encode_item($w,true);
}
Libsync::build_sync_packet($uid,array('wiki' => $pkt));
}
}
}
public static function delete_wiki($channel_id,$observer_hash,$resource_id) {
$w = self::get_wiki($channel_id,$observer_hash,$resource_id);
if(! $w['wiki']) {
return [ 'success' => false ];
}
else {
$r = q("SELECT id FROM item WHERE uid = %s AND resource_id = '%s'",
intval($channel_id),
dbesc($resource_id)
);
$ids = array_column($r, 'id');
drop_items($ids, true, DROPITEM_PHASE1);
info(t('Wiki files deleted successfully'));
return [ 'success' => true ];
}
}
public static function get_wiki($channel_id, $observer_hash, $resource_id) {
$sql_extra = item_permissions_sql($channel_id,$observer_hash);
$item = q("SELECT * FROM item WHERE uid = %d AND resource_type = '%s' AND resource_id = '%s' AND item_deleted = 0
$sql_extra ORDER BY id LIMIT 1",
intval($channel_id),
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
dbesc($resource_id)
);
if(! $item) {
return [ 'wiki' => null ];
}
else {
$w = $item[0]; // wiki item table record
// Get wiki metadata
$rawName = get_iconfig($w, 'wiki', 'rawName');
$mimeType = get_iconfig($w, 'wiki', 'mimeType');
$typelock = get_iconfig($w, 'wiki', 'typelock');
return array(
'wiki' => $w,
'rawName' => $rawName,
'htmlName' => escape_tags($rawName),
//'urlName' => urlencode(urlencode($rawName)),
'urlName' => self::name_encode($rawName),
'mimeType' => $mimeType,
'typelock' => $typelock
);
}
}
public static function exists_by_name($uid, $urlName) {
$sql_extra = item_permissions_sql($uid);
$item = q("SELECT item.id, resource_id FROM item left join iconfig on iconfig.iid = item.id
WHERE resource_type = '%s' AND iconfig.v = '%s' AND uid = %d
AND item_deleted = 0 $sql_extra limit 1",
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
//dbesc(urldecode($urlName)),
dbesc(self::name_decode($urlName)),
intval($uid)
);
if($item) {
return array('id' => $item[0]['id'], 'resource_id' => $item[0]['resource_id']);
}
else {
return array('id' => null, 'resource_id' => null);
}
}
public static function get_permissions($resource_id, $owner_id, $observer_hash) {
// TODO: For now, only the owner can edit
$sql_extra = item_permissions_sql($owner_id, $observer_hash);
if(local_channel() && local_channel() == $owner_id) {
return [ 'read' => true, 'write' => true, 'success' => true ];
}
$r = q("SELECT * FROM item WHERE uid = %d and resource_type = '%s' AND resource_id = '%s' $sql_extra LIMIT 1",
intval($owner_id),
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
dbesc($resource_id)
);
if(! $r) {
return array('read' => false, 'write' => false, 'success' => true);
}
else {
$write = perm_is_allowed($owner_id, $observer_hash,'write_wiki');
return array('read' => true, 'write' => $write, 'success' => true);
}
}
public static function name_encode ($string) {
$string = html_entity_decode($string);
$encoding = mb_internal_encoding();
mb_internal_encoding("UTF-8");
$ret = mb_ereg_replace_callback ('[^A-Za-z0-9\-\_\.\~]',function ($char) {
$charhex = unpack('H*',$char[0]);
$ret = '('.$charhex[1].')';
return $ret;
}
,$string);
mb_internal_encoding($encoding);
return $ret;
}
public static function name_decode ($string) {
$encoding = mb_internal_encoding();
mb_internal_encoding("UTF-8");
$ret = mb_ereg_replace_callback ('(\(([0-9a-f]+)\))',function ($chars) {
return pack('H*',$chars[2]);
}
,$string);
mb_internal_encoding($encoding);
return $ret;
}
}

View File

@@ -1,725 +0,0 @@
<?php
namespace Zotlabs\Lib;
use App;
use Zotlabs\Access\PermissionLimits;
class NativeWikiPage {
static public function page_list($channel_id, $observer_hash, $resource_id) {
// TODO: Create item table records for pages so that metadata like title can be applied
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
$pages[] = [
'resource_id' => '',
'title' => 'Home',
'url' => 'Home',
'link_id' => 'id_wiki_home_0'
];
$sql_extra = item_permissions_sql($channel_id, $observer_hash);
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and item_deleted = 0
$sql_extra order by title asc",
dbesc($resource_id),
intval($channel_id)
);
if ($r) {
$x = [];
$y = [];
foreach ($r as $rv) {
if (!in_array($rv['mid'], $x)) {
$y[] = $rv;
$x[] = $rv['mid'];
}
}
$items = fetch_post_tags($y, true);
foreach ($items as $page_item) {
$title = get_iconfig($page_item['id'], 'nwikipage', 'pagetitle', t('(No Title)'));
if (urldecode($title) !== 'Home') {
$pages[] = [
'resource_id' => $resource_id,
'title' => escape_tags($title),
//'url' => str_replace('%2F','/',urlencode(str_replace('%2F','/',urlencode($title)))),
'url' => NativeWiki::name_encode($title),
'link_id' => 'id_' . substr($resource_id, 0, 10) . '_' . $page_item['id']
];
}
}
}
return ['pages' => $pages, 'wiki' => $w];
}
static public function create_page($channel, $observer_hash, $name, $resource_id, $mimetype = 'text/bbcode') {
logger('mimetype: ' . $mimetype);
if (!in_array($mimetype, ['text/markdown', 'text/bbcode', 'text/plain', 'text/html']))
$mimetype = 'text/markdown';
$w = NativeWiki::get_wiki($channel['channel_id'], $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
// backslashes won't work well in the javascript functions
$name = str_replace('\\', '', $name);
$uuid = new_uuid();
$mid = z_root() . '/item/' . $uuid;
// create an empty activity
$arr = [];
$arr['aid'] = $channel['channel_account_id'];
$arr['uid'] = $channel['channel_id'];
$arr['mid'] = $mid;
$arr['parent_mid'] = $w['wiki']['mid'];
$arr['parent'] = $w['wiki']['parent'];
$arr['uuid'] = $uuid;
$arr['item_hidden'] = $w['wiki']['item_hidden'];
$arr['plink'] = $mid;
$arr['llink'] = z_root() . '/display/' . gen_link_id($mid);
$arr['author_xchan'] = $observer_hash;
$arr['mimetype'] = $mimetype;
$arr['title'] = $name;
$arr['resource_type'] = 'nwikipage';
$arr['resource_id'] = $resource_id;
$arr['allow_cid'] = $w['wiki']['allow_cid'];
$arr['allow_gid'] = $w['wiki']['allow_gid'];
$arr['deny_cid'] = $w['wiki']['deny_cid'];
$arr['deny_gid'] = $w['wiki']['deny_gid'];
$arr['item_private'] = $w['wiki']['item_private'];
$arr['item_wall'] = 1;
$arr['item_origin'] = 1;
$arr['item_thread_top'] = 1;
$arr['verb'] = ACTIVITY_CREATE;
$arr['obj_type'] = 'Document';
// TODO: add an object?
$arr['public_policy'] = map_scope(PermissionLimits::Get($channel['channel_id'], 'view_wiki'), true);
// We may wish to change this some day.
$arr['item_unpublished'] = 1;
set_iconfig($arr, 'nwikipage', 'pagetitle', (($name) ? $name : t('(No Title)')), true);
$p = item_store($arr, false, false);
if ($p['item_id']) {
$page = [
'rawName' => $name,
'htmlName' => escape_tags($name),
//'urlName' => urlencode($name),
'urlName' => NativeWiki::name_encode($name)
];
return ['page' => $page, 'item_id' => $p['item_id'], 'item' => $p['activity'], 'wiki' => $w, 'message' => '', 'success' => true];
}
return ['success' => false, 'message' => t('Wiki page create failed.')];
}
static public function rename_page($arr) {
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$pageNewName = ((array_key_exists('pageNewName', $arr)) ? $arr['pageNewName'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['message' => t('Wiki not found.'), 'success' => false];
}
$ic = q("select * from iconfig left join item on iconfig.iid = item.id
where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageNewName)
);
if ($ic) {
return ['success' => false, 'message' => t('Destination name already exists')];
}
$ids = [];
$ic = q("select *, item.id as item_id from iconfig left join item on iconfig.iid = item.id
where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageUrlName)
);
if ($ic) {
foreach ($ic as $c) {
set_iconfig($c['item_id'], 'nwikipage', 'pagetitle', $pageNewName);
$ids[] = $c['item_id'];
}
$str_ids = implode(',', $ids);
q("update item set title = '%s' where id in ($str_ids)",
dbesc($pageNewName)
);
$page = [
'rawName' => $pageNewName,
'htmlName' => escape_tags($pageNewName),
//'urlName' => urlencode(escape_tags($pageNewName))
'urlName' => NativeWiki::name_encode($pageNewName)
];
return ['success' => true, 'page' => $page];
}
return ['success' => false, 'message' => t('Page not found')];
}
static public function get_page_content($arr) {
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? intval($arr['channel_id']) : 0);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$item = self::load_page($arr);
if ($item) {
$content = $item['body'];
return [
'content' => $content,
'mimeType' => $w['mimeType'],
'pageMimeType' => $item['mimetype'],
'message' => '',
'success' => true
];
}
return ['content' => null, 'message' => t('Error reading page content'), 'success' => false];
}
static public function page_history($arr) {
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['history' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$items = self::load_page_history($arr);
$history = [];
if ($items) {
$processed = 0;
foreach ($items as $item) {
if ($processed > 1000)
break;
$processed++;
$history[] = [
'revision' => $item['revision'],
'date' => datetime_convert('UTC', date_default_timezone_get(), $item['edited']),
'name' => $item['author']['xchan_name'],
'title' => get_iconfig($item, 'nwikipage', 'commit_msg')
];
}
return ['success' => true, 'history' => $history];
}
return ['success' => false];
}
static public function load_page($arr) {
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$revision = ((array_key_exists('revision', $arr)) ? $arr['revision'] : (-1));
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$ids = '';
$ic = q("select * from iconfig left join item on iconfig.iid = item.id where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageUrlName)
);
if ($ic) {
foreach ($ic as $c) {
if ($ids)
$ids .= ',';
$ids .= intval($c['iid']);
}
}
$sql_extra = item_permissions_sql($channel_id, $observer_hash);
if ($revision == (-1))
$sql_extra .= " order by revision desc ";
elseif ($revision)
$sql_extra .= " and revision = " . intval($revision) . " ";
$r = null;
if ($ids) {
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and id in ( $ids ) $sql_extra limit 1",
dbesc($resource_id),
intval($channel_id)
);
if ($r) {
$items = fetch_post_tags($r, true);
return $items[0];
}
}
return null;
}
static public function load_page_history($arr) {
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['content' => null, 'message' => 'Error reading wiki', 'success' => false];
}
$ids = '';
$ic = q("select * from iconfig left join item on iconfig.iid = item.id where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageUrlName)
);
if ($ic) {
foreach ($ic as $c) {
if ($ids)
$ids .= ',';
$ids .= intval($c['iid']);
}
}
$sql_extra = item_permissions_sql($channel_id, $observer_hash);
$sql_extra .= " order by revision desc ";
$r = null;
if ($ids) {
$r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and id in ( $ids ) and item_deleted = 0 $sql_extra",
dbesc($resource_id),
intval($channel_id)
);
if ($r) {
xchan_query($r);
$items = fetch_post_tags($r, true);
return $items;
}
}
return null;
}
static public function save_page($arr) {
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$content = ((array_key_exists('content', $arr)) ? $arr['content'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['message' => t('Error reading wiki'), 'success' => false];
}
// fetch the most recently saved revision.
$item = self::load_page($arr);
if (!$item) {
return ['message' => t('Page not found'), 'success' => false];
}
$mimetype = $item['mimetype'];
// change just the fields we need to change to create a revision;
unset($item['id']);
unset($item['author']);
$item['parent'] = 0;
$item['body'] = $content;
$item['author_xchan'] = $observer_hash;
$item['revision'] = (($arr['revision']) ? intval($arr['revision']) + 1 : intval($item['revision']) + 1);
$item['edited'] = datetime_convert();
$item['mimetype'] = $mimetype;
if ($item['iconfig'] && is_array($item['iconfig']) && count($item['iconfig'])) {
for ($x = 0; $x < count($item['iconfig']); $x++) {
unset($item['iconfig'][$x]['id']);
unset($item['iconfig'][$x]['iid']);
}
}
$ret = item_store($item, false, false);
if ($ret['item_id'])
return ['message' => '', 'item_id' => $ret['item_id'], 'filename' => $pageUrlName, 'success' => true];
else
return ['message' => t('Page update failed.'), 'success' => false];
}
static public function delete_page($arr) {
$pageUrlName = (array_key_exists('pageUrlName', $arr) ? $arr['pageUrlName'] : '');
$resource_id = (array_key_exists('resource_id', $arr) ? $arr['resource_id'] : '');
$observer_hash = (array_key_exists('observer_hash', $arr) ? $arr['observer_hash'] : '');
$channel_id = (array_key_exists('channel_id', $arr) ? $arr['channel_id'] : 0);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['success' => false, 'message' => t('Error reading wiki')];
}
$ids = [];
$ic = q("select * from iconfig left join item on iconfig.iid = item.id
where uid = %d and cat = 'nwikipage' and k = 'pagetitle' and v = '%s'",
intval($channel_id),
dbesc($pageUrlName)
);
if ($ic) {
foreach ($ic as $c) {
$ids[] = intval($c['iid']);
}
}
if ($ids) {
drop_items($ids, true, DROPITEM_PHASE1);
return ['success' => true];
}
return ['success' => false, 'message' => t('Nothing deleted')];
}
static public function revert_page($arr) {
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$commitHash = ((array_key_exists('commitHash', $arr)) ? $arr['commitHash'] : null);
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
if (!$commitHash) {
return ['message' => 'No commit was provided', 'success' => false];
}
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['message' => 'Error reading wiki', 'success' => false];
}
$x = $arr;
if (intval($commitHash) > 0) {
unset($x['commitHash']);
$x['revision'] = intval($commitHash) - 1;
$loaded = self::load_page($x);
if ($loaded) {
$content = $loaded['body'];
return ['content' => $content, 'success' => true];
}
return ['success' => false];
}
}
static public function compare_page($arr) {
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$compareCommit = ((array_key_exists('compareCommit', $arr)) ? $arr['compareCommit'] : 0);
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['message' => t('Error reading wiki'), 'success' => false];
}
$x = $arr;
$x['revision'] = (-1);
$currpage = self::load_page($x);
if ($currpage)
$currentContent = $currpage['body'];
$x['revision'] = $compareCommit;
$comppage = self::load_page($x);
if ($comppage)
$compareContent = $comppage['body'];
if ($currpage && $comppage) {
require_once('library/class.Diff.php');
$diff = \Diff::toTable(\Diff::compare($currentContent, $compareContent));
return ['success' => true, 'diff' => $diff];
}
return ['success' => false, 'message' => t('Compare: object not found.')];
}
static public function commit($arr) {
$commit_msg = ((array_key_exists('commit_msg', $arr)) ? $arr['commit_msg'] : t('Page updated'));
$observer_hash = ((array_key_exists('observer_hash', $arr)) ? $arr['observer_hash'] : '');
$channel_id = ((array_key_exists('channel_id', $arr)) ? $arr['channel_id'] : 0);
if (array_key_exists('resource_id', $arr)) {
$resource_id = $arr['resource_id'];
}
else {
return ['message' => t('Wiki resource_id required for git commit'), 'success' => false];
}
$w = NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id);
if (!$w['wiki']) {
return ['message' => t('Error reading wiki'), 'success' => false];
}
$page = self::load_page($arr);
if ($page) {
set_iconfig($page['id'], 'nwikipage', 'commit_msg', escape_tags($commit_msg), true);
return ['success' => true, 'item_id' => $page['id'], 'page' => $page];
}
return ['success' => false, 'message' => t('Page not found.')];
}
static public function convert_links($s, $wikiURL) {
if (strpos($s, '[[') !== false) {
preg_match_all("/\[\[(.*?)\]\]/", $s, $match);
$pages = $pageURLs = [];
foreach ($match[1] as $m) {
// TODO: Why do we need to double urlencode for this to work?
//$pageURLs[] = urlencode(urlencode(escape_tags($m)));
$titleUri = explode('|', $m);
$page = $titleUri[0] ?? '';
$title = $titleUri[1] ?? $page;
$pageURLs[] = NativeWiki::name_encode(escape_tags($page));
$pages[] = $title;
}
$idx = 0;
while (strpos($s, '[[') !== false) {
$replace = '<a href="' . $wikiURL . '/' . $pageURLs[$idx] . '">' . $pages[$idx] . '</a>';
$s = preg_replace("/\[\[(.*?)\]\]/", $replace, $s, 1);
$idx++;
}
}
return $s;
}
static public function render_page_history($arr) {
$pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : '');
$pageHistory = self::page_history([
'channel_id' => App::$profile_uid,
'observer_hash' => get_observer_hash(),
'resource_id' => $resource_id,
'pageUrlName' => $pageUrlName
]);
return replace_macros(get_markup_template('nwiki_page_history.tpl'), [
'$pageHistory' => $pageHistory['history'],
'$permsWrite' => $arr['permsWrite'],
'$name_lbl' => t('Name'),
'$msg_label' => t('Message', 'wiki_history'),
'$date_lbl' => t('Date'),
'$revert_btn' => t('Revert'),
'$compare_btn' => t('Compare')
]);
}
/**
* Replace the instances of the string [toc] with a list element that will be populated by
* a table of contents by the JavaScript library
* @param string $s
* @return string
*/
static public function generate_toc($s) {
if (strpos($s, '[toc]') !== false) {
//$toc_md = wiki_toc($s); // Generate Markdown-formatted list prior to HTML render
$toc_md = '<ul id="wiki-toc"></ul>'; // use the available jQuery plugin http://ndabas.github.io/toc/
$s = preg_replace("/\[toc\]/", $toc_md, $s, -1);
}
return $s;
}
/**
* Converts a select set of bbcode tags. Much of the code is copied from include/bbcode.php
* @param string $s
* @return string
*/
static public function bbcode($s) {
$s = str_replace(['[baseurl]', '[sitename]'], [z_root(), get_config('system', 'sitename')], $s);
$s = preg_replace_callback("/\[observer\.language\=(.*?)\](.*?)\[\/observer\]/ism", 'oblanguage_callback', $s);
$s = preg_replace_callback("/\[observer\.language\!\=(.*?)\](.*?)\[\/observer\]/ism", 'oblanguage_necallback', $s);
$observer = App::get_observer();
if ($observer) {
$s1 = '<span class="bb_observer" title="' . t('Different viewers will see this text differently') . '">';
$s2 = '</span>';
$obsBaseURL = $observer['xchan_connurl'];
$obsBaseURL = preg_replace("/\/poco\/.*$/", '', $obsBaseURL);
$s = str_replace('[observer.baseurl]', $obsBaseURL, $s);
$s = str_replace('[observer.url]', $observer['xchan_url'], $s);
$s = str_replace('[observer.name]', $s1 . $observer['xchan_name'] . $s2, $s);
$s = str_replace('[observer.address]', $s1 . $observer['xchan_addr'] . $s2, $s);
$s = str_replace('[observer.webname]', substr($observer['xchan_addr'], 0, strpos($observer['xchan_addr'], '@')), $s);
$s = str_replace('[observer.photo]', '', $s);
}
else {
$s = str_replace('[observer.baseurl]', '', $s);
$s = str_replace('[observer.url]', '', $s);
$s = str_replace('[observer.name]', '', $s);
$s = str_replace('[observer.address]', '', $s);
$s = str_replace('[observer.webname]', '', $s);
$s = str_replace('[observer.photo]', '', $s);
}
return $s;
}
static public function get_file_ext($arr) {
if ($arr['mimetype'] === 'text/bbcode')
return '.bb';
elseif ($arr['mimetype'] === 'text/markdown')
return '.md';
elseif ($arr['mimetype'] === 'text/plain')
return '.txt';
}
// This function is derived from
// http://stackoverflow.com/questions/32068537/generate-table-of-contents-from-markdown-in-php
static public function toc($content) {
// ensure using only "\n" as line-break
$source = str_replace(["\r\n", "\r"], "\n", $content);
// look for markdown TOC items
preg_match_all(
'/^(?:=|-|#).*$/m',
$source,
$matches,
PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE
);
// preprocess: iterate matched lines to create an array of items
// where each item is an array(level, text)
$file_size = strlen($source);
foreach ($matches[0] as $item) {
$found_mark = substr($item[0], 0, 1);
if ($found_mark == '#') {
// text is the found item
$item_text = $item[0];
$item_level = strrpos($item_text, '#') + 1;
$item_text = substr($item_text, $item_level);
}
else {
// text is the previous line (empty if <hr>)
$item_offset = $item[1];
$prev_line_offset = strrpos($source, "\n", -($file_size - $item_offset + 2));
$item_text =
substr($source, $prev_line_offset, $item_offset - $prev_line_offset - 1);
$item_text = trim($item_text);
$item_level = $found_mark == '=' ? 1 : 2;
}
if (!trim($item_text) or strpos($item_text, '|') !== FALSE) {
// item is an horizontal separator or a table header, don't mind
continue;
}
$raw_toc[] = ['level' => $item_level, 'text' => trim($item_text)];
}
$o = '';
foreach ($raw_toc as $t) {
$level = intval($t['level']);
$text = $t['text'];
switch ($level) {
case 1:
$li = '* ';
break;
case 2:
$li = ' * ';
break;
case 3:
$li = ' * ';
break;
case 4:
$li = ' * ';
break;
default:
$li = '* ';
break;
}
$o .= $li . $text . "\n";
}
return $o;
}
}

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),
@@ -65,16 +64,38 @@ class Queue {
);
}
static function remove($id,$channel_id = 0) {
logger('queue: remove queue item ' . $id,LOGGER_DEBUG);
public static function remove($id, $channel_id = 0) {
logger('queue: remove queue item ' . $id, LOGGER_DEBUG);
$sql_extra = (($channel_id) ? " and outq_channel = " . intval($channel_id) . " " : '');
q("DELETE FROM outq WHERE outq_hash = '%s' $sql_extra",
// figure out what endpoint it is going to.
$record = q("select outq_posturl from outq where outq_hash = '%s' $sql_extra",
dbesc($id)
);
}
if ($record) {
q("DELETE FROM outq WHERE outq_hash = '%s' $sql_extra",
dbesc($id)
);
// If there's anything remaining in the queue for this site, move one of them to the next active
// queue run by setting outq_scheduled back to the present. We may be attempting to deliver it
// as a 'piled_up' delivery, but this ensures the site has an active queue entry as long as queued
// 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.
$r = q("SELECT outq_hash, outq_posturl FROM outq WHERE outq_posturl = '%s' LIMIT 1",
dbesc($record[0]['outq_posturl'])
);
if ($r) {
$hashes = ids_to_querystr($r, 'outq_hash', true);
$x = q("UPDATE outq SET outq_scheduled = '%s' WHERE outq_hash IN ($hashes)",
dbesc(datetime_convert())
);
}
}
}
static function remove_by_posturl($posturl) {
logger('queue: remove queue posturl ' . $posturl,LOGGER_DEBUG);
@@ -84,8 +105,6 @@ class Queue {
);
}
static function set_delivered($id,$channel = 0) {
logger('queue: set delivered ' . $id,LOGGER_DEBUG);
$sql_extra = (($channel['channel_id']) ? " and outq_channel = " . intval($channel['channel_id']) . " " : '');
@@ -110,21 +129,30 @@ class Queue {
return false;
}
$hash = $arr['hash'] ?? '';
$account_id = $arr['account_id'] ?? 0;
$channel_id = $arr['channel_id'] ?? 0;
$driver = $arr['driver'] ?? 'zot6';
$posturl = $arr['posturl'] ?? '';
$priority = $arr['priority'] ?? 0;
$notify = $arr['notify'] ?? '';
$msg = $arr['msg'] ?? '';
$x = q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_priority,
outq_created, outq_updated, outq_scheduled, outq_notify, outq_msg )
values ( '%s', %d, %d, '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s' )",
dbesc($arr['hash']),
intval($arr['account_id']),
intval($arr['channel_id']),
dbesc(($arr['driver']) ? $arr['driver'] : 'zot6'),
dbesc($arr['posturl']),
dbesc($hash),
intval($account_id),
intval($channel_id),
dbesc($driver),
dbesc($posturl),
intval(1),
intval(isset($arr['priority']) ? $arr['priority'] : 0),
intval($priority),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc($arr['notify']),
dbesc(($arr['msg']) ? $arr['msg'] : '')
dbesc($notify),
dbesc($msg)
);
return $x;
@@ -143,17 +171,19 @@ class Queue {
$y = q("select site_update, site_dead from site where site_url = '%s' ",
dbesc($base)
);
if($y) {
if(intval($y[0]['site_dead'])) {
if ($y) {
// Don't bother delivering if the site is dead.
// And if we haven't heard from the site in over a month - let them through but 3 strikes you're out.
if (intval($y[0]['site_dead']) || ($y[0]['site_update'] < datetime_convert('UTC', 'UTC', 'now - 1 month') && $outq['outq_priority'] > 20)) {
q("update dreport set dreport_result = '%s' where dreport_queue = '%s'",
dbesc('site dead'),
dbesc($outq['outq_hash'])
);
self::remove_by_posturl($outq['outq_posturl']);
logger('dead site ignored ' . $base);
return;
}
if($y[0]['site_update'] < datetime_convert('UTC','UTC','now - 1 month')) {
self::update($outq['outq_hash'], 10);
logger('immediate delivery deferred for site ' . $base);
return;
}
}
else {
@@ -202,7 +232,7 @@ class Queue {
if($channel && $base) {
$h = q("SELECT hubloc_sitekey, site_crypto FROM hubloc LEFT JOIN site ON hubloc_url = site_url
WHERE site_url = '%s' AND hubloc_network = 'zot6' ORDER BY hubloc_id DESC LIMIT 1",
WHERE site_url = '%s' AND hubloc_network = 'zot6' AND hubloc_deleted = 0 ORDER BY hubloc_primary DESC, hubloc_id DESC LIMIT 1",
dbesc($base)
);
if($h) {
@@ -216,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']);

384
Zotlabs/Lib/QueueWorker.php Normal file
View File

@@ -0,0 +1,384 @@
<?php
namespace Zotlabs\Lib;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\Exception\UnableToBuildUuidException;
class QueueWorker {
public static $queueworker = null;
public static $maxworkers = 0;
public static $workermaxage = 0;
public static $workersleep = 100;
public static $default_priorities = [
'Notifier' => 10,
'Deliver' => 10,
'Cache_query' => 10,
'Content_importer' => 1,
'File_importer' => 1,
'Channel_purge' => 1,
'Directory' => 1
];
// Exceptions for processtimeout ($workermaxage) value.
// Currently the value is overriden with 3600 seconds (1h).
public static $long_running_cmd = [
'Queue',
'Expire'
];
private static function qstart() {
q('START TRANSACTION');
}
private static function qcommit() {
q("COMMIT");
}
private static function qrollback() {
q("ROLLBACK");
}
public static function Summon($argv) {
if ($argv[0] !== 'Queueworker') {
$priority = 0; // @TODO allow reprioritization
if (isset(self::$default_priorities[$argv[0]])) {
$priority = self::$default_priorities[$argv[0]];
}
$workinfo = ['argc' => count($argv), 'argv' => $argv];
$workinfo_json = json_encode($workinfo);
$uuid = self::getUuid($workinfo_json);
$r = q("SELECT * FROM workerq WHERE workerq_uuid = '%s'",
dbesc($uuid)
);
if ($r) {
logger("Summon: Ignoring duplicate workerq task", LOGGER_DEBUG);
logger(print_r($workinfo, true));
return;
}
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),
$workinfo_json,
dbesc($uuid),
dbesc($argv[0])
);
if (!$r) {
self::qrollback();
logger("INSERT FAILED", LOGGER_DEBUG);
return;
}
self::qcommit();
logger('INSERTED: ' . $workinfo_json, LOGGER_DEBUG);
}
$workers = self::GetWorkerCount();
if ($workers < self::$maxworkers) {
logger($workers . '/' . self::$maxworkers . ' workers active', LOGGER_DEBUG);
$phpbin = get_config('system', 'phpbin', 'php');
proc_run($phpbin, 'Zotlabs/Daemon/Master.php', ['Queueworker']);
}
}
public static function Release($argv) {
if ($argv[0] !== 'Queueworker') {
$priority = 0; // @TODO allow reprioritization
if (isset(self::$default_priorities[$argv[0]])) {
$priority = self::$default_priorities[$argv[0]];
}
$workinfo = ['argc' => count($argv), 'argv' => $argv];
$workinfo_json = json_encode($workinfo);
$uuid = self::getUuid($workinfo_json);
$r = q("SELECT * FROM workerq WHERE workerq_uuid = '%s'",
dbesc($uuid)
);
if ($r) {
logger("Release: Duplicate task - do not insert.", LOGGER_DEBUG);
logger(print_r($workinfo, true));
return;
}
self::qstart();
$r = q("INSERT INTO workerq (workerq_priority, workerq_data, workerq_uuid, workerq_cmd) VALUES (%d, '%s', '%s', '%s')",
intval($priority),
$workinfo_json,
dbesc($uuid),
dbesc($argv[0])
);
if (!$r) {
self::qrollback();
logger("Insert failed: " . $workinfo_json, LOGGER_DEBUG);
return;
}
self::qcommit();
logger('INSERTED: ' . $workinfo_json, LOGGER_DEBUG);
}
self::Process();
}
public static function GetWorkerCount() {
if (self::$maxworkers == 0) {
self::$maxworkers = get_config('queueworker', 'max_queueworkers', 4);
self::$maxworkers = self::$maxworkers > 3 ? self::$maxworkers : 4;
}
if (self::$workermaxage == 0) {
self::$workermaxage = get_config('queueworker', 'max_queueworker_age');
self::$workermaxage = self::$workermaxage > 120 ? self::$workermaxage : 300;
}
self::qstart();
// skip locked is preferred but is not supported by mariadb < 10.6 which is still used a lot - hence make it optional
$sql_quirks = ((get_config('system', 'db_skip_locked_supported')) ? 'SKIP LOCKED' : 'NOWAIT');
$r = q("SELECT workerq_id FROM workerq WHERE workerq_reservationid IS NOT NULL AND workerq_processtimeout < %s FOR UPDATE $sql_quirks",
db_utcnow()
);
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)");
}
self::qcommit();
//q("update workerq set workerq_reservationid = null where workerq_reservationid is not null and workerq_processtimeout < %s",
//db_utcnow()
//);
//usleep(self::$workersleep);
$workers = dbq("select count(*) as total from workerq where workerq_reservationid is not null");
logger("WORKERCOUNT: " . $workers[0]['total'], LOGGER_DEBUG);
return intval($workers[0]['total']);
}
public static function GetWorkerID() {
if (self::$queueworker) {
return self::$queueworker;
}
$wid = uniqid('', true);
//usleep(mt_rand(300000, 1000000)); //Sleep .3 - 1 seconds before creating a new worker.
$workers = self::GetWorkerCount();
if ($workers >= self::$maxworkers) {
logger("Too many active workers ($workers) max = " . self::$maxworkers, LOGGER_DEBUG);
return false;
}
self::$queueworker = $wid;
return $wid;
}
private static function getWorkId() {
self::GetWorkerCount();
self::qstart();
// skip locked is preferred but is not supported by mariadb < 10.6 which is still used a lot - hence make it optional
$sql_quirks = ((get_config('system', 'db_skip_locked_supported')) ? 'SKIP LOCKED' : 'NOWAIT');
$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::qrollback();
return false;
}
$id = $work[0]['workerq_id'];
$cmd = $work[0]['workerq_cmd'];
$age = self::$workermaxage;
if (in_array($cmd, self::$long_running_cmd)) {
$age = 3600; // 1h TODO: make this configurable
}
$work = q("UPDATE workerq SET workerq_reservationid = '%s', workerq_processtimeout = %s + INTERVAL %s WHERE workerq_id = %d",
self::$queueworker,
db_utcnow(),
db_quoteinterval($age . " SECOND"),
intval($id)
);
if (!$work) {
self::qrollback();
logger("Could not update workerq.", LOGGER_DEBUG);
return false;
}
logger("GOTWORK: " . json_encode($work), LOGGER_DEBUG);
self::qcommit();
return $id;
}
public static function Process() {
$sleep = intval(get_config('queueworker', 'queue_worker_sleep', 100));
$auto_queue_worker_sleep = get_config('queueworker', 'auto_queue_worker_sleep', 0);
if (!self::GetWorkerID()) {
if ($auto_queue_worker_sleep) {
set_config('queueworker', 'queue_worker_sleep', $sleep + 100);
}
logger('Unable to get worker ID. Exiting.', LOGGER_DEBUG);
killme();
}
if ($auto_queue_worker_sleep && $sleep > 100) {
$next_sleep = $sleep - 100;
set_config('queueworker', 'queue_worker_sleep', (($next_sleep < 100) ? 100 : $next_sleep));
}
$jobs = 0;
$workid = self::getWorkId();
$load_average_sleep = false;
self::$workersleep = $sleep;
self::$workersleep = ((intval(self::$workersleep) > 100) ? intval(self::$workersleep) : 100);
if (function_exists('sys_getloadavg') && get_config('queueworker', 'load_average_sleep')) {
// very experimental!
$load_average_sleep = true;
}
while ($workid) {
if ($load_average_sleep) {
$load_average = sys_getloadavg();
self::$workersleep = intval($load_average[0]) * 10000;
if (!self::$workersleep) {
self::$workersleep = 100;
}
}
logger('queue_worker_sleep: ' . self::$workersleep, LOGGER_DEBUG);
usleep(self::$workersleep);
$workitem = dbq("SELECT * FROM workerq WHERE workerq_id = $workid");
if ($workitem) {
// At least SOME work to do.... in case there's more, let's ramp up workers.
$workers = self::GetWorkerCount();
if ($workers < self::$maxworkers) {
logger($workers . '/' . self::$maxworkers . ' workers active', LOGGER_DEBUG);
$phpbin = get_config('system', 'phpbin', 'php');
proc_run($phpbin, 'Zotlabs/Daemon/Master.php', ['Queueworker']);
}
$jobs++;
logger("Workinfo: " . $workitem[0]['workerq_data'], LOGGER_DEBUG);
$workinfo = json_decode($workitem[0]['workerq_data'], true);
$argv = $workinfo['argv'];
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
$argv = flatten_array_recursive($argv);
$argc = count($argv);
$rnd = random_string(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.
// At some point we may want to test whether the run returns true/false
// and requeue the work to be tried again if needed. But we probably want
// to implement some sort of "retry interval" first.
dbq("delete from workerq where workerq_id = $workid");
}
else {
logger("NO WORKITEM!", LOGGER_DEBUG);
}
$workid = self::getWorkId();
}
logger('Master: Worker Thread: queue items processed:' . $jobs, LOGGER_DEBUG);
}
public static function ClearQueue() {
$work = q("select * from workerq");
while ($work) {
foreach ($work as $workitem) {
$workinfo = json_decode($workitem['v'], true);
$argc = $workinfo['argc'];
$argv = $workinfo['argv'];
logger('Master: process: ' . print_r($argv, true), LOGGER_ALL, LOG_DEBUG);
if (!isset($argv[0])) {
q("delete from workerq where workerq_id = %d",
$work[0]['workerq_id']
);
continue;
}
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
$cls::run($argc, $argv);
q("delete from workerq where workerq_id = %d",
$work[0]['workerq_id']
);
//Give the server .3 seconds to catch its breath between tasks.
//This will hopefully keep it from crashing to it's knees entirely
//if the last task ended up initiating other parallel processes
//(eg. polling remotes)
usleep(300000);
}
//Make sure nothing new came in
$work = q("select * from workerq");
}
}
/**
* @brief Generate a name-based v5 UUID with custom namespace
*
* @param string $data
* @return string $uuid
*/
private static function getUuid(string $data) {
$namespace = '3a112e42-f147-4ccf-a78b-f6841339ea2a';
try {
$uuid = Uuid::uuid5($namespace, $data)->toString();
} catch (UnableToBuildUuidException $e) {
logger('UUID generation failed');
return '';
}
return $uuid;
}
}

View File

@@ -112,7 +112,7 @@ class Share {
if(! $this->item)
return $bb;
$is_photo = (($this->item['obj_type'] === ACTIVITY_OBJ_PHOTO) ? true : false);
$is_photo = ((in_array($this->item['obj_type'], ['Image', ACTIVITY_OBJ_PHOTO])) ? true : false);
if($is_photo) {
$object = json_decode($this->item['obj'],true);
$photo_bb = $object['body'];

View File

@@ -16,13 +16,13 @@ class System {
}
static public function get_site_name() {
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['sitename'])
if(is_array(\App::$config) && is_array(\App::$config['system']) && isset(\App::$config['system']['sitename']))
return \App::$config['system']['sitename'];
return '';
}
static public function get_project_version() {
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['hide_version'])
if(is_array(\App::$config) && is_array(\App::$config['system']) && isset(\App::$config['system']['hide_version']))
return '';
if(is_array(\App::$config) && is_array(\App::$config['system']) && array_key_exists('std_version',\App::$config['system']))
return \App::$config['system']['std_version'];
@@ -31,33 +31,33 @@ class System {
}
static public function get_update_version() {
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['hide_version'])
if(is_array(\App::$config) && is_array(\App::$config['system']) && isset(\App::$config['system']['hide_version']))
return '';
return DB_UPDATE_VERSION;
}
static public function get_notify_icon() {
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['email_notify_icon_url'])
if(is_array(\App::$config) && is_array(\App::$config['system']) && isset(\App::$config['system']['email_notify_icon_url']))
return \App::$config['system']['email_notify_icon_url'];
return z_root() . DEFAULT_NOTIFY_ICON;
}
static public function get_site_icon() {
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['site_icon_url'])
if(is_array(\App::$config) && is_array(\App::$config['system']) && isset(\App::$config['system']['site_icon_url']))
return \App::$config['system']['site_icon_url'];
return z_root() . DEFAULT_PLATFORM_ICON ;
}
static public function get_project_link() {
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['project_link'])
if(is_array(\App::$config) && is_array(\App::$config['system']) && isset(\App::$config['system']['project_link']))
return \App::$config['system']['project_link'];
return 'https://hubzilla.org';
}
static public function get_project_srclink() {
if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['project_srclink'])
if(is_array(\App::$config) && is_array(\App::$config['system']) && isset(\App::$config['system']['project_srclink']))
return \App::$config['system']['project_srclink'];
return 'https://framagit.org/hubzilla/core.git';
}
@@ -68,7 +68,7 @@ class System {
static public function get_zot_revision() {
$x = [ 'revision' => ZOT_REVISION ];
$x = [ 'revision' => ZOT_REVISION ];
call_hooks('zot_revision',$x);
return $x['revision'];
}

24
Zotlabs/Lib/Text.php Normal file
View File

@@ -0,0 +1,24 @@
<?php
namespace Zotlabs\Lib;
class Text {
/**
* use this on "body" or "content" input where angle chars shouldn't be removed,
* and allow them to be safely displayed.
*
* @param string $string
*
* @return string
*/
public static function escape_tags(string $string): string {
if (!$string) {
return EMPTY_STR;
}
return htmlspecialchars($string, ENT_COMPAT, 'UTF-8', false);
}
}

View File

@@ -19,7 +19,7 @@ class ThreadItem {
private $comment_box_template = 'comment_item.tpl';
private $commentable = false;
// list of supported reaction emojis - a site can over-ride this via config system.reactions
private $reactions = ['1f60a','1f44f','1f37e','1f48b','1f61e','2665','1f606','1f62e','1f634','1f61c','1f607','1f608'];
private $reactions = ['slightly_smiling_face','clapping_hands','bottle_with_popping_cork','kiss_mark','disappointed_face','red_heart','grinning_face','astonished_face','sleeping_face','winking_face_with_tongue','smiling_face_with_halo','smiling_face_with_horns'];
private $toplevel = false;
private $children = array();
private $parent = null;
@@ -34,6 +34,7 @@ class ThreadItem {
private $channel = null;
private $display_mode = 'normal';
private $reload = '';
private $mid_uuid_map = [];
public function __construct($data) {
@@ -46,6 +47,7 @@ class ThreadItem {
// Prepare the children
if(isset($data['children'])) {
foreach($data['children'] as $item) {
/*
@@ -56,7 +58,6 @@ class ThreadItem {
continue;
}
$child = new ThreadItem($item);
$this->add_child($child);
}
@@ -65,6 +66,8 @@ class ThreadItem {
unset($this->data['children']);
}
// allow a site to configure the order and content of the reaction emoji list
if($this->toplevel) {
$x = get_config('system','reactions');
@@ -82,12 +85,10 @@ class ThreadItem {
* _ false on failure
*/
public function get_template_data($conv_responses, $thread_level=1, $conv_flags = []) {
$result = array();
$item = $this->get_data();
public function get_template_data($conv_responses, $mid_uuid_map, $thread_level=1, $conv_flags = []) {
$result = [];
$item = $this->get_data();
$commentww = '';
$sparkle = '';
$buttons = '';
@@ -98,12 +99,12 @@ class ThreadItem {
$is_item = false;
$osparkle = '';
$total_children = $this->count_descendants();
$unseen_comments = (($item['real_uid']) ? 0 : $this->count_unseen_descendants());
$unseen_comments = ((isset($item['real_uid']) && $item['real_uid']) ? 0 : $this->count_unseen_descendants());
$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()))
@@ -123,12 +124,14 @@ class ThreadItem {
$locktype = 0;
}
$shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && ($item['item_private'] != 1)) ? true : false);
$shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && (intval($item['item_private']) === 0)) ? true : false);
// allow an exemption for sharing stuff from your private feeds
if($item['author']['xchan_network'] === 'rss')
$shareable = true;
$repeatable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && (intval($item['item_private']) === 0) && (in_array($item['author']['xchan_network'], ['zot6', 'activitypub']))) ? true : false);
// @fixme
// Have recently added code to properly handle polls in group reshares by redirecting all of the poll responses to the group.
// Sharing a poll using a regular embedded share is harder because the poll will need to fork. This is due to comment permissions.
@@ -139,16 +142,10 @@ class ThreadItem {
$shareable = false;
}
$privacy_warning = false;
if(intval($item['item_private']) && ($item['owner']['xchan_network'] === 'activitypub')) {
$recips = get_iconfig($item['parent'], 'activitypub', 'recips');
if(! is_array($recips['to']) || ! in_array($observer['xchan_url'], $recips['to']))
$privacy_warning = true;
}
$privacy_warning = ($item['owner']['xchan_network'] === 'activitypub' && intval($item['item_private']) === 1);
if ($lock) {
if (($item['mid'] == $item['parent_mid']) && count(get_terms_oftype($item['term'],TERM_FORUM))) {
if (($item['mid'] == $item['parent_mid']) && isset($item['term']) && count(get_terms_oftype($item['term'], TERM_FORUM))) {
$privacy_warning = true;
$conv_flags['parent_privacy_warning'] = true;
}
@@ -162,24 +159,11 @@ class ThreadItem {
$mode = $conv->get_mode();
switch($item['item_type']) {
case ITEM_TYPE_CARD:
$edlink = 'card_edit';
break;
case ITEM_TYPE_ARTICLE:
$edlink = 'article_edit';
break;
default:
$edlink = 'editpost';
break;
}
if(local_channel() && $observer['xchan_hash'] === $item['author_xchan'])
$edpost = array(z_root() . '/' . $edlink . '/' . $item['id'], t('Edit'));
$edpost = array(z_root() . '/editpost/' . $item['id'], t('Edit'));
else
$edpost = false;
if($observer && $observer['xchan_hash']
&& ($observer['xchan_hash'] == $this->get_data_value('author_xchan')
|| $observer['xchan_hash'] == $this->get_data_value('owner_xchan')
@@ -193,7 +177,7 @@ class ThreadItem {
$dropping = false;
}
$drop = [];
if($dropping) {
$drop = array(
'dropping' => $dropping,
@@ -204,29 +188,26 @@ class ThreadItem {
$drop = [ 'dropping' => true, 'delete' => t('Admin Delete') ];
}
// FIXME
if($observer_is_pageowner) {
$multidrop = array(
'select' => t('Select'),
);
}
$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'];
$location = format_location($item);
$isevent = false;
$attend = null;
$canvote = false;
// process action responses - e.g. like/dislike/attend/agree/whatever
$response_verbs = array('like');
if(feature_enabled($conv->get_profile_owner(),'dislike'))
$response_verbs[] = 'like';
if(feature_enabled($conv->get_profile_owner(),'dislike')) {
$response_verbs[] = 'dislike';
if($item['obj_type'] === ACTIVITY_OBJ_EVENT) {
}
$response_verbs[] = 'announce';
if(in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) {
$response_verbs[] = 'attendyes';
$response_verbs[] = 'attendno';
$response_verbs[] = 'attendmaybe';
@@ -240,17 +221,6 @@ class ThreadItem {
$response_verbs[] = 'answer';
}
$consensus = (intval($item['item_consensus']) ? true : false);
if($consensus) {
$response_verbs[] = 'agree';
$response_verbs[] = 'disagree';
$response_verbs[] = 'abstain';
if($this->is_commentable() && $observer) {
$conlabels = array( t('I agree'), t('I disagree'), t('I abstain'));
$canvote = true;
}
}
if(! feature_enabled($conv->get_profile_owner(),'dislike'))
unset($conv_responses['dislike']);
@@ -258,9 +228,12 @@ class ThreadItem {
$my_responses = [];
foreach($response_verbs as $v) {
$my_responses[$v] = (($conv_responses[$v][$item['mid'] . '-m']) ? 1 : 0);
$my_responses[$v] = ((isset($conv_responses[$v][$item['mid'] . '-m'])) ? 1 : 0);
}
/*
$like_count = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid']] : '');
$like_list = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid'] . '-l'] : '');
if (($like_list) && (count($like_list) > MAX_LIKERS)) {
@@ -271,6 +244,17 @@ class ThreadItem {
}
$like_button_label = tt('Like','Likes',$like_count,'noun');
$repeat_count = ((x($conv_responses['announce'],$item['mid'])) ? $conv_responses['announce'][$item['mid']] : '');
$repeat_list = ((x($conv_responses['announce'],$item['mid'])) ? $conv_responses['announce'][$item['mid'] . '-l'] : '');
if (($repeat_list) && (count($repeat_list) > MAX_LIKERS)) {
$repeat_list_part = array_slice($repeat_list, 0, MAX_LIKERS);
array_push($repeat_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#repeatModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>');
} else {
$repeat_list_part = '';
}
$repeat_button_label = tt('Repeat','Repeats',$repeat_count,'noun');
$showdislike = '';
if (feature_enabled($conv->get_profile_owner(),'dislike')) {
$dislike_count = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid']] : '');
$dislike_list = ((x($conv_responses['dislike'],$item['mid'])) ? $conv_responses['dislike'][$item['mid'] . '-l'] : '');
@@ -281,11 +265,12 @@ class ThreadItem {
} else {
$dislike_list_part = '';
}
$showdislike = ((x($conv_responses['dislike'],$item['mid'])) ? format_like($conv_responses['dislike'][$item['mid']],$conv_responses['dislike'][$item['mid'] . '-l'],'dislike',$item['mid']) : '');
}
$showlike = ((x($conv_responses['like'],$item['mid'])) ? format_like($conv_responses['like'][$item['mid']],$conv_responses['like'][$item['mid'] . '-l'],'like',$item['mid']) : '');
$showdislike = ((x($conv_responses['dislike'],$item['mid']) && feature_enabled($conv->get_profile_owner(),'dislike'))
? format_like($conv_responses['dislike'][$item['mid']],$conv_responses['dislike'][$item['mid'] . '-l'],'dislike',$item['mid']) : '');
*/
/*
* We should avoid doing this all the time, but it depends on the conversation mode
@@ -296,14 +281,11 @@ class ThreadItem {
$this->check_wall_to_wall();
if($this->is_toplevel()) {
// FIXME check this permission
if(($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) {
$star = array(
if((local_channel() && $conv->get_profile_owner() === local_channel()) || (local_channel() && App::$module === 'pubstream')) {
$star = [
'toggle' => t("Toggle Star Status"),
'isstarred' => ((intval($item['item_starred'])) ? true : false),
);
];
}
}
else {
@@ -320,7 +302,7 @@ class ThreadItem {
$tagger = [];
// FIXME - check this permission
if($conv->get_profile_owner() == local_channel()) {
if(local_channel() && $conv->get_profile_owner() == local_channel()) {
/* disable until we agree on how to implemnt this in zot6/activitypub
$tagger = array(
'tagit' => t("Add Tag"),
@@ -332,7 +314,7 @@ class ThreadItem {
}
$has_bookmarks = false;
if(Apps::system_app_installed(local_channel(), 'Bookmarks') && is_array($item['term'])) {
if(Apps::system_app_installed(local_channel(), 'Bookmarks') && isset($item['term']) && is_array($item['term'])) {
foreach($item['term'] as $t) {
if(($t['ttype'] == TERM_BOOKMARK))
$has_bookmarks = true;
@@ -340,23 +322,27 @@ 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 = [];
$dislike = [];
$reply_to = [];
if($this->is_commentable() && $observer) {
$like = array( t("I like this \x28toggle\x29"), t("like"));
$dislike = array( t("I don't like this \x28toggle\x29"), t("dislike"));
$reply_to = array( t("Reply on this comment"), t("reply"), t("Reply to"));
}
$share = [];
$embed = [];
if ($shareable) {
// This actually turns out not to be possible in some protocol stacks without opening up hundreds of new issues.
// Will allow it only for uri resolvable sources.
if(strpos($item['mid'],'http') === 0) {
$share = []; //Not yet ready for primetime
//$share = array( t('Repeat This'), t('repeat'));
}
$embed = array( t('Share This'), t('share'));
$embed = [t('Share'), t('share')];
}
if ($repeatable) {
$share = [t('Repeat'), t('repeat')];
}
$dreport = '';
@@ -365,11 +351,13 @@ class ThreadItem {
if($keep_reports === 0)
$keep_reports = 10;
if((! get_config('system','disable_dreport')) && strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC',"now - $keep_reports days")) > 0) {
$dreport_link = '';
if((intval($item['item_type']) == ITEM_TYPE_POST) && (! get_config('system','disable_dreport')) && strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC',"now - $keep_reports days")) > 0) {
$dreport = t('Delivery Report');
$dreport_link = gen_link_id($item['mid']);
$dreport_link = '?mid=' . $item['mid'];
}
$is_new = false;
if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
$is_new = true;
@@ -385,8 +373,8 @@ class ThreadItem {
if($conv->get_mode() === 'channel')
$viewthread = z_root() . '/channel/' . $owner_address . '?f=&mid=' . urlencode(gen_link_id($item['mid']));
$comment_count_txt = sprintf( tt('%d comment','%d comments',$total_children),$total_children );
$list_unseen_txt = (($unseen_comments) ? sprintf( t('%d unseen'),$unseen_comments) : '');
$comment_count_txt = ['label' => sprintf(tt('%d comment', '%d comments', $total_children), $total_children), 'count' => $total_children];
$list_unseen_txt = $unseen_comments ? ['label' => sprintf(t('%d unseen'), $unseen_comments), 'count' => $unseen_comments] : [];
$children = $this->get_children();
@@ -396,8 +384,8 @@ class ThreadItem {
call_hooks('dropdown_extras',$dropdown_extras_arr);
$dropdown_extras = $dropdown_extras_arr['dropdown_extras'];
$midb64 = gen_link_id($item['mid']);
$mids = [ $midb64 ];
$midb64 = $item['uuid'];
$mids = [ $item['uuid'] ];
$response_mids = [];
foreach($response_verbs as $v) {
if(isset($conv_responses[$v]['mids'][$item['mid']])) {
@@ -439,9 +427,6 @@ class ThreadItem {
'author_is_group_actor' => (($item['author']['xchan_pubforum']) ? t('Forum') : ''),
'isevent' => $isevent,
'attend' => $attend,
'consensus' => $consensus,
'conlabels' => $conlabels,
'canvote' => $canvote,
'linktitle' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
'olinktitle' => (($item['owner']['xchan_addr']) ? $item['owner']['xchan_addr'] : $item['owner']['xchan_url']),
'llink' => $item['llink'],
@@ -510,38 +495,50 @@ class ThreadItem {
'bookmark' => (($conv->get_profile_owner() == local_channel() && local_channel() && $has_bookmarks) ? t('Save Bookmarks') : ''),
'addtocal' => (($has_event) ? t('Add to Calendar') : ''),
'drop' => $drop,
'multidrop' => ((feature_enabled($conv->get_profile_owner(),'multi_delete')) ? $multidrop : ''),
'dropdown_extras' => $dropdown_extras,
// end toolbar buttons
'unseen_comments' => $unseen_comments,
'comment_count' => $total_children,
'comment_count_txt' => $comment_count_txt,
'list_unseen_txt' => $list_unseen_txt,
'markseen' => t('Mark all seen'),
'markseen' => t('Mark all comments seen'),
'responses' => $responses,
'my_responses' => $my_responses,
/*
'like_count' => $like_count,
'like_list' => $like_list,
'like_list_part' => $like_list_part,
'like_button_label' => $like_button_label,
'like_modal_title' => t('Likes','noun'),
'repeat_count' => $repeat_count,
'repeat_list' => $repeat_list,
'repeat_list_part' => $repeat_list_part,
'repeat_button_label' => $repeat_button_label,
'repeat_modal_title' => t('Repeats','noun'),
'dislike_modal_title' => t('Dislikes','noun'),
'dislike_count' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_count : ''),
'dislike_list' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list : ''),
'dislike_list_part' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_list_part : ''),
'dislike_button_label' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike_button_label : ''),
*/
'modal_dismiss' => t('Close'),
'showlike' => $showlike,
'showdislike' => $showdislike,
'comment' => ($item['item_delayed'] ? '' : $this->get_comment_box($indent)),
// 'showlike' => $showlike,
// 'showdislike' => $showdislike,
'comment' => ($item['item_delayed'] ? '' : $this->get_comment_box()),
'previewing' => ($conv->is_preview() ? true : false ),
'preview_lbl' => t('This is an unsaved preview'),
'wait' => t('Please wait'),
'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'] : '')
'thr_parent_uuid' => (($item['parent_mid'] != $item['thr_parent']) ? $mid_uuid_map[$item['thr_parent']] : ''),
'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()),
);
$arr = array('item' => $item, 'output' => $tmp_item);
@@ -564,12 +561,12 @@ class ThreadItem {
if(($this->get_display_mode() === 'normal') && ($nb_children > 0)) {
foreach($children as $child) {
$result['children'][] = $child->get_template_data($conv_responses, $thread_level + 1,$conv_flags);
$result['children'][] = $child->get_template_data($conv_responses, $mid_uuid_map, $thread_level + 1,$conv_flags);
}
// Collapse
if(($nb_children > $visible_comments) || ($thread_level > 1)) {
$result['children'][0]['comment_firstcollapsed'] = true;
$result['children'][0]['num_comments'] = $comment_count_txt;
$result['children'][0]['num_comments'] = $comment_count_txt['label'];
$result['children'][0]['hide_text'] = sprintf( t('%s show all'), '<i class="fa fa-chevron-down"></i>');
if($thread_level > 1) {
$result['children'][$nb_children - 1]['comment_lastcollapsed'] = true;
@@ -646,7 +643,7 @@ class ThreadItem {
* Only add what will be displayed
*/
if(activity_match($item->get_data_value('verb'),ACTIVITY_LIKE) || activity_match($item->get_data_value('verb'),ACTIVITY_DISLIKE)) {
if(activity_match($item->get_data_value('verb'), ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
return false;
}
@@ -827,7 +824,7 @@ class ThreadItem {
* _ The comment box string (empty if no comment box)
* _ false on failure
*/
private function get_comment_box($indent) {
private function get_comment_box() {
if(!$this->is_toplevel() && !get_config('system','thread_allow')) {
return '';
@@ -873,7 +870,6 @@ class ThreadItem {
'$edurl' => t('Insert Link'),
'$edvideo' => t('Video'),
'$preview' => t('Preview'), // ((feature_enabled($conv->get_profile_owner(),'preview')) ? t('Preview') : ''),
'$indent' => $indent,
'$can_upload' => (perm_is_allowed($conv->get_profile_owner(),get_observer_hash(),'write_storage') && $conv->is_uploadable()),
'$feature_encrypt' => ((feature_enabled($conv->get_profile_owner(),'content_encrypt')) ? true : false),
'$encrypt' => t('Encrypt text'),
@@ -908,10 +904,16 @@ 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;
}
elseif($this->is_toplevel() && $this->get_data_value('verb') === 'Announce' && isset($this->data['source'])) {
$this->owner_url = chanlink_hash($this->data['source']['xchan_hash']);
$this->owner_photo = $this->data['source']['xchan_photo_s'];
$this->owner_name = $this->data['source']['xchan_name'];
$this->wall_to_wall = true;
}
}
private function is_wall_to_wall() {

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

@@ -69,12 +69,12 @@ class ThreadStream {
case 'cards':
$this->profile_owner = \App::$profile['profile_uid'];
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
$this->reload = $_SESSION['return_url'];
//$this->reload = $_SESSION['return_url'];
break;
case 'articles':
$this->profile_owner = \App::$profile['profile_uid'];
$this->writable = perm_is_allowed($this->profile_owner,$ob_hash,'post_comments');
$this->reload = $_SESSION['return_url'];
//$this->reload = $_SESSION['return_url'];
break;
case 'display':
// in this mode we set profile_owner after initialisation (from conversation()) and then
@@ -171,7 +171,7 @@ class ThreadStream {
*/
if(($item->get_data_value('id') != $item->get_data_value('parent')) && (activity_match($item->get_data_value('verb'),ACTIVITY_LIKE) || activity_match($item->get_data_value('verb'),ACTIVITY_DISLIKE))) {
if($item->get_data_value('id') != $item->get_data_value('parent') && activity_match($item->get_data_value('verb'), ['Like', 'Dislike', ACTIVITY_LIKE, ACTIVITY_DISLIKE])) {
return false;
}
@@ -211,7 +211,7 @@ class ThreadStream {
* _ The data requested on success
* _ false on failure
*/
public function get_template_data($conv_responses) {
public function get_template_data($conv_responses, $mid_uuid_map) {
$result = array();
foreach($this->threads as $item) {
@@ -220,7 +220,7 @@ class ThreadStream {
$item_data = $this->prepared_item;
}
else {
$item_data = $item->get_template_data($conv_responses);
$item_data = $item->get_template_data($conv_responses, $mid_uuid_map);
}
if(!$item_data) {
logger('Failed to get item template data ('. $item->get_id() .').', LOGGER_DEBUG, LOG_ERR);

View File

@@ -52,15 +52,21 @@ class Webfinger {
if(strpos($resource,'http') === 0) {
$m = parse_url($resource);
if($m) {
if($m['scheme'] !== 'https') {
return false;
}
self::$server = $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
}
else {
if (!$m) {
return false;
}
if(isset($m['scheme']) && $m['scheme'] !== 'https') {
return false;
}
if(!isset($m['host'])) {
return false;
}
self::$server = $m['host'] . ((isset($m['port'])) ? ':' . $m['port'] : '');
}
elseif(strpos($resource,'tag:') === 0) {
$arr = explode(':',$resource); // split the tag
@@ -86,7 +92,7 @@ class Webfinger {
/**
* @brief fetch a webfinger resource and return a zot6 discovery url if present
*
*/
*/
static function zot_url($resource) {

View File

@@ -162,7 +162,7 @@ class XConfig {
*/
static public function Delete($xchan, $family, $key) {
if(x(\App::$config[$xchan][$family], $key))
if(isset(\App::$config[$xchan][$family][$key]))
unset(\App::$config[$xchan][$family][$key]);
$ret = q("DELETE FROM xconfig WHERE xchan = '%s' AND cat = '%s' AND k = '%s'",

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

@@ -66,6 +66,11 @@ class Acl extends \Zotlabs\Web\Controller {
killme();
$permitted = [];
$sql_extra = '';
$sql_extra2 = '';
$sql_extra3 = '';
$sql_extra2_xchan = '';
$order_extra2 = '';
if(in_array($type, [ 'm', 'a', 'c', 'f' ])) {
@@ -81,7 +86,6 @@ class Acl extends \Zotlabs\Web\Controller {
}
if($search) {
$sql_extra = " AND pgrp.gname LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ";
$sql_extra2 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") ";
@@ -100,10 +104,6 @@ class Acl extends \Zotlabs\Web\Controller {
$sql_extra3 = "AND ( xchan_addr like " . protect_sprintf( "'%" . dbesc(punify($search)) . "%'" ) . " OR xchan_name like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ) ";
}
else {
$sql_extra = $sql_extra2 = $sql_extra3 = "";
}
$groups = array();
$contacts = array();
@@ -284,7 +284,7 @@ class Acl extends \Zotlabs\Web\Controller {
}
elseif($type == 'm') {
$r = array();
$z = q("SELECT xchan_hash as hash, xchan_name as name, xchan_network as net, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url
$z = q("SELECT abook_id as id, xchan_hash as hash, xchan_name as name, xchan_network as net, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url, abook_self
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d
and xchan_deleted = 0
@@ -304,7 +304,7 @@ class Acl extends \Zotlabs\Web\Controller {
}
elseif($type == 'a') {
$r = q("SELECT abook_id as id, xchan_name as name, xchan_network as net, xchan_hash as hash, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url, xchan_addr as attag , abook_their_perms FROM abook left join xchan on abook_xchan = xchan_hash
$r = q("SELECT abook_id as id, xchan_name as name, xchan_network as net, xchan_hash as hash, xchan_addr as nick, xchan_photo_s as micro, xchan_url as url, xchan_addr as attag, abook_their_perms, abook_self FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d
and xchan_deleted = 0
$sql_extra3
@@ -342,7 +342,7 @@ class Acl extends \Zotlabs\Web\Controller {
$x = [];
foreach($r as $g) {
if(in_array($g['net'],['rss','anon','unknown']) && ($type != 'a'))
if(isset($g['net']) && in_array($g['net'], ['rss','anon','unknown']) && ($type != 'a'))
continue;
$g['hash'] = urlencode($g['hash']);
@@ -378,12 +378,13 @@ class Acl extends \Zotlabs\Web\Controller {
"name" => $g['name'],
"id" => urlencode($g['id']),
"xid" => $g['hash'],
"url" => $g['url'],
"link" => $clink,
"nick" => ((strpos($g['nick'],'@')) ? substr($g['nick'],0,strpos($g['nick'],'@')) : $g['nick']),
"self" => (intval($g['abook_self']) ? 'abook-self' : ''),
"taggable" => '',
"label" => '',
"net" => $g['net']
"net" => $g['net'] ?? ''
);
}
}

View File

@@ -7,7 +7,6 @@ use Zotlabs\Web\Controller;
use Zotlabs\Daemon\Master;
use Zotlabs\Lib\Activity as ZlibActivity;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\LDSignatures;
use Zotlabs\Web\HTTPSig;
use Zotlabs\Lib\Libzot;
use Zotlabs\Lib\ThreadListener;
@@ -26,7 +25,7 @@ class Activity extends Controller {
$portable_id = EMPTY_STR;
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
$item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
dbesc(ACTIVITY_FOLLOW),
dbesc(ACTIVITY_UNFOLLOW)
);
@@ -155,22 +154,7 @@ class Activity extends Controller {
if(! $i)
http_status_exit(404, 'Not found');
$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);
}
@@ -182,7 +166,7 @@ class Activity extends Controller {
return;
}
$ob_authorise = false;
$ob_authorize = false;
$item_uid = 0;
$bear = ZlibActivity::token_from_request();
@@ -202,7 +186,7 @@ class Activity extends Controller {
}
}
$item_normal_extra = sprintf(" and not verb in ('%s', '%s') ",
$item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
dbesc(ACTIVITY_FOLLOW),
dbesc(ACTIVITY_UNFOLLOW)
);
@@ -260,25 +244,7 @@ class Activity extends Controller {
$channel = channelx_by_n($items[0]['uid']);
$x = array_merge( ['@context' => [
ACTIVITYSTREAMS_JSONLD_REV,
'https://w3id.org/security/v1',
z_root() . ZOT_APSCHEMA_REV
]], ZlibActivity::encode_activity($items[0],true));
$headers = [];
$headers['Content-Type'] = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ;
$x['signature'] = LDSignatures::sign($x,$channel);
$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,$channel['channel_prvkey'],channel_url($channel));
HTTPSig::set_headers($h);
echo $ret;
killme();
as_return_and_die(ZlibActivity::encode_activity($items[0]), $channel);
}
goaway(z_root() . '/item/' . argv(1));

View File

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

View File

@@ -77,6 +77,7 @@ class Addons {
} catch (\PHPGit\Exception\GitException $e) {
json_return_and_die(array('message' => 'Error updating addon repo.', 'success' => false));
}
break;
case 'removerepo':
if (array_key_exists('repoName', $_REQUEST)) {
$repoName = $_REQUEST['repoName'];
@@ -111,6 +112,7 @@ class Addons {
} else {
json_return_and_die(array('message' => 'Error deleting addon repo.', 'success' => false));
}
break;
case 'installrepo':
if (array_key_exists('repoURL', $_REQUEST)) {
require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies
@@ -172,6 +174,7 @@ class Addons {
$repo = $git->probeRepo();
json_return_and_die(array('repo' => $repo, 'message' => '', 'success' => true));
}
break;
case 'addrepo':
if (array_key_exists('repoURL', $_REQUEST)) {
require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies

View File

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

View File

@@ -5,11 +5,11 @@ namespace Zotlabs\Module\Admin;
class Dbsync {
function get() {
$o = '';
if(argc() > 3 && intval(argv(3)) && argv(2) === 'mark') {
// remove the old style config if it exists
del_config('database', 'update_r' . intval(argv(3)));
@@ -29,7 +29,7 @@ class Dbsync {
if(method_exists($c,'verify')) {
$retval = $c->verify();
if($retval === UPDATE_FAILED) {
$o .= sprintf( t('Verification of update %s failed. Check system logs.'), $s);
$o .= sprintf( t('Verification of update %s failed. Check system logs.'), $s);
}
elseif($retval === UPDATE_SUCCESS) {
$o .= sprintf( t('Update %s was successfully applied.'), $s);
@@ -44,20 +44,8 @@ class Dbsync {
}
else
$o .= sprintf( t('Update function %s could not be found.'), $s);
return $o;
// remove the old style config if it exists
del_config('database', 'update_r' . intval(argv(3)));
set_config('database', '_' . intval(argv(3)), 'success');
if(intval(get_config('system','db_version')) < intval(argv(3)))
set_config('system','db_version',intval(argv(3)));
info( t('Update has been marked successful') . EOL);
goaway(z_root() . '/admin/dbsync');
}
if(argc() > 2 && intval(argv(2))) {
@@ -68,7 +56,7 @@ class Dbsync {
$c = new $cls();
$retval = $c->run();
if($retval === UPDATE_FAILED) {
$o .= sprintf( t('Executing update procedure %s failed. Check system logs.'), $s);
$o .= sprintf( t('Executing update procedure %s failed. Check system logs.'), $s);
}
elseif($retval === UPDATE_SUCCESS) {
$o .= sprintf( t('Update %s was successfully applied.'), $s);
@@ -79,10 +67,10 @@ class Dbsync {
}
else
$o .= sprintf( t('Update function %s could not be found.'), $s);
return $o;
}
$failed = array();
$r = q("select * from config where cat = 'database' ");
if(count($r)) {
@@ -107,7 +95,7 @@ class Dbsync {
else {
return '<div class="generic-content-wrapper-styled"><h3>' . t('No failed updates.') . '</h3></div>';
}
return $o;
}
}
}

View File

@@ -12,18 +12,18 @@ class Queue {
$o = '';
$expert = ((array_key_exists('expert',$_REQUEST)) ? intval($_REQUEST['expert']) : 0);
$expert = $_REQUEST['expert'] ?? false;
if($_REQUEST['drophub']) {
if(isset($_REQUEST['drophub'])) {
hubloc_mark_as_down($_REQUEST['drophub']);
LibQueue::remove_by_posturl($_REQUEST['drophub']);
}
if($_REQUEST['emptyhub']) {
if(isset($_REQUEST['emptyhub'])) {
LibQueue::remove_by_posturl($_REQUEST['emptyhub']);
}
if($_REQUEST['deliverhub']) {
if(isset($_REQUEST['deliverhub'])) {
$hubq = q("SELECT * FROM outq WHERE outq_posturl = '%s'",
dbesc($_REQUEST['deliverhub'])
@@ -39,7 +39,6 @@ class Queue {
for($x = 0; $x < count($r); $x ++) {
$r[$x]['eurl'] = urlencode($r[$x]['outq_posturl']);
$r[$x]['connected'] = datetime_convert('UTC',date_default_timezone_get(),$r[$x]['connected'],'Y-m-d');
}
$o = replace_macros(get_markup_template('admin_queue.tpl'), array(

View File

@@ -0,0 +1,121 @@
<?php
namespace Zotlabs\Module\Admin;
use App;
use Zotlabs\Web\Controller;
class Queueworker extends Controller {
function init() {
}
function post() {
check_form_security_token('form_security_token', 'queueworker');
$maxqueueworkers = intval($_POST['queueworker_maxworkers']);
$maxqueueworkers = ($maxqueueworkers > 3) ? $maxqueueworkers : 4;
set_config('queueworker', 'max_queueworkers', $maxqueueworkers);
$maxworkerage = intval($_POST['queueworker_max_age']);
$maxworkerage = ($maxworkerage >= 120) ? $maxworkerage : 300;
set_config('queueworker', 'queueworker_max_age', $maxworkerage);
$queueworkersleep = intval($_POST['queue_worker_sleep']);
$queueworkersleep = ($queueworkersleep > 100) ? $queueworkersleep : 100;
set_config('queueworker', 'queue_worker_sleep', $queueworkersleep);
$auto_queue_worker_sleep = intval($_POST['auto_queue_worker_sleep']);
set_config('queueworker', 'auto_queue_worker_sleep', $auto_queue_worker_sleep);
goaway(z_root() . '/admin/queueworker');
}
function get() {
$content = "<H1>Queue Status</H1>\n";
$r = q('select count(*) as total from workerq');
$content .= "<H4>There are " . $r[0]['total'] . " queue items to be processed.</H4>";
$r = dbq("select count(*) as qworkers from workerq where workerq_reservationid is not null");
$content .= "<H4>Active workers: " . $r[0]['qworkers'] . "</H4>";
$r = dbq("select workerq_cmd, count(*) as total from workerq where true group by workerq_cmd");
if ($r) {
$content .= "<H4>Work items</H4>";
foreach($r as $rr) {
$content .= $rr['workerq_cmd'] . ': ' . $rr['total'] . '<br>';
}
}
$maxqueueworkers = get_config('queueworker', 'max_queueworkers', 4);
$maxqueueworkers = ($maxqueueworkers > 3) ? $maxqueueworkers : 4;
$sc = '';
$sc .= replace_macros(get_markup_template('field_input.tpl'), [
'$field' => [
'queueworker_maxworkers',
t('Max queueworker threads'),
$maxqueueworkers,
t('Minimum 4, default 4')
]
]);
$workermaxage = get_config('queueworker', 'queueworker_max_age');
$workermaxage = ($workermaxage >= 120) ? $workermaxage : 300;
$sc .= replace_macros(get_markup_template('field_input.tpl'), [
'$field' => [
'queueworker_max_age',
t('Assume workers dead after'),
$workermaxage,
t('Minimum 120, default 300 seconds')
]
]);
$queueworkersleep = get_config('queueworker', 'queue_worker_sleep');
$queueworkersleep = ($queueworkersleep > 100) ? $queueworkersleep : 100;
$auto_queue_worker_sleep = get_config('queueworker', 'auto_queue_worker_sleep', 0);
$sc .= replace_macros(get_markup_template('field_input.tpl'), [
'$field' => [
'queue_worker_sleep',
t('Pause before starting next task'),
$queueworkersleep,
t('Minimum 100, default 100 microseconds'),
'',
(($auto_queue_worker_sleep) ? 'disabled' : '')
]
]);
$sc .= replace_macros(get_markup_template('field_checkbox.tpl'), [
'$field' => [
'auto_queue_worker_sleep',
t('Automatically adjust pause before starting next task'),
$auto_queue_worker_sleep,
]
]);
$tpl = get_markup_template('settings_addon.tpl');
$content .= replace_macros($tpl, [
'$action_url' => 'admin/queueworker',
'$form_security_token' => get_form_security_token('queueworker'),
'$title' => t('Queueworker Settings'),
'$content' => $sc,
'$baseurl' => z_root(),
'$submit' => t('Save')
]
);
return $content;
}
}

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,9 +67,8 @@ 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);
$default_expire_days = ((array_key_exists('default_expire_days',$_POST)) ? intval($_POST['default_expire_days']) : 30);
$active_expire_days = ((array_key_exists('active_expire_days',$_POST)) ? intval($_POST['active_expire_days']) : 7);
$reply_address = ((array_key_exists('reply_address',$_POST) && trim($_POST['reply_address'])) ? trim($_POST['reply_address']) : 'noreply@' . \App::get_hostname());
@@ -100,7 +99,7 @@ class Site {
$reg_expire = (preg_match('/^[a-z]{1,1}$/', $regexpireu) ? $regexpiren . $regexpireu : '');
$imagick_path = ((x($_POST,'imagick_path')) ? trim($_POST['imagick_path']) : '');
$force_queue = ((intval($_POST['force_queue']) > 0) ? intval($_POST['force_queue']) : 3000);
//$force_queue = ((intval($_POST['force_queue']) > 0) ? intval($_POST['force_queue']) : 3000);
$pub_incl = escape_tags(trim($_POST['pub_incl']));
$pub_excl = escape_tags(trim($_POST['pub_excl']));
@@ -129,7 +128,7 @@ class Site {
set_config('system', 'register_duty', $this->register_duty);
set_config('system', 'register_duty_jso', $this->joo);
} else {
notice('ZAR0130E,'.t('Errors') . ': ' . $this->error) . EOL . $this->msgfg;
notice('ZAR0130E,' . t('Errors') . ': ' . $this->error . EOL . $this->msgfg . EOL);
}
}
}
@@ -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');
@@ -205,12 +204,7 @@ class Site {
set_config('system','disable_discover_tab', $disable_discover_tab);
set_config('system','site_firehose', $site_firehose);
set_config('system','open_pubstream', $open_pubstream);
set_config('system','force_queue_threshold', $force_queue);
if ($global_directory == '') {
del_config('system', 'directory_submit_url');
} else {
set_config('system', 'directory_submit_url', $global_directory);
}
//set_config('system','force_queue_threshold', $force_queue);
set_config('system','no_community_page', $no_community_page);
set_config('system','no_utf', $no_utf);
@@ -233,20 +227,6 @@ class Site {
*/
function get() {
/* Installed langs */
$lang_choices = array();
$langs = glob('view/*/hstrings.php');
if(is_array($langs) && count($langs)) {
if(! in_array('view/en/hstrings.php',$langs))
$langs[] = 'view/en/';
asort($langs);
foreach($langs as $l) {
$t = explode("/",$l);
$lang_choices[$t[1]] = $t[1];
}
}
/* Installed themes */
$theme_choices_mobile["---"] = t("Default");
$theme_choices = array();
@@ -283,7 +263,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 +281,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 +411,6 @@ 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),
'$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")),
@@ -508,10 +493,10 @@ class Site {
'$frontpage' => array('frontpage', t("Site homepage to show visitors (default: login box)"), get_config('system','frontpage'), t("example: 'pubstream' to show public stream, 'page/sys/home' to show a system webpage called 'home' or 'include:home.html' to include a file.")),
'$mirror_frontpage' => array('mirror_frontpage', t("Preserve site homepage URL"), get_config('system','mirror_frontpage'), t('Present the site homepage in a frame at the original location instead of redirecting')),
'$allowed_sites' => array('allowed_sites', t("Allowed friend domains"), get_config('system','allowed_sites'), t("Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains")),
'$force_publish' => array('publish_all', t("Force publish"), get_config('system','publish_all'), t("Check to force all profiles on this site to be listed in the site directory.")),
'$disable_discover_tab' => array('disable_discover_tab', t('Import Public Streams'), $discover_tab, t('Import and allow access to public content pulled from other sites. Warning: this content is unmoderated.')),
'$site_firehose' => array('site_firehose', t('Site only Public Streams'), get_config('system','site_firehose'), t('Allow access to public content originating only from this site if Imported Public Streams are disabled.')),
'$open_pubstream' => array('open_pubstream', t('Allow anybody on the internet to access the Public streams'), get_config('system','open_pubstream',1), t('Disable to require authentication before viewing. Warning: this content is unmoderated.')),
'$force_publish' => array('publish_all', t("Force publish"), get_config('system','publish_all'), t("Check to force all profiles on this site to be listed in the site directory")),
'$disable_discover_tab' => array('disable_discover_tab', t('Enable public stream'), $discover_tab, t('Enable the public stream. Warning: this content is unmoderated')),
'$site_firehose' => array('site_firehose', t('Site only public stream'), get_config('system','site_firehose'), t('Restrict the public stream to content originating at this site')),
'$open_pubstream' => array('open_pubstream', t('Allow anybody on the internet to access the public streams'), get_config('system','open_pubstream',1), t('Disable to require authentication before viewing')),
'$incl' => array('pub_incl',t('Only import Public stream posts with this text'), get_config('system','pubstream_incl'),t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')),
'$excl' => array('pub_excl',t('Do not import Public stream posts with this text'), get_config('system','pubstream_excl'),t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')),
@@ -532,11 +517,11 @@ class Site {
'$timeout' => array('timeout', t("Network timeout"), (x(get_config('system','curl_timeout'))?get_config('system','curl_timeout'):60), t("Value is in seconds. Set to 0 for unlimited (not recommended).")),
'$delivery_interval' => array('delivery_interval', t("Delivery interval"), (x(get_config('system','delivery_interval'))?get_config('system','delivery_interval'):2), t("Delay background delivery processes by this many seconds to reduce system load. Recommend: 4-5 for shared hosts, 2-3 for virtual private servers. 0-1 for large dedicated servers.")),
'$delivery_batch_count' => array('delivery_batch_count', t('Deliveries per process'),(x(get_config('system','delivery_batch_count'))?get_config('system','delivery_batch_count'):1), t("Number of deliveries to attempt in a single operating system process. Adjust if necessary to tune system performance. Recommend: 1-5.")),
'$force_queue' => array('force_queue', t("Queue Threshold"), get_config('system','force_queue_threshold',3000), t("Always defer immediate delivery if queue contains more than this number of entries.")),
//'$force_queue' => array('force_queue', t("Queue Threshold"), get_config('system','force_queue_threshold',3000), t("Always defer immediate delivery if queue contains more than this number of entries.")),
'$poll_interval' => array('poll_interval', t("Poll interval"), (x(get_config('system','poll_interval'))?get_config('system','poll_interval'):2), t("Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval.")),
'$imagick_path' => array('imagick_path', t("Path to ImageMagick convert program"), get_config('system','imagick_convert_path'), t("If set, use this program to generate photo thumbnails for huge images ( > 4000 pixels in either dimension), otherwise memory exhaustion may occur. Example: /usr/bin/convert")),
'$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")),
'$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content')),
'$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days', 30)), t('0 for no expiration of imported content')),
'$active_expire_days' => array('active_expire_days', t('Do not expire any posts which have comments less than this many days ago'), intval(get_config('system','active_expire_days',7)), ''),
'$sellpage' => array('site_sellpage', t('Public servers: Optional landing (marketing) webpage for new registrants'), get_config('system','sellpage',''), sprintf( t('Create this page first. Default is %s/register'),z_root())),
'$first_page' => array('first_page', t('Page to display after creating a new channel'), get_config('system','workflow_channel_next','profiles'), t('Default: profiles')),

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

@@ -24,42 +24,42 @@ class Api extends \Zotlabs\Web\Controller {
notice( t('Permission denied.') . EOL);
return;
}
}
function get() {
if(\App::$cmd === 'api/oauth/authorize'){
/*
/*
* api/oauth/authorize interact with the user. return a standard page
*/
\App::$page['template'] = 'minimal';
// get consumer/client from request token
try {
$request = \OAuth1Request::from_request();
}
catch(\Exception $e) {
logger('OAuth exception: ' . print_r($e,true));
// echo "<pre>"; var_dump($e);
// echo "<pre>"; var_dump($e);
killme();
}
if(x($_POST,'oauth_yes')){
$app = $this->oauth_get_client($request);
if (is_null($app))
if (is_null($app))
return "Invalid request. Unknown token.";
$consumer = new \OAuth1Consumer($app['client_id'], $app['pw'], $app['redirect_uri']);
$verifier = md5($app['secret'] . local_channel());
set_config('oauth', $verifier, local_channel());
if($consumer->callback_url != null) {
$params = $request->get_parameters();
$glue = '?';
@@ -68,28 +68,28 @@ class Api extends \Zotlabs\Web\Controller {
goaway($consumer->callback_url . $glue . "oauth_token=" . \OAuth1Util::urlencode_rfc3986($params['oauth_token']) . "&oauth_verifier=" . \OAuth1Util::urlencode_rfc3986($verifier));
killme();
}
$tpl = get_markup_template("oauth_authorize_done.tpl");
$o = replace_macros($tpl, array(
'$title' => t('Authorize application connection'),
'$info' => t('Return to your app and insert this Security Code:'),
'$code' => $verifier,
));
return $o;
}
if(! local_channel()) {
//TODO: we need login form to redirect to this page
notice( t('Please login to continue.') . EOL );
return login(false,'api-login',$request->get_parameters());
}
$app = $this->oauth_get_client($request);
if (is_null($app))
return "Invalid request. Unknown token.";
$tpl = get_markup_template('oauth_authorize.tpl');
$o = replace_macros($tpl, array(
'$title' => t('Authorize application connection'),
@@ -98,12 +98,12 @@ class Api extends \Zotlabs\Web\Controller {
'$yes' => t('Yes'),
'$no' => t('No'),
));
//echo "<pre>"; var_dump($app); killme();
return $o;
}
echo api_call();
killme();
}
@@ -112,8 +112,8 @@ class Api extends \Zotlabs\Web\Controller {
$params = $request->get_parameters();
$token = $params['oauth_token'];
$r = q("SELECT clients.* FROM clients, tokens WHERE clients.client_id = tokens.client_id
$r = q("SELECT clients.* FROM clients, tokens WHERE clients.client_id = tokens.client_id
AND tokens.id = '%s' AND tokens.auth_scope = 'request' ",
dbesc($token)
);
@@ -121,7 +121,7 @@ class Api extends \Zotlabs\Web\Controller {
return $r[0];
return null;
}
}

View File

@@ -13,7 +13,7 @@ class Appman extends \Zotlabs\Web\Controller {
if(! local_channel())
return;
if($_POST['url']) {
if(isset($_POST['url']) && $_POST['url']) {
$arr = array(
'uid' => intval($_REQUEST['uid']),
'url' => escape_tags($_REQUEST['url']),
@@ -50,7 +50,7 @@ class Appman extends \Zotlabs\Web\Controller {
return;
}
if($_POST['install']) {
if(isset($_POST['install']) && $_POST['install']) {
Apps::app_install(local_channel(),$papp);
if(Apps::app_installed(local_channel(),$papp))
info( t('App installed.') . EOL);
@@ -65,15 +65,15 @@ class Appman extends \Zotlabs\Web\Controller {
}
if (intval($sync[0]['app_system'])) {
Libsync::build_sync_packet($uid, ['sysapp' => $sync]);
Libsync::build_sync_packet(local_channel(), ['sysapp' => $sync]);
}
else {
Libsync::build_sync_packet($uid, ['app' => $sync]);
Libsync::build_sync_packet(local_channel(), ['app' => $sync]);
}
}
if($_POST['delete']) {
if(isset($_POST['delete']) && $_POST['delete']) {
// Fetch the app for sync before it is deleted (if it is deletable))
$sync = q("SELECT * FROM app WHERE app_channel = %d AND app_id = '%s' LIMIT 1",
@@ -91,18 +91,18 @@ class Appman extends \Zotlabs\Web\Controller {
$sync[0]['app_deleted'] = 1;
if (intval($sync[0]['app_system'])) {
Libsync::build_sync_packet($uid, ['sysapp' => $sync]);
Libsync::build_sync_packet(local_channel(), ['sysapp' => $sync]);
}
else {
Libsync::build_sync_packet($uid, ['app' => $sync]);
Libsync::build_sync_packet(local_channel(), ['app' => $sync]);
}
}
if($_POST['edit']) {
if(isset($_POST['edit']) && $_POST['edit']) {
return;
}
if($_POST['feature']) {
if(isset($_POST['feature']) && $_POST['feature']) {
Apps::app_feature(local_channel(), $papp, $_POST['feature']);
$sync = q("SELECT * FROM app WHERE app_channel = %d AND app_id = '%s' LIMIT 1",
@@ -110,15 +110,20 @@ class Appman extends \Zotlabs\Web\Controller {
dbesc($papp['guid'])
);
$sync[0]['term'] = q("select * from term where otype = %d and oid = %d",
intval(TERM_OBJ_APP),
intval($sync[0]['id'])
);
if (intval($sync[0]['app_system'])) {
Libsync::build_sync_packet($uid, ['sysapp' => $sync]);
Libsync::build_sync_packet(local_channel(), ['sysapp' => $sync]);
}
else {
Libsync::build_sync_packet($uid, ['app' => $sync]);
Libsync::build_sync_packet(local_channel(), ['app' => $sync]);
}
}
if($_POST['pin']) {
if(isset($_POST['pin']) && $_POST['pin']) {
Apps::app_feature(local_channel(), $papp, $_POST['pin']);
$sync = q("SELECT * FROM app WHERE app_channel = %d AND app_id = '%s' LIMIT 1",
@@ -126,15 +131,20 @@ class Appman extends \Zotlabs\Web\Controller {
dbesc($papp['guid'])
);
$sync[0]['term'] = q("select * from term where otype = %d and oid = %d",
intval(TERM_OBJ_APP),
intval($sync[0]['id'])
);
if (intval($sync[0]['app_system'])) {
Libsync::build_sync_packet($uid, ['sysapp' => $sync]);
Libsync::build_sync_packet(local_channel(), ['sysapp' => $sync]);
}
else {
Libsync::build_sync_packet($uid, ['app' => $sync]);
Libsync::build_sync_packet(local_channel(), ['app' => $sync]);
}
}
if($_POST['aj']) {
if(isset($_POST['aj']) && $_POST['aj']) {
killme();
}
@@ -171,7 +181,7 @@ class Appman extends \Zotlabs\Web\Controller {
$app = null;
$embed = null;
if($_REQUEST['appid']) {
if(isset($_REQUEST['appid']) && $_REQUEST['appid']) {
$r = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
dbesc($_REQUEST['appid']),
dbesc(local_channel())
@@ -200,27 +210,25 @@ class Appman extends \Zotlabs\Web\Controller {
}
return replace_macros(get_markup_template('app_create.tpl'), array(
'$banner' => (($app) ? t('Edit App') : t('Create App')),
'$app' => $app,
'$guid' => (($app) ? $app['app_id'] : ''),
'$author' => (($app) ? $app['app_author'] : $channel['channel_hash']),
'$addr' => (($app) ? $app['app_addr'] : $channel['xchan_addr']),
'$name' => array('name', t('Name of app'),(($app) ? $app['app_name'] : ''), t('Required')),
'$url' => array('url', t('Location (URL) of app'),(($app) ? $app['app_url'] : ''), t('Required')),
'$desc' => array('desc', t('Description'),(($app) ? $app['app_desc'] : ''), ''),
'$photo' => array('photo', t('Photo icon URL'),(($app) ? $app['app_photo'] : ''), t('80 x 80 pixels - optional')),
'$categories' => array('categories',t('Categories (optional, comma separated list)'),(($app) ? $app['categories'] : ''),''),
'$version' => array('version', t('Version ID'),(($app) ? $app['app_version'] : ''), ''),
'$price' => array('price', t('Price of app'),(($app) ? $app['app_price'] : ''), ''),
'$page' => array('page', t('Location (URL) to purchase app'),(($app) ? $app['app_page'] : ''), ''),
'$system' => (($app) ? intval($app['app_system']) : 0),
'$plugin' => (($app) ? $app['app_plugin'] : ''),
'$requires' => (($app) ? $app['app_requires'] : ''),
'$guid' => $app['app_id'] ?? '',
'$author' => $app['app_author'] ?? $channel['channel_hash'],
'$addr' => $app['app_addr'] ?? $channel['xchan_addr'],
'$name' => array('name', t('Name of app'), $app['app_name'] ?? '', t('Required')),
'$url' => array('url', t('Location (URL) of app'), $app['app_url'] ?? '', t('Required')),
'$desc' => array('desc', t('Description'), $app['app_desc'] ?? '', ''),
'$photo' => array('photo', t('Photo icon URL'),$app['app_photo'] ?? '', t('80 x 80 pixels - optional')),
'$categories' => array('categories',t('Categories (optional, comma separated list)'), $app['categories'] ?? '',''),
'$version' => array('version', t('Version ID'), $app['app_version'] ?? '', ''),
'$price' => array('price', t('Price of app'), $app['app_price'] ?? '', ''),
'$page' => array('page', t('Location (URL) to purchase app'), $app['app_page'] ?? '', ''),
'$system' => $app['app_system'] ?? 0,
'$plugin' => $app['app_plugin'] ?? '',
'$requires' => $app['app_requires'] ?? '',
'$embed' => $embed,
'$submit' => t('Submit')
));
}
}

View File

@@ -19,7 +19,8 @@ class Apps extends \Zotlabs\Web\Controller {
$_SESSION['return_url'] = \App::$query_string;
$apps = array();
$apps = [];
$cat = [];
if(local_channel()) {
Zlib\Apps::import_system_apps();

View File

@@ -2,68 +2,13 @@
namespace Zotlabs\Module;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\Activity;
class Apschema extends \Zotlabs\Web\Controller {
class Apschema extends Controller {
function init() {
$base = z_root();
$arr = [
'@context' => [
'zot' => z_root() . '/apschema#',
'id' => '@id',
'type' => '@type',
'commentPolicy' => 'zot:commentPolicy',
'meData' => 'zot:meData',
'meDataType' => 'zot:meDataType',
'meEncoding' => 'zot:meEncoding',
'meAlgorithm' => 'zot:meAlgorithm',
'meCreator' => 'zot:meCreator',
'meSignatureValue' => 'zot:meSignatureValue',
'locationAddress' => 'zot:locationAddress',
'locationPrimary' => 'zot:locationPrimary',
'locationDeleted' => 'zot:locationDeleted',
'nomadicLocation' => 'zot:nomadicLocation',
'nomadicHubs' => 'zot:nomadicHubs',
'emojiReaction' => 'zot:emojiReaction',
'expires' => 'zot:expires',
'directMessage' => 'zot:directMessage',
'schema' => 'http://schema.org#',
'PropertyValue' => 'schema:PropertyValue',
'value' => 'schema:value',
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
'magicEnv' => [
'@id' => 'zot:magicEnv',
'@type' => '@id'
],
'nomadicLocations' => [
'@id' => 'zot:nomadicLocations',
'@type' => '@id'
],
'ostatus' => 'http://ostatus.org#',
'conversation' => 'ostatus:conversation',
'diaspora' => 'https://diasporafoundation.org/ns/',
'guid' => 'diaspora:guid',
'Hashtag' => 'as:Hashtag'
]
];
header('Content-Type: application/ld+json');
echo json_encode($arr,JSON_UNESCAPED_SLASHES);
echo json_encode(Activity::ap_context(), JSON_UNESCAPED_SLASHES);
killme();
}
}

View File

@@ -1,138 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/channel.php');
require_once('include/acl_selectors.php');
require_once('include/conversation.php');
class Article_edit extends \Zotlabs\Web\Controller {
function get() {
// Figure out which post we're editing
$post_id = ((argc() > 1) ? intval(argv(1)) : 0);
if(! $post_id) {
notice( t('Item not found') . EOL);
return;
}
$itm = q("SELECT * FROM item WHERE id = %d and item_type = %d LIMIT 1",
intval($post_id),
intval(ITEM_TYPE_ARTICLE)
);
if($itm) {
$item_id = q("select * from iconfig where cat = 'system' and k = 'ARTICLE' and iid = %d limit 1",
intval($itm[0]['id'])
);
if($item_id)
$card_title = $item_id[0]['v'];
}
else {
notice( t('Item not found') . EOL);
return;
}
$owner = $itm[0]['uid'];
$uid = local_channel();
$observer = \App::get_observer();
$channel = channelx_by_n($owner);
if(! $channel) {
notice( t('Channel not found.') . EOL);
return;
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner,$ob_hash,'write_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
$is_owner = (($uid && $uid == $owner) ? true : false);
$o = '';
$category = '';
$catsenabled = ((feature_enabled($owner,'categories')) ? 'categories' : '');
if ($catsenabled){
$itm = fetch_post_tags($itm);
$cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY);
foreach ($cats as $cat) {
if (strlen($category))
$category .= ', ';
$category .= $cat['term'];
}
}
if($itm[0]['attach']) {
$j = json_decode($itm[0]['attach'],true);
if($j) {
foreach($j as $jj) {
$itm[0]['body'] .= "\n" . '[attachment]' . basename($jj['href']) . ',' . $jj['revision'] . '[/attachment]' . "\n";
}
}
}
$mimetype = $itm[0]['mimetype'];
$content = $itm[0]['body'];
$rp = 'articles/' . $channel['channel_address'];
$x = array(
'nickname' => $channel['channel_address'],
'bbco_autocomplete'=> 'bbcode',
'return_path' => $rp,
'webpage' => ITEM_TYPE_ARTICLE,
'button' => t('Edit'),
'writefiles' => perm_is_allowed($owner, get_observer_hash(), 'write_pages'),
'weblink' => t('Insert web link'),
'hide_voting' => false,
'hide_future' => false,
'hide_location' => false,
'hide_expire' => false,
'showacl' => true,
'acl' => populate_acl($itm[0],false,\Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')),
'permissions' => $itm[0],
'lockstate' => (($itm[0]['allow_cid'] || $itm[0]['allow_gid'] || $itm[0]['deny_cid'] || $itm[0]['deny_gid']) ? 'lock' : 'unlock'),
'ptyp' => $itm[0]['type'],
'mimeselect' => false,
'mimetype' => $itm[0]['mimetype'],
'body' => undo_post_tagging($content),
'post_id' => $post_id,
'visitor' => true,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
'summary' => htmlspecialchars($itm[0]['summary'],ENT_COMPAT,'UTF-8'),
'placeholdertitle' => t('Title (optional)'),
'pagetitle' => $card_title,
'profile_uid' => (intval($channel['channel_id'])),
'catsenabled' => $catsenabled,
'category' => $category,
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
);
$editor = status_editor($a, $x, false, 'Article_edit');
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit Article'),
'$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false),
'$id' => $itm[0]['id'],
'$cancel' => t('Cancel'),
'$editor' => $editor
));
return $o;
}
}

View File

@@ -1,232 +0,0 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Lib\Apps;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\PermissionDescription;
require_once('include/channel.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
require_once('include/opengraph.php');
class Articles extends Controller {
function init() {
if(argc() > 1)
$which = argv(1);
if(! $which) {
if(local_channel()) {
$channel = App::get_channel();
if($channel && $channel['channel_address'])
$which = $channel['channel_address'];
} else {
return;
}
}
profile_load($which);
}
function get($update = 0, $load = false) {
if(observer_prohibited(true)) {
return login();
}
if(! App::$profile) {
notice( t('Requested profile is not available.') . EOL );
App::$error = 404;
return;
}
if(! Apps::system_app_installed(App::$profile_uid, 'Articles')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$papp = Apps::get_papp('Articles');
return Apps::app_render($papp, 'module');
}
nav_set_selected('Articles');
head_add_link([
'rel' => 'alternate',
'type' => 'application/json+oembed',
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string),
'title' => 'oembed'
]);
$category = (($_REQUEST['cat']) ? escape_tags(trim($_REQUEST['cat'])) : '');
if($category) {
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'],'item', $category, TERM_CATEGORY));
}
$datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
$datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
$which = argv(1);
$selected_card = ((argc() > 2) ? argv(2) : '');
$_SESSION['return_url'] = App::$query_string;
$uid = local_channel();
$owner = App::$profile_uid;
$observer = App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner,$ob_hash,'view_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
$is_owner = ($uid && $uid == $owner);
$channel = channelx_by_n($owner);
if($channel) {
$channel_acl = array(
'allow_cid' => $channel['channel_allow_cid'],
'allow_gid' => $channel['channel_allow_gid'],
'deny_cid' => $channel['channel_deny_cid'],
'deny_gid' => $channel['channel_deny_gid']
);
}
else {
$channel_acl = [ 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ];
}
if(perm_is_allowed($owner,$ob_hash,'write_pages')) {
$x = [
'webpage' => ITEM_TYPE_ARTICLE,
'is_owner' => true,
'content_label' => t('Add Article'),
'button' => t('Save'),
'nickname' => $channel['channel_address'],
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
'acl' => (($is_owner) ? populate_acl($channel_acl, false,
PermissionDescription::fromGlobalPermission('view_pages')) : ''),
'permissions' => $channel_acl,
'showacl' => (($is_owner) ? true : false),
'visitor' => true,
'hide_location' => false,
'hide_voting' => false,
'profile_uid' => intval($owner),
'mimetype' => 'text/bbcode',
'mimeselect' => false,
'layoutselect' => false,
'expanded' => false,
'novoting' => false,
'catsenabled' => feature_enabled($owner,'categories'),
'bbco_autocomplete' => 'bbcode',
'bbcode' => true
];
if($_REQUEST['title'])
$x['title'] = $_REQUEST['title'];
if($_REQUEST['body'])
$x['body'] = $_REQUEST['body'];
$editor = status_editor($a,$x,false,'Articles');
}
else {
$editor = '';
}
$itemspage = get_pconfig(local_channel(),'system','itemspage');
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
$sql_extra = item_permissions_sql($owner);
$sql_item = '';
if($selected_card) {
$r = q("select * from iconfig where iconfig.cat = 'system' and iconfig.k = 'ARTICLE' and iconfig.v = '%s' limit 1",
dbesc($selected_card)
);
if($r) {
$sql_item = "and item.id = " . intval($r[0]['iid']) . " ";
}
}
if($datequery) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery))));
$order = 'post';
}
if($datequery2) {
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
}
if($datequery || $datequery2) {
$sql_extra2 .= " and item.item_thread_top != 0 ";
}
$r = q("select * from item
where item.uid = %d and item_type = %d
$sql_extra $sql_extra2 $sql_item order by item.created desc $pager_sql",
intval($owner),
intval(ITEM_TYPE_ARTICLE)
);
$item_normal = " and item.item_hidden = 0 and item.item_type in (0,7) and item.item_deleted = 0
and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0
and item.item_blocked = 0 ";
if($r) {
$pager_total = count($r);
$parents_str = ids_to_querystr($r,'id');
$r = q("SELECT item.*, item.id AS item_id
FROM item
WHERE item.uid = %d $item_normal
AND item.parent IN ( %s )
$sql_extra $sql_extra2 ",
intval(App::$profile['profile_uid']),
dbesc($parents_str)
);
if($r) {
xchan_query($r);
$items = fetch_post_tags($r, true);
$items = conv_sort($items,'updated');
}
else
$items = [];
}
// Add Opengraph markup
opengraph_add_meta((! empty($items) ? $r[0] : []), $channel);
$mode = 'articles';
if(get_pconfig(local_channel(),'system','articles_list_mode') && (! $selected_card))
$page_mode = 'pager_list';
else
$page_mode = 'traditional';
$content = conversation($items,$mode,false,$page_mode);
$o = replace_macros(get_markup_template('cards.tpl'), [
'$title' => t('Articles'),
'$editor' => $editor,
'$content' => $content,
'$pager' => alt_pager($pager_total)
]);
return $o;
}
}

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

@@ -9,43 +9,43 @@ require_once('include/acl_selectors.php');
class Blocks extends \Zotlabs\Web\Controller {
function init() {
if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
\App::$is_sys = true;
}
}
if(argc() > 1)
$which = argv(1);
else
return;
profile_load($which);
}
function get() {
if(! \App::$profile) {
notice( t('Requested profile is not available.') . EOL );
\App::$error = 404;
return;
}
$which = argv(1);
$_SESSION['return_url'] = \App::$query_string;
$uid = local_channel();
$owner = 0;
$channel = null;
$observer = \App::get_observer();
$channel = \App::get_channel();
if(\App::$is_sys && is_site_admin()) {
$sys = get_sys_channel();
if($sys && intval($sys['channel_id'])) {
@@ -54,7 +54,7 @@ class Blocks extends \Zotlabs\Web\Controller {
$observer = $sys;
}
}
if(! $owner) {
// Figure out who the page owner is.
$r = q("select channel_id from channel where channel_address = '%s'",
@@ -64,24 +64,24 @@ class Blocks extends \Zotlabs\Web\Controller {
$owner = intval($r[0]['channel_id']);
}
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms($owner,$ob_hash);
if(! $perms['write_pages']) {
notice( t('Permission denied.') . EOL);
return;
}
// Block design features from visitors
// Block design features from visitors
if((! $uid) || ($uid != $owner)) {
notice( t('Permission denied.') . EOL);
return;
}
$mimetype = (($_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype'));
$mimetype = ((isset($_REQUEST['mimetype']) && $_REQUEST['mimetype']) ? $_REQUEST['mimetype'] : get_pconfig($owner,'system','page_mimetype'));
$x = array(
'webpage' => ITEM_TYPE_BLOCK,
@@ -101,27 +101,25 @@ class Blocks extends \Zotlabs\Web\Controller {
'bbco_autocomplete' => 'bbcode',
'bbcode' => true
);
if($_REQUEST['title'])
$x['title'] = $_REQUEST['title'];
if($_REQUEST['body'])
$x['body'] = $_REQUEST['body'];
if($_REQUEST['pagetitle'])
$x['pagetitle'] = $_REQUEST['pagetitle'];
$editor = status_editor($a,$x,false,'Blocks');
$r = q("select iconfig.iid, iconfig.k, iconfig.v, mid, title, body, mimetype, created, edited from iconfig
$x['title'] = $_REQUEST['title'] ?? '';
$x['body'] = $_REQUEST['body'] ?? '';
$x['pagetitle'] = $_REQUEST['pagetitle'] ?? '';
$a = '';
$editor = status_editor($x, false, 'Blocks');
$r = q("select iconfig.iid, iconfig.k, iconfig.v, mid, title, body, mimetype, created, edited from iconfig
left join item on iconfig.iid = item.id
where uid = %d and iconfig.cat = 'system' and iconfig.k = 'BUILDBLOCK'
where uid = %d and iconfig.cat = 'system' and iconfig.k = 'BUILDBLOCK'
and item_type = %d order by item.created desc",
intval($owner),
intval(ITEM_TYPE_BLOCK)
);
$pages = null;
if($r) {
$pages = array();
foreach($r as $rr) {
@@ -143,13 +141,13 @@ class Blocks extends \Zotlabs\Web\Controller {
'edited' => $rr['edited'],
'bb_element' => '[element]' . base64url_encode(json_encode($element_arr)) . '[/element]'
);
}
}
}
//Build the base URL for edit links
$url = z_root() . '/editblock/' . $which;
$o .= replace_macros(get_markup_template('blocklist.tpl'), array(
$url = z_root() . '/editblock/' . $which;
$o = replace_macros(get_markup_template('blocklist.tpl'), array(
'$baseurl' => $url,
'$title' => t('Blocks'),
'$name' => t('Block Name'),
@@ -166,8 +164,8 @@ class Blocks extends \Zotlabs\Web\Controller {
'$view' => t('View'),
'$preview' => '1',
));
return $o;
}
}

View File

@@ -39,7 +39,7 @@ class Cal extends Controller {
head_set_icon(App::$data['channel']['xchan_photo_s']);
App::$page['htmlhead'] .= "<script> var profile_uid = " . ((App::$data['channel']) ? App::$data['channel']['channel_id'] : 0) . "; </script>" ;
App::$page['htmlhead'] = "<script> var profile_uid = " . ((App::$data['channel']) ? App::$data['channel']['channel_id'] : 0) . "; </script>" ;
}
@@ -65,13 +65,9 @@ class Cal extends Controller {
nav_set_selected('Calendar');
head_add_css('/library/fullcalendar/packages/core/main.min.css');
head_add_css('/library/fullcalendar/packages/daygrid/main.min.css');
head_add_js('/library/fullcalendar/dist/index.global.js');
head_add_css('cdav_calendar.css');
head_add_js('/library/fullcalendar/packages/core/main.min.js');
head_add_js('/library/fullcalendar/packages/daygrid/main.min.js');
$sql_extra = permissions_sql($channel['channel_id'], get_observer_hash(), 'event');
if(! perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_contacts') || App::$profile['hide_friends'])

View File

@@ -1,140 +0,0 @@
<?php
namespace Zotlabs\Module;
require_once('include/channel.php');
require_once('include/acl_selectors.php');
require_once('include/conversation.php');
class Card_edit extends \Zotlabs\Web\Controller {
function get() {
// Figure out which post we're editing
$post_id = ((argc() > 1) ? intval(argv(1)) : 0);
if(! $post_id) {
notice( t('Item not found') . EOL);
return;
}
$itm = q("SELECT * FROM item WHERE id = %d and item_type = %d LIMIT 1",
intval($post_id),
intval(ITEM_TYPE_CARD)
);
if($itm) {
$item_id = q("select * from iconfig where cat = 'system' and k = 'CARD' and iid = %d limit 1",
intval($itm[0]['id'])
);
if($item_id)
$card_title = $item_id[0]['v'];
}
else {
notice( t('Item not found') . EOL);
return;
}
$owner = $itm[0]['uid'];
$uid = local_channel();
$observer = \App::get_observer();
$channel = channelx_by_n($owner);
if(! $channel) {
notice( t('Channel not found.') . EOL);
return;
}
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner,$ob_hash,'write_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
$is_owner = (($uid && $uid == $owner) ? true : false);
$o = '';
$category = '';
$catsenabled = ((feature_enabled($owner,'categories')) ? 'categories' : '');
if ($catsenabled){
$itm = fetch_post_tags($itm);
$cats = get_terms_oftype($itm[0]['term'], TERM_CATEGORY);
foreach ($cats as $cat) {
if (strlen($category))
$category .= ', ';
$category .= $cat['term'];
}
}
if($itm[0]['attach']) {
$j = json_decode($itm[0]['attach'],true);
if($j) {
foreach($j as $jj) {
$itm[0]['body'] .= "\n" . '[attachment]' . basename($jj['href']) . ',' . $jj['revision'] . '[/attachment]' . "\n";
}
}
}
$mimetype = $itm[0]['mimetype'];
$content = $itm[0]['body'];
$rp = 'cards/' . $channel['channel_address'];
$x = array(
'nickname' => $channel['channel_address'],
'bbco_autocomplete'=> 'bbcode',
'return_path' => $rp,
'webpage' => ITEM_TYPE_CARD,
'button' => t('Edit'),
'writefiles' => perm_is_allowed($owner, get_observer_hash(), 'write_pages'),
'weblink' => t('Insert web link'),
'hide_voting' => false,
'hide_future' => false,
'hide_location' => false,
'hide_expire' => false,
'showacl' => true,
'acl' => populate_acl($itm[0],false,\Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')),
'permissions' => $itm[0],
'lockstate' => (($itm[0]['allow_cid'] || $itm[0]['allow_gid'] || $itm[0]['deny_cid'] || $itm[0]['deny_gid']) ? 'lock' : 'unlock'),
'ptyp' => $itm[0]['type'],
'mimeselect' => false,
'mimetype' => $itm[0]['mimetype'],
'body' => undo_post_tagging($content),
'post_id' => $post_id,
'visitor' => true,
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
'summary' => htmlspecialchars($itm[0]['summary'],ENT_COMPAT,'UTF-8'),
'placeholdertitle' => t('Title (optional)'),
'pagetitle' => $card_title,
'profile_uid' => (intval($channel['channel_id'])),
'catsenabled' => $catsenabled,
'category' => $category,
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
);
$editor = status_editor($a, $x, false, 'Card_edit');
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
'$title' => t('Edit Card'),
'$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false),
'$id' => $itm[0]['id'],
'$cancel' => t('Cancel'),
'$editor' => $editor
));
return $o;
}
}

View File

@@ -1,214 +0,0 @@
<?php
namespace Zotlabs\Module;
use App;
use Zotlabs\Lib\Apps;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\PermissionDescription;
require_once('include/channel.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
/**
* @brief Provides the Cards module.
*
*/
class Cards extends Controller {
public function init() {
if(argc() > 1)
$which = argv(1);
else
return;
profile_load($which);
}
/**
* {@inheritDoc}
* @see \\Zotlabs\\Web\\Controller::get()
*
* @return string Parsed HTML from template 'cards.tpl'
*/
public function get($update = 0, $load = false) {
if(observer_prohibited(true)) {
return login();
}
if(! App::$profile) {
notice( t('Requested profile is not available.') . EOL );
App::$error = 404;
return;
}
if(! Apps::system_app_installed(App::$profile_uid, 'Cards')) {
//Do not display any associated widgets at this point
App::$pdl = '';
$papp = Apps::get_papp('Cards');
return Apps::app_render($papp, 'module');
}
nav_set_selected('Cards');
head_add_link([
'rel' => 'alternate',
'type' => 'application/json+oembed',
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string),
'title' => 'oembed'
]);
$category = (($_REQUEST['cat']) ? escape_tags(trim($_REQUEST['cat'])) : '');
if($category) {
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'], 'item', $category, TERM_CATEGORY));
}
$which = argv(1);
$selected_card = ((argc() > 2) ? argv(2) : '');
$_SESSION['return_url'] = App::$query_string;
$uid = local_channel();
$owner = App::$profile_uid;
$observer = App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
if(! perm_is_allowed($owner, $ob_hash, 'view_pages')) {
notice( t('Permission denied.') . EOL);
return;
}
$is_owner = ($uid && $uid == $owner);
$channel = channelx_by_n($owner);
if($channel) {
$channel_acl = [
'allow_cid' => $channel['channel_allow_cid'],
'allow_gid' => $channel['channel_allow_gid'],
'deny_cid' => $channel['channel_deny_cid'],
'deny_gid' => $channel['channel_deny_gid']
];
}
else {
$channel_acl = [ 'allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ];
}
if(perm_is_allowed($owner, $ob_hash, 'write_pages')) {
$x = [
'webpage' => ITEM_TYPE_CARD,
'is_owner' => true,
'content_label' => t('Add Card'),
'button' => t('Save'),
'nickname' => $channel['channel_address'],
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
'acl' => (($is_owner) ? populate_acl($channel_acl, false,
PermissionDescription::fromGlobalPermission('view_pages')) : ''),
'permissions' => $channel_acl,
'showacl' => (($is_owner) ? true : false),
'visitor' => true,
'hide_location' => false,
'hide_voting' => false,
'profile_uid' => intval($owner),
'mimetype' => 'text/bbcode',
'mimeselect' => false,
'layoutselect' => false,
'expanded' => false,
'novoting' => false,
'catsenabled' => feature_enabled($owner, 'categories'),
'bbco_autocomplete' => 'bbcode',
'bbcode' => true
];
if($_REQUEST['title'])
$x['title'] = $_REQUEST['title'];
if($_REQUEST['body'])
$x['body'] = $_REQUEST['body'];
$editor = status_editor($a, $x, false, 'Cards');
}
else {
$editor = '';
}
$itemspage = get_pconfig(local_channel(),'system','itemspage');
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 10));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
$sql_extra = item_permissions_sql($owner);
$sql_item = '';
if($selected_card) {
$r = q("select * from iconfig where iconfig.cat = 'system' and iconfig.k = 'CARD' and iconfig.v = '%s' limit 1",
dbesc($selected_card)
);
if($r) {
$sql_item = "and item.id = " . intval($r[0]['iid']) . " ";
}
}
$r = q("select * from item
where uid = %d and item_type = %d
$sql_extra $sql_item order by item.created desc $pager_sql",
intval($owner),
intval(ITEM_TYPE_CARD)
);
$item_normal = " and item.item_hidden = 0 and item.item_type in (0,6) and item.item_deleted = 0
and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0
and item.item_blocked = 0 ";
$items_result = [];
if($r) {
$pager_total = count($r);
$parents_str = ids_to_querystr($r, 'id');
$items = q("SELECT item.*, item.id AS item_id
FROM item
WHERE item.uid = %d $item_normal
AND item.parent IN ( %s )
$sql_extra $sql_extra2 ",
intval(App::$profile['profile_uid']),
dbesc($parents_str)
);
if($items) {
xchan_query($items);
$items = fetch_post_tags($items, true);
$items_result = conv_sort($items, 'updated');
}
}
$mode = 'cards';
if(get_pconfig(local_channel(),'system','articles_list_mode') && (! $selected_card))
$page_mode = 'pager_list';
else
$page_mode = 'traditional';
$content = conversation($items_result, $mode, false, $page_mode);
$o = replace_macros(get_markup_template('cards.tpl'), [
'$title' => t('Cards'),
'$editor' => $editor,
'$content' => $content,
'$pager' => alt_pager($pager_total)
]);
return $o;
}
}

View File

@@ -200,7 +200,7 @@ class Cdav extends Controller {
$etag = (isset($_SERVER['HTTP_IF_MATCH']) ? $_SERVER['HTTP_IF_MATCH'] : false);
// delete
if($httpmethod === 'DELETE' && $cdavdata['etag'] == $etag) {
if($httpmethod === 'DELETE' && $etag && isset($cdavdata['etag']) && $cdavdata['etag'] == $etag) {
Libsync::build_sync_packet($channel['channel_id'], [
$sync => [
'action' => 'delete_card',
@@ -210,7 +210,7 @@ class Cdav extends Controller {
]);
}
else {
if($etag && $cdavdata['etag'] !== $etag) {
if($etag && isset($cdavdata['etag']) && $cdavdata['etag'] !== $etag) {
// update
Libsync::build_sync_packet($channel['channel_id'], [
$sync => [
@@ -317,7 +317,7 @@ class Cdav extends Controller {
$calendars = $caldavBackend->getCalendarsForUser($principalUri);
//create new calendar
if($_REQUEST['{DAV:}displayname'] && $_REQUEST['create']) {
if((isset($_REQUEST['{DAV:}displayname']) && $_REQUEST['{DAV:}displayname']) && (isset($_REQUEST['create']) && $_REQUEST['create'])) {
do {
$duplicate = false;
$calendarUri = random_string(40);
@@ -332,9 +332,9 @@ class Cdav extends Controller {
} while ($duplicate == true);
$properties = [
'{DAV:}displayname' => $_REQUEST['{DAV:}displayname'],
'{http://apple.com/ns/ical/}calendar-color' => $_REQUEST['color'],
'{urn:ietf:params:xml:ns:caldav}calendar-description' => $channel['channel_name']
'{DAV:}displayname' => escape_tags($_REQUEST['{DAV:}displayname']),
'{http://apple.com/ns/ical/}calendar-color' => escape_tags($_REQUEST['color']),
'{urn:ietf:params:xml:ns:caldav}calendar-description' => escape_tags($channel['channel_name'])
];
$id = $caldavBackend->createCalendar($principalUri, $calendarUri, $properties);
@@ -352,7 +352,7 @@ class Cdav extends Controller {
}
//create new calendar object via ajax request
if($_REQUEST['submit'] === 'create_event' && $_REQUEST['title'] && $_REQUEST['target'] && $_REQUEST['dtstart']) {
if((isset($_REQUEST['submit']) && $_REQUEST['submit'] === 'create_event') && $_REQUEST['title'] && $_REQUEST['target'] && $_REQUEST['dtstart']) {
$id = explode(':', $_REQUEST['target']);
@@ -366,7 +366,7 @@ class Cdav extends Controller {
$allday = $_REQUEST['allday'];
$title = $_REQUEST['title'];
$title = escape_tags($_REQUEST['title']);
$start = datetime_convert('UTC', 'UTC', $_REQUEST['dtstart']);
$dtstart = new \DateTime($start);
@@ -374,8 +374,8 @@ class Cdav extends Controller {
$end = datetime_convert('UTC', 'UTC', $_REQUEST['dtend']);
$dtend = new \DateTime($end);
}
$description = $_REQUEST['description'];
$location = $_REQUEST['location'];
$description = escape_tags($_REQUEST['description']);
$location = escape_tags($_REQUEST['location']);
do {
$duplicate = false;
@@ -431,7 +431,7 @@ class Cdav extends Controller {
}
//edit calendar name and color
if($_REQUEST['{DAV:}displayname'] && $_REQUEST['edit'] && $_REQUEST['id']) {
if((isset($_REQUEST['{DAV:}displayname']) && $_REQUEST['{DAV:}displayname']) && $_REQUEST['edit'] && $_REQUEST['id']) {
$id = explode(':', $_REQUEST['id']);
@@ -441,8 +441,8 @@ class Cdav extends Controller {
$cdavdata = $this->get_cdav_data($id[0], 'calendarinstances');
$mutations = [
'{DAV:}displayname' => $_REQUEST['{DAV:}displayname'],
'{http://apple.com/ns/ical/}calendar-color' => $_REQUEST['color']
'{DAV:}displayname' => escape_tags($_REQUEST['{DAV:}displayname']),
'{http://apple.com/ns/ical/}calendar-color' => escape_tags($_REQUEST['color'])
];
$patch = new \Sabre\DAV\PropPatch($mutations);
@@ -459,7 +459,7 @@ class Cdav extends Controller {
}
//edit calendar object via ajax request
if($_REQUEST['submit'] === 'update_event' && $_REQUEST['uri'] && $_REQUEST['title'] && $_REQUEST['target'] && $_REQUEST['dtstart']) {
if((isset($_REQUEST['submit']) && $_REQUEST['submit'] === 'update_event') && $_REQUEST['uri'] && $_REQUEST['title'] && $_REQUEST['target'] && $_REQUEST['dtstart']) {
$id = explode(':', $_REQUEST['target']);
@@ -471,18 +471,18 @@ class Cdav extends Controller {
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
$tz = (($timezone) ? $timezone : date_default_timezone_get());
$allday = $_REQUEST['allday'];
$allday = intval($_REQUEST['allday']);
$uri = $_REQUEST['uri'];
$title = $_REQUEST['title'];
$uri = escape_tags($_REQUEST['uri']);
$title = escape_tags($_REQUEST['title']);
$start = datetime_convert('UTC', 'UTC', $_REQUEST['dtstart']);
$dtstart = new \DateTime($start);
if($_REQUEST['dtend']) {
$end = datetime_convert('UTC', 'UTC', $_REQUEST['dtend']);
$dtend = new \DateTime($end);
}
$description = $_REQUEST['description'];
$location = $_REQUEST['location'];
$description = escape_tags($_REQUEST['description']);
$location = escape_tags($_REQUEST['location']);
$object = $caldavBackend->getCalendarObject($id, $uri);
@@ -654,7 +654,7 @@ class Cdav extends Controller {
$duplicate = true;
} while ($duplicate == true);
$properties = ['{DAV:}displayname' => $_REQUEST['{DAV:}displayname']];
$properties = ['{DAV:}displayname' => escape_tags($_REQUEST['{DAV:}displayname'])];
$carddavBackend->createAddressBook($principalUri, $addressbookUri, $properties);
@@ -668,9 +668,9 @@ class Cdav extends Controller {
}
//edit addressbook
if($_REQUEST['{DAV:}displayname'] && $_REQUEST['edit'] && intval($_REQUEST['id'])) {
if($_REQUEST['{DAV:}displayname'] && $_REQUEST['edit'] && $_REQUEST['id']) {
$id = $_REQUEST['id'];
$id = intval($_REQUEST['id']);
if(! cdav_perms($id,$addressbooks))
return;
@@ -678,7 +678,7 @@ class Cdav extends Controller {
$cdavdata = $this->get_cdav_data($id, 'addressbooks');
$mutations = [
'{DAV:}displayname' => $_REQUEST['{DAV:}displayname']
'{DAV:}displayname' => escape_tags($_REQUEST['{DAV:}displayname'])
];
$patch = new \Sabre\DAV\PropPatch($mutations);
@@ -901,19 +901,10 @@ class Cdav extends Controller {
//Display calendar(s) here
if(argc() <= 3 && argv(1) === 'calendar') {
head_add_css('/library/fullcalendar/packages/core/main.min.css');
head_add_css('/library/fullcalendar/packages/daygrid/main.min.css');
head_add_css('/library/fullcalendar/packages/timegrid/main.min.css');
head_add_css('/library/fullcalendar/packages/list/main.min.css');
head_add_js('/library/fullcalendar/dist/index.global.js');
head_add_css('cdav_calendar.css');
head_add_js('/library/fullcalendar/packages/core/main.min.js');
head_add_js('/library/fullcalendar/packages/interaction/main.min.js');
head_add_js('/library/fullcalendar/packages/daygrid/main.min.js');
head_add_js('/library/fullcalendar/packages/timegrid/main.min.js');
head_add_js('/library/fullcalendar/packages/list/main.min.js');
$o = '';
$sources = '';
$resource_id = '';
$resource = null;
@@ -921,6 +912,8 @@ class Cdav extends Controller {
if(argc() == 3)
$resource_id = argv(2);
$categories = '';
if($resource_id) {
$r = q("SELECT event.*, item.author_xchan, item.owner_xchan, item.plink, item.id as item_id FROM event LEFT JOIN item ON event.event_hash = item.resource_id
WHERE event.uid = %d AND event.event_hash = '%s' LIMIT 1",
@@ -944,7 +937,6 @@ class Cdav extends Controller {
$resource = $r[0];
$catsenabled = feature_enabled(local_channel(),'categories');
$categories = '';
if($catsenabled){
if($r[0]['term']) {
$cats = get_terms_oftype($r[0]['term'], TERM_CATEGORY);
@@ -1095,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

@@ -31,8 +31,10 @@ class Channel extends Controller {
goaway(z_root() . '/search?f=&search=' . $_GET['search']);
$which = null;
if (argc() > 1)
if (argc() > 1) {
$which = argv(1);
}
if (!$which) {
if (local_channel()) {
$channel = App::get_channel();
@@ -40,9 +42,9 @@ class Channel extends Controller {
$which = $channel['channel_address'];
}
}
if (!$which) {
notice(t('You must be logged in to see this page.') . EOL);
return;
http_status_exit(404, 'Not found');
}
$profile = 0;
@@ -67,7 +69,7 @@ class Channel extends Controller {
if ($sigdata && $sigdata['signer'] && $sigdata['header_valid']) {
$data = json_encode(Libzot::zotinfo(['guid_hash' => $channel['channel_hash'], 'target_url' => $sigdata['signer']]));
$s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
$s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' order by hubloc_id desc limit 1",
dbesc($sigdata['signer'])
);
@@ -99,16 +101,23 @@ class Channel extends Controller {
App::$meta->set('robots', 'noindex, noarchive');
}
$identifier = 'uuid';
$mid = $_REQUEST['mid'] ?? '';
if (str_starts_with($mid, 'b64.')) {
$mid = unpack_link_id($mid);
$identifier = 'mid';
}
if ($mid === false) {
http_status_exit(404, 'Not found');
}
if (ActivityStreams::is_as_request($channel)) {
// Somebody may attempt an ActivityStreams fetch on one of our message permalinks
// Make it do the right thing.
$mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
if ($mid === false) {
http_status_exit(404, 'Not found');
}
if ($mid) {
$obj = null;
if (strpos($mid, z_root() . '/item/') === 0) {
@@ -125,6 +134,7 @@ class Channel extends Controller {
$obj->init();
}
}
as_return_and_die(Activity::encode_person($channel, true), $channel);
}
@@ -153,15 +163,9 @@ class Channel extends Controller {
profile_load($which, $profile);
// Add Opengraph markup
$mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
if ($mid === false) {
notice(t('Malformed message id.') . EOL);
return;
}
if ($mid) {
$r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
$r = q("SELECT * FROM item WHERE $identifier = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
dbesc($mid),
intval($channel['channel_id'])
);
@@ -176,7 +180,16 @@ class Channel extends Controller {
$category = $datequery = $datequery2 = '';
$mid = ((x($_REQUEST, 'mid')) ? unpack_link_id($_REQUEST['mid']) : '');
$mid = $_REQUEST['mid'] ?? '';
$identifier = 'uuid';
$encoded_mid = null;
if (str_starts_with($mid, 'b64.')) {
$encoded_mid = $mid;
$mid = unpack_link_id($mid);
$identifier = 'mid';
}
if ($mid === false) {
notice(t('Malformed message id.') . EOL);
return;
@@ -245,9 +258,7 @@ class Channel extends Controller {
$channel_acl = ['allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => ''];
}
if ($perms['post_wall']) {
$x = [
'is_owner' => $is_owner,
'allow_location' => ((($is_owner || $observer) && (intval(get_pconfig(App::$profile['profile_uid'], 'system', 'use_browser_location')))) ? true : false),
@@ -267,9 +278,16 @@ class Channel extends Controller {
'reset' => t('Reset form')
];
$o .= status_editor($a, $x, false, 'Channel');
$a = '';
$o .= status_editor($x, false, 'Channel');
}
// Add pinned content
if (!x($_REQUEST, 'mid') && !$search) {
$pinned = new \Zotlabs\Widget\Pinned;
$r = $pinned->widget(intval(App::$profile['profile_uid']), [ITEM_TYPE_POST]);
$o .= $r['html'];
}
}
@@ -277,13 +295,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';
@@ -293,7 +307,7 @@ class Channel extends Controller {
$abook_uids = " and abook.abook_channel = " . intval(App::$profile['profile_uid']) . " ";
$simple_update = '';
if ($update && $_SESSION['loadtime'])
if ($update && isset($_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']) . "' ) ";
if ($search) {
@@ -319,7 +333,7 @@ class Channel extends Controller {
if (($update) && (!$load)) {
if ($mid) {
$r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d $item_normal_update
$r = q("SELECT parent AS item_id, uuid from item where $identifier = '%s' and uid = %d $item_normal_update
AND item_wall = 1 $simple_update $sql_extra limit 1",
dbesc($mid),
intval(App::$profile['profile_uid'])
@@ -367,7 +381,7 @@ class Channel extends Controller {
if ($noscript_content || $load) {
if ($mid) {
$r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d $item_normal
$r = q("SELECT parent AS item_id, uuid from item where $identifier = '%s' and uid = %d $item_normal
AND item_wall = 1 $sql_extra limit 1",
dbesc($mid),
intval(App::$profile['profile_uid'])
@@ -393,7 +407,6 @@ class Channel extends Controller {
}
}
if ($r) {
$parents_str = ids_to_querystr($r, 'item_id');
$r = q("SELECT item.*, item.id AS item_id
@@ -420,19 +433,12 @@ class Channel extends Controller {
$items = [];
}
// Add pinned content
if (!x($_REQUEST, 'mid') && !$search) {
$pinned = new \Zotlabs\Widget\Pinned;
$r = $pinned->widget(intval(App::$profile['profile_uid']), [ITEM_TYPE_POST]);
$o .= $r['html'];
}
$mode = (($search) ? 'search' : 'channel');
if ((!$update) && (!$load)) {
//if we got a decoded hash we must encode it again before handing to javascript
$mid = gen_link_id($mid);
if ((!$update) && (!$load)) {
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
// because browser prefetching might change it on us. We have to deliver it with the page.
@@ -470,7 +476,7 @@ class Channel extends Controller {
'$file' => '',
'$cats' => (($category) ? urlencode($category) : ''),
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
'$mid' => (($mid) ? urlencode($mid) : ''),
'$mid' => $encoded_mid ?? $mid,
'$verb' => '',
'$net' => '',
'$dend' => $datequery,

View File

@@ -30,7 +30,7 @@ class Channel_calendar extends Controller {
$xchan = ((x($_POST, 'xchan')) ? dbesc($_POST['xchan']) : '');
// only allow editing your own events.
// only allow editing your own events.
if (($xchan) && ($xchan !== get_observer_hash()))
return;
@@ -55,8 +55,8 @@ class Channel_calendar extends Controller {
// Don't allow the event to finish before it begins.
// It won't hurt anything, but somebody will file a bug report
// and we'll waste a bunch of time responding to it. Time that
// could've been spent doing something else.
// and we'll waste a bunch of time responding to it. Time that
// could've been spent doing something else.
if (strcmp($finish, $start) < 0) {
notice(t('Event can not end before it has started.') . EOL);
@@ -319,12 +319,12 @@ class Channel_calendar extends Controller {
// fixed an issue with "nofinish" events not showing up in the calendar.
// There's still an issue if the finish date crosses the end of month.
// Noting this for now - it will need to be fixed here and in Friendica.
// Ultimately the finish date shouldn't be involved in the query.
// Ultimately the finish date shouldn't be involved in the query.
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan, item.id as item_id
from event left join item on event.event_hash = item.resource_id
where item.resource_type = 'event' and event.uid = %d and event.uid = item.uid $ignored
AND (( event.adjust = 0 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' )
from event left join item on event.event_hash = item.resource_id
where item.resource_type = 'event' and event.uid = %d and event.uid = item.uid $ignored
AND (( event.adjust = 0 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' )
OR ( event.adjust = 1 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' )) ",
intval(local_channel()),
dbesc($start),
@@ -357,7 +357,7 @@ class Channel_calendar extends Controller {
$catsenabled = feature_enabled(local_channel(), 'categories');
$categories = '';
if ($catsenabled) {
if ($rr['term']) {
if (isset($rr['term']) && $rr['term']) {
$cats = get_terms_oftype($rr['term'], TERM_CATEGORY);
foreach ($cats as $cat) {
if (strlen($categories))
@@ -449,7 +449,7 @@ class Channel_calendar extends Controller {
}
// The site admin can delete any post/item on the site.
// If the item originated on this site+channel the deletion will propagate downstream.
// If the item originated on this site+channel the deletion will propagate downstream.
// Otherwise just the local copy is removed.
if (is_site_admin()) {

View File

@@ -16,17 +16,17 @@ class Chanview extends \Zotlabs\Web\Controller {
$r = null;
if($_REQUEST['hash']) {
if(!empty($_REQUEST['hash'])) {
$r = q("select * from xchan where xchan_hash = '%s' and xchan_deleted = 0",
dbesc($_REQUEST['hash'])
);
}
if($_REQUEST['address']) {
if(!empty($_REQUEST['address'])) {
$r = q("select * from xchan where xchan_addr = '%s' and xchan_deleted = 0",
dbesc(punify($_REQUEST['address']))
);
}
elseif(local_channel() && intval($_REQUEST['cid'])) {
elseif(local_channel() && !empty($_REQUEST['cid'])) {
$r = q("SELECT abook.*, xchan.*
FROM abook left join xchan on abook_xchan = xchan_hash
WHERE abook_channel = %d and abook_id = %d and xchan_deleted = 0",
@@ -34,8 +34,7 @@ class Chanview extends \Zotlabs\Web\Controller {
intval($_REQUEST['cid'])
);
}
elseif($_REQUEST['url']) {
elseif(!empty($_REQUEST['url'])) {
// if somebody re-installed they will have more than one xchan, use the most recent name date as this is
// the most useful consistently ascending table item we have.
@@ -56,7 +55,7 @@ class Chanview extends \Zotlabs\Web\Controller {
if(! App::$poi) {
logger('mod_chanview: fallback');
if($_REQUEST['address']) {
if(!empty($_REQUEST['address'])) {
$href = Webfinger::zot_url(punify($_REQUEST['address']));
if($href) {
$_REQUEST['url'] = $href;
@@ -65,9 +64,9 @@ class Chanview extends \Zotlabs\Web\Controller {
$r = null;
if($_REQUEST['url']) {
if(!empty($_REQUEST['url'])) {
$zf = Zotfinger::exec($_REQUEST['url'], null);
$zf = Zotfinger::exec($_REQUEST['url']);
if(array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $_REQUEST['url'] && intval($zf['signature']['header_valid'])) {
Libzot::import_xchan($zf['data']);
@@ -79,6 +78,7 @@ class Chanview extends \Zotlabs\Web\Controller {
}
}
if(! $r) {
if(discover_by_webbie($_REQUEST['url'])) {
$r = q("select * from xchan where xchan_url = '%s' and xchan_deleted = 0",
dbesc($_REQUEST['url'])

View File

@@ -174,13 +174,14 @@ class Chat extends Controller {
$x = Chatroom::enter($observer,$room_id,'online',$_SERVER['REMOTE_ADDR']);
if(! $x)
return;
$x = q("select * from chatroom where cr_id = %d and cr_uid = %d $sql_extra limit 1",
$x = q("select * from chatroom where cr_id = %d and cr_uid = %d limit 1",
intval($room_id),
intval(App::$profile['profile_uid'])
);
if($x) {
$acl = new AccessList(false);
$acl = new AccessList([]);
$acl->set($x[0]);
$private = $acl->is_private();
@@ -211,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'),
@@ -224,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

@@ -1,6 +1,6 @@
<?php /** @file */
namespace Zotlabs\Module;
namespace Zotlabs\Module;
require_once('include/security.php');
@@ -9,76 +9,76 @@ use \Zotlabs\Lib as Zlib;
class Chatsvc extends \Zotlabs\Web\Controller {
function init() {
//logger('chatsvc');
$ret = array('success' => false);
\App::$data['chat']['room_id'] = intval($_REQUEST['room_id']);
$x = q("select cr_uid from chatroom where cr_id = %d and cr_id != 0 limit 1",
intval(\App::$data['chat']['room_id'])
);
if(! $x)
json_return_and_die($ret);
\App::$data['chat']['uid'] = $x[0]['cr_uid'];
if(! perm_is_allowed(\App::$data['chat']['uid'],get_observer_hash(),'chat')) {
json_return_and_die($ret);
}
}
function post() {
$ret = array('success' => false);
$room_id = \App::$data['chat']['room_id'];
$text = escape_tags($_REQUEST['chat_text']);
if(! $text)
return;
$sql_extra = permissions_sql(\App::$data['chat']['uid']);
$r = q("select * from chatroom where cr_uid = %d and cr_id = %d $sql_extra",
intval(\App::$data['chat']['uid']),
intval(\App::$data['chat']['room_id'])
);
if(! $r)
json_return_and_die($ret);
$arr = array(
'chat_room' => \App::$data['chat']['room_id'],
'chat_xchan' => get_observer_hash(),
'chat_text' => $text
);
call_hooks('chat_post',$arr);
$x = q("insert into chat ( chat_room, chat_xchan, created, chat_text )
values( %d, '%s', '%s', '%s' )",
intval(\App::$data['chat']['room_id']),
dbesc(get_observer_hash()),
dbesc(datetime_convert()),
dbesc(str_rot47(base64url_encode($arr['chat_text'])))
dbesc(str_rot47(base64url_encode($arr['chat_text'])))
);
$ret['success'] = true;
json_return_and_die($ret);
}
function get() {
$status = strip_tags($_REQUEST['status']);
$status = ((isset($_REQUEST['status'])) ? strip_tags($_REQUEST['status']) : '');
$room_id = intval(\App::$data['chat']['room_id']);
$stopped = ((x($_REQUEST,'stopped') && intval($_REQUEST['stopped'])) ? true : false);
if($status && $room_id) {
$x = q("select channel_address from channel where channel_id = %d limit 1",
intval(\App::$data['chat']['uid'])
);
);
$r = q("update chatpresence set cp_status = '%s', cp_last = '%s' where cp_room = %d and cp_xchan = '%s' and cp_client = '%s'",
dbesc($status),
dbesc(datetime_convert()),
@@ -86,27 +86,27 @@ class Chatsvc extends \Zotlabs\Web\Controller {
dbesc(get_observer_hash()),
dbesc($_SERVER['REMOTE_ADDR'])
);
goaway(z_root() . '/chat/' . $x[0]['channel_address'] . '/' . $room_id);
goaway(z_root() . '/chat/' . $x[0]['channel_address'] . '/' . $room_id);
}
if(! $stopped) {
$lastseen = intval($_REQUEST['last']);
$ret = array('success' => false);
$sql_extra = permissions_sql(\App::$data['chat']['uid']);
$r = q("select * from chatroom where cr_uid = %d and cr_id = %d $sql_extra",
intval(\App::$data['chat']['uid']),
intval(\App::$data['chat']['room_id'])
);
if(! $r)
json_return_and_die($ret);
$inroom = array();
$r = q("select * from chatpresence left join xchan on xchan_hash = cp_xchan where cp_room = %d order by xchan_name",
intval(\App::$data['chat']['room_id'])
);
@@ -120,9 +120,9 @@ class Chatsvc extends \Zotlabs\Web\Controller {
$rv['xchan_url'] = z_root();
$rv['xchan_hidden'] = 1;
$rv['xchan_photo_mimetype'] = 'image/png';
$rv['xchan_photo_l'] = z_root() . '/' . get_default_profile_photo(300);
$rv['xchan_photo_m'] = z_root() . '/' . get_default_profile_photo(80);
$rv['xchan_photo_s'] = z_root() . '/' . get_default_profile_photo(48);
$rv['xchan_photo_l'] = z_root() . '/' . get_default_profile_photo(300);
$rv['xchan_photo_m'] = z_root() . '/' . get_default_profile_photo(80);
$rv['xchan_photo_s'] = z_root() . '/' . get_default_profile_photo(48);
}
@@ -137,13 +137,13 @@ class Chatsvc extends \Zotlabs\Web\Controller {
$status_class = 'online';
break;
}
$inroom[] = array('img' => zid($rv['xchan_photo_m']), 'img_type' => $rv['xchan_photo_mimetype'],'name' => $rv['xchan_name'], 'status' => $status, 'status_class' => $status_class);
}
}
$chats = array();
$r = q("select * from chat left join xchan on chat_xchan = xchan_hash where chat_room = %d and chat_id > %d order by created",
intval(\App::$data['chat']['room_id']),
intval($lastseen)
@@ -152,7 +152,7 @@ class Chatsvc extends \Zotlabs\Web\Controller {
foreach($r as $rr) {
$chats[] = array(
'id' => $rr['chat_id'],
'img' => zid($rr['xchan_photo_m']),
'img' => zid($rr['xchan_photo_m']),
'img_type' => $rr['xchan_photo_mimetype'],
'name' => $rr['xchan_name'],
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $rr['created'], 'c'),
@@ -163,22 +163,22 @@ class Chatsvc extends \Zotlabs\Web\Controller {
}
}
}
$r = q("update chatpresence set cp_last = '%s' where cp_room = %d and cp_xchan = '%s' and cp_client = '%s'",
dbesc(datetime_convert()),
intval(\App::$data['chat']['room_id']),
dbesc(get_observer_hash()),
dbesc($_SERVER['REMOTE_ADDR'])
);
$ret['success'] = true;
if(! $stopped) {
$ret['inroom'] = $inroom;
$ret['chats'] = $chats;
}
json_return_and_die($ret);
}
}

View File

@@ -54,9 +54,9 @@ class Cloud extends Controller {
if (local_channel()) {
$channel = \App::get_channel();
$auth->setCurrentUser($channel['channel_address']);
$auth->channel_account_id = $channel['channel_account_id'];
$auth->channel_id = $channel['channel_id'];
$auth->channel_hash = $channel['channel_hash'];
$auth->channel_account_id = $channel['channel_account_id'];
if($channel['channel_timezone'])
$auth->setTimezone($channel['channel_timezone']);
}
@@ -70,7 +70,7 @@ class Cloud extends Controller {
$_SESSION['cloud_sort'] = 'name';
}
$_SESSION['cloud_sort'] = (($_REQUEST['sort']) ? trim(notags($_REQUEST['sort'])) : $_SESSION['cloud_sort']);
$_SESSION['cloud_sort'] = ((isset($_REQUEST['sort']) && $_REQUEST['sort']) ? trim(notags($_REQUEST['sort'])) : $_SESSION['cloud_sort']);
$x = clean_query_string();
if($x !== \App::$query_string)
@@ -100,7 +100,6 @@ class Cloud extends Controller {
// over-ride the default XML output on thrown exceptions
$server->on('exception', [ $this, 'DAVException' ]);
// All we need to do now, is to fire up the server
@@ -117,21 +116,19 @@ class Cloud extends Controller {
function DAVException($err) {
if($err instanceof \Sabre\DAV\Exception\NotFound) {
notice( t('Not found') . EOL);
\App::$page['content'] = '<h2>404 Not found</h2>';
}
elseif($err instanceof \Sabre\DAV\Exception\Forbidden) {
notice( t('Permission denied') . EOL);
\App::$page['content'] = '<h2>403 Forbidden</h2>';
}
elseif($err instanceof \Sabre\DAV\Exception\NotImplemented) {
// notice( t('Please refresh page') . EOL);
goaway(z_root() . '/' . \App::$query_string);
}
else {
notice( t('Unknown error') . EOL);
\App::$page['content'] = '<h2>Unknown error</h2>';
}
construct_page();
killme();
}

View File

@@ -6,7 +6,7 @@ class Cloud_tiles extends \Zotlabs\Web\Controller {
function init() {
if(intval($_SESSION['cloud_tiles']))
if(isset($_SESSION['cloud_tiles']) && intval($_SESSION['cloud_tiles']))
$_SESSION['cloud_tiles'] = 0;
else
$_SESSION['cloud_tiles'] = 1;
@@ -18,4 +18,4 @@ class Cloud_tiles extends \Zotlabs\Web\Controller {
goaway(z_root() . '/' . hex2bin(argv(1)));
}
}
}

View File

@@ -45,7 +45,7 @@ class Connections extends \Zotlabs\Web\Controller {
$unconnected = false;
$all = false;
if(! $_REQUEST['aj'])
if(!(isset($_REQUEST['aj']) && $_REQUEST['aj']))
$_SESSION['return_url'] = App::$query_string;
$search_flags = "";
@@ -128,7 +128,9 @@ class Connections extends \Zotlabs\Web\Controller {
$unblocked = true;
}
switch($_REQUEST['order']) {
$order = $_REQUEST['order'] ?? '';
switch($order) {
case 'name_desc':
$sql_order = 'xchan_name DESC';
break;
@@ -143,6 +145,7 @@ class Connections extends \Zotlabs\Web\Controller {
}
$search = ((x($_REQUEST,'search')) ? notags(trim($_REQUEST['search'])) : '');
$search_xchan = ((x($_REQUEST,'search_xchan')) ? notags(trim($_REQUEST['search_xchan'])) : '');
$tabs = array(
/*
@@ -227,14 +230,21 @@ class Connections extends \Zotlabs\Web\Controller {
//$t = replace_macros($tab_tpl, array('$tabs'=>$tabs));
$searching = false;
$search_hdr = '';
if($search) {
$search_hdr = $search;
$search_txt = dbesc(protect_sprintf(preg_quote($search)));
$searching = true;
}
$sql_extra .= (($searching) ? protect_sprintf(" AND xchan_name like '%$search_txt%' ") : "");
$search_txt = (($search_xchan) ? urldecode($search_xchan) : preg_quote($search));
if($_REQUEST['gid']) {
if ($search_xchan) {
$sql_extra .= " AND xchan_hash = '" . protect_sprintf(dbesc($search_txt)) . "' ";
}
else {
$sql_extra .= " AND xchan_name LIKE '%%" . protect_sprintf(dbesc($search_txt)) . "%%' ";
}
}
if(isset($_REQUEST['gid']) && $_REQUEST['gid']) {
$sql_extra .= " and xchan_hash in ( select xchan from pgrp_member where gid = " . intval($_REQUEST['gid']) . " and uid = " . intval(local_channel()) . " ) ";
}
@@ -272,14 +282,13 @@ class Connections extends \Zotlabs\Web\Controller {
foreach($r as $rr) {
if($rr['xchan_url']) {
if(($rr['vcard']) && is_array($rr['vcard']['tels']) && $rr['vcard']['tels'][0]['nr'])
if((isset($rr['vcard'])) && is_array($rr['vcard']['tels']) && $rr['vcard']['tels'][0]['nr'])
$phone = $rr['vcard']['tels'][0]['nr'];
else
$phone = '';
$status_str = '';
$status = array(
((intval($rr['abook_active'])) ? t('Active') : ''),
((intval($rr['abook_pending'])) ? t('Pending approval') : ''),
((intval($rr['abook_archived'])) ? t('Archived') : ''),
((intval($rr['abook_hidden'])) ? t('Hidden') : ''),
@@ -354,9 +363,9 @@ class Connections extends \Zotlabs\Web\Controller {
'oneway' => $oneway,
'perminfo' => $perminfo,
'connect' => (intval($rr['abook_not_here']) ? t('Connect') : ''),
'follow' => z_root() . '/follow/?f=&url=' . urlencode($rr['xchan_hash']) . '&interactive=0',
'follow' => z_root() . '/follow/?f=&url=' . urlencode($rr['xchan_hash']) . '&interactive=1',
'connect_hover' => t('Connect at this location'),
'role' => $roles_dict[$rr['abook_role']],
'role' => $roles_dict[$rr['abook_role']] ?? '',
'pending' => intval($rr['abook_pending'])
);
}
@@ -365,13 +374,13 @@ class Connections extends \Zotlabs\Web\Controller {
$limit = service_class_fetch(local_channel(),'total_channels');
if($limit !== false) {
$abook_usage_message = sprintf( t("You have %1$.0f of %2$.0f allowed connections."), $$total, $limit);
$abook_usage_message = sprintf( t("You have %1$.0f of %2$.0f allowed connections."), $total, $limit);
}
else {
$abook_usage_message = '';
}
if($_REQUEST['aj']) {
if(isset($_REQUEST['aj']) && $_REQUEST['aj']) {
if($contacts) {
$o = replace_macros(get_markup_template('contactsajax.tpl'),array(
'$contacts' => $contacts,
@@ -393,14 +402,13 @@ class Connections extends \Zotlabs\Web\Controller {
'$search' => $search_hdr,
'$label' => t('Search'),
'$role_label' => t('Contact role'),
'$desc' => t('Search your connections'),
'$desc' => $search ?? t('Search your connections'),
'$finding' => (($searching) ? t('Contact search') . ": '" . $search . "'" : ""),
'$submit' => t('Find'),
'$edit' => t('Edit'),
'$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

@@ -103,7 +103,7 @@ class Contactedit extends Controller {
dbesc($profile_id),
intval(local_channel())
);
if (!count($r)) {
if (!$r) {
notice(t('Could not locate selected profile.') . EOL);
return;
}
@@ -177,22 +177,8 @@ class Contactedit extends Controller {
intval($channel['channel_id'])
);
if (($pr) && (!intval($contact['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'], 'system', 'post_newfriend')))) {
$xarr = [];
$xarr['item_wall'] = 1;
$xarr['item_origin'] = 1;
$xarr['item_thread_top'] = 1;
$xarr['owner_xchan'] = $xarr['author_xchan'] = $channel['channel_hash'];
$xarr['allow_cid'] = $channel['channel_allow_cid'];
$xarr['allow_gid'] = $channel['channel_allow_gid'];
$xarr['deny_cid'] = $channel['channel_deny_cid'];
$xarr['deny_gid'] = $channel['channel_deny_gid'];
$xarr['item_private'] = (($xarr['allow_cid'] || $xarr['allow_gid'] || $xarr['deny_cid'] || $xarr['deny_gid']) ? 1 : 0);
$xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . $contact['xchan_url'] . ']' . $contact['xchan_name'] . '[/zrl]';
$xarr['body'] .= "\n\n\n" . '[zrl=' . $contact['xchan_url'] . '][zmg=80x80]' . $contact['xchan_photo_m'] . '[/zmg][/zrl]';
$xarr['body'] .= "\n\n\n" . '[zrl=' . $contact['xchan_url'] . '][zmg=' . $contact['xchan_photo_m'] . ']' . $contact['xchan_name'] . '[/zmg][/zrl]';
post_activity_item($xarr);
}
@@ -452,8 +438,8 @@ class Contactedit extends Controller {
if (is_ajax()) {
json_return_and_die([
'success' => ((intval($_REQUEST['success'])) ? intval($_REQUEST['success']) : 1),
'message' => (($_REQUEST['success']) ? t('Contact updated') : t('Contact update failed')),
'success' => ((isset($_REQUEST['success'])) ? intval($_REQUEST['success']) : 1),
'message' => ((isset($_REQUEST['success'])) ? t('Contact updated') : t('Contact update failed')),
'id' => $contact_id,
'title' => $header_html,
'role' => ((intval($contact['abook_pending'])) ? '' : $roles_dict[$current_permcat]),
@@ -494,28 +480,32 @@ class Contactedit extends Controller {
'message' => ''
];
if ($cmd === 'resetphoto') {
q("update xchan set xchan_photo_date = '2001-01-01 00:00:00' where xchan_hash = '%s'",
if ($cmd === 'refresh') {
q("update xchan set xchan_photo_date = '0001-01-01 00:00:00', xchan_name_date = '0001-01-01 00:00:00' where xchan_hash = '%s'",
dbesc($contact['xchan_hash'])
);
$cmd = 'refresh';
}
if ($cmd === 'refresh') {
if ($contact['xchan_network'] === 'zot6') {
if (Libzot::refresh($contact, App::get_channel())) {
$ret['success'] = true;
$ret['message'] = t('Refresh succeeded');
}
else {
$ret['message'] = t('Refresh failed - channel is currently unavailable');
$ret['message'] = t('Refresh failed');
}
}
else {
// if you are on a different network we'll force a refresh of the connection basic info
Master::Summon(['Notifier', 'permission_update', $contact['abook_id']]);
$ret['success'] = true;
$ret['message'] = t('Refresh succeeded');
$hookinfo = [
'contact' => $contact,
'success' => false,
'message' => ''
];
call_hooks('actor_refetch', $hookinfo);
$ret['success'] = $hookinfo['success'];
$ret['message'] = $hookinfo['message'];
}
return $ret;
@@ -625,16 +615,10 @@ class Contactedit extends Controller {
return [
'refresh' => [
'label' => t('Refresh Permissions'),
'title' => t('Fetch updated permissions'),
'label' => t('Refresh'),
'title' => t('Refetch contact info'),
],
'rephoto' => [
'label' => t('Refresh Photo'),
'title' => t('Fetch updated photo'),
],
'block' => [
'label' => (intval($contact['abook_blocked']) ? t('Unblock') : t('Block')),
'sel' => (intval($contact['abook_blocked']) ? 'active' : ''),

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 ('Follow', 'Ignore', '%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

@@ -3,7 +3,7 @@ namespace Zotlabs\Module;
use Zotlabs\Lib\Libsync;
/*
/*
@file cover_photo.php
@brief Module-file with functions for handling of cover-photos
@@ -29,43 +29,43 @@ class Cover_photo extends \Zotlabs\Web\Controller {
if(! local_channel()) {
return;
}
$channel = \App::get_channel();
profile_load($channel['channel_address']);
profile_load($channel['channel_address']);
}
/**
* @brief Evaluate posted values
*
* @return void
*
*/
function post() {
if(! local_channel()) {
return;
}
$channel = \App::get_channel();
check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
// Remove cover photo
if(isset($_POST['remove'])) {
$r = q("SELECT resource_id FROM photo WHERE photo_usage = %d AND uid = %d LIMIT 1",
intval(PHOTO_COVER),
intval(local_channel())
);
if($r) {
q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
intval(PHOTO_NORMAL),
intval(PHOTO_COVER),
intval(local_channel())
);
$sync = attach_export_data($channel,$r[0]['resource_id']);
if($sync)
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
@@ -76,47 +76,45 @@ class Cover_photo extends \Zotlabs\Web\Controller {
goaway(z_root() . '/cover_photo');
}
if((array_key_exists('cropfinal',$_POST)) && ($_POST['cropfinal'] == 1)) {
// phase 2 - we have finished cropping
if(argc() != 2) {
notice( t('Image uploaded but image cropping failed.') . EOL );
return;
}
$image_id = argv(1);
if(substr($image_id,-2,1) == '-') {
$scale = substr($image_id,-1,1);
$image_id = substr($image_id,0,-2);
}
$srcX = intval($_POST['xstart']);
$srcY = intval($_POST['ystart']);
$srcW = intval($_POST['xfinal']) - $srcX;
$srcH = intval($_POST['yfinal']) - $srcY;
$r = q("select gender from profile where uid = %d and is_default = 1 limit 1",
intval(local_channel())
);
if($r) {
$profile = $r[0];
}
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale = 0 LIMIT 1",
dbesc($image_id),
intval(local_channel())
);
if($r) {
$max_thumb = intval(get_config('system','max_thumbnail',1600));
$iscaled = false;
if(intval($r[0]['height']) > $max_thumb || intval($r[0]['width']) > $max_thumb) {
if(intval($r[0]['height']) > $max_thumb || intval($r[0]['width']) > $max_thumb) {
$imagick_path = get_config('system','imagick_convert_path');
if($imagick_path && @file_exists($imagick_path) && intval($r[0]['os_storage'])) {
@@ -150,63 +148,63 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$im = photo_factory($base_image['content'], $base_image['mimetype']);
if($im->is_valid()) {
// We are scaling and cropping the relative pixel locations to the original photo instead of the
// We are scaling and cropping the relative pixel locations to the original photo instead of the
// scaled photo we operated on.
// First load the scaled photo to check its size. (Should probably pass this in the post form and save
// a query.)
$g = q("select width, height from photo where resource_id = '%s' and uid = %d and imgscale = 3",
dbesc($image_id),
intval(local_channel())
);
$scaled_width = $g[0]['width'];
$scaled_height = $g[0]['height'];
if((! $scaled_width) || (! $scaled_height)) {
logger('potential divide by zero scaling cover photo');
return;
}
// unset all other cover photos
q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
intval(PHOTO_NORMAL),
intval(PHOTO_COVER),
intval(local_channel())
);
$orig_srcx = ( $base_image['width'] / $scaled_width ) * $srcX;
$orig_srcy = ( $base_image['height'] / $scaled_height ) * $srcY;
$orig_srcw = ( $srcW / $scaled_width ) * $base_image['width'];
$orig_srch = ( $srcH / $scaled_height ) * $base_image['height'];
$im->cropImageRect(1200,435,$orig_srcx, $orig_srcy, $orig_srcw, $orig_srch);
$aid = get_account_id();
$p = [
'aid' => $aid,
'uid' => local_channel(),
$p = [
'aid' => $aid,
'uid' => local_channel(),
'resource_id' => $base_image['resource_id'],
'filename' => $base_image['filename'],
'filename' => $base_image['filename'],
'album' => t('Cover Photos'),
'os_path' => $base_image['os_path'],
'display_path' => $base_image['display_path'],
'photo_usage' => PHOTO_COVER
];
$r1 = $im->storeThumbnail($p, PHOTO_RES_COVER_1200);
$im->doScaleImage(850,310);
$r2 = $im->storeThumbnail($p, PHOTO_RES_COVER_850);
$im->doScaleImage(425,160);
$r3 = $im->storeThumbnail($p, PHOTO_RES_COVER_425);
if($r1 === false || $r2 === false || $r3 === false) {
// if one failed, delete them all so we can start over.
notice( t('Image resize failed.') . EOL );
@@ -214,7 +212,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
dbesc($base_image['resource_id']),
local_channel()
);
$x = q("SELECT content FROM photo WHERE resource_id = '%s' AND uid = %d AND os_storage = 1 AND imgscale >= 7",
dbesc($base_image['resource_id']),
local_channel()
@@ -228,8 +226,8 @@ class Cover_photo extends \Zotlabs\Web\Controller {
return;
}
$this->send_cover_photo_activity($channel,$base_image,$profile);
profile_activity([t('Cover Photo')], $base_image['resource_id']);
$sync = attach_export_data($channel,$base_image['resource_id']);
if($sync)
Libsync::build_sync_packet($channel['channel_id'],array('file' => array($sync)));
@@ -240,33 +238,32 @@ class Cover_photo extends \Zotlabs\Web\Controller {
else
notice( t('Unable to process image') . EOL);
}
goaway(z_root() . '/channel/' . $channel['channel_address']);
}
$hash = photo_new_resource();
$smallest = 0;
require_once('include/attach.php');
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Cover Photos'), 'hash' => $hash, 'nosync' => true));
$res = attach_store(\App::get_channel(), get_observer_hash(), '', ['album' => t('Cover Photos'), 'hash' => $hash, 'nosync' => true, 'source' => 'photos']);
logger('attach_store: ' . print_r($res,true));
if($res && intval($res['data']['is_photo'])) {
$i = q("select * from photo where resource_id = '%s' and uid = %d and imgscale = 0",
dbesc($hash),
intval(local_channel())
);
if(! $i) {
notice( t('Image upload failed.') . EOL );
return;
}
$os_storage = false;
foreach($i as $ii) {
$smallest = intval($ii['imgscale']);
$os_storage = intval($ii['os_storage']);
@@ -274,91 +271,51 @@ class Cover_photo extends \Zotlabs\Web\Controller {
$filetype = $ii['mimetype'];
}
}
$imagedata = (($os_storage) ? @file_get_contents(dbunescbin($imagedata)) : dbunescbin($imagedata));
$ph = photo_factory($imagedata, $filetype);
if(! $ph->is_valid()) {
notice( t('Unable to process image.') . EOL );
return;
}
return $this->cover_photo_crop_ui_head($a, $ph, $hash, $smallest);
}
function send_cover_photo_activity($channel,$photo,$profile) {
$arr = array();
$arr['item_thread_top'] = 1;
$arr['item_origin'] = 1;
$arr['item_wall'] = 1;
if($profile && stripos($profile['gender'],t('female')) !== false)
$t = t('%1$s updated her %2$s');
elseif($profile && stripos($profile['gender'],t('male')) !== false)
$t = t('%1$s updated his %2$s');
else
$t = t('%1$s updated their %2$s');
$ptext = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']' . t('cover photo') . '[/zrl]';
$ltext = '[zrl=' . z_root() . '/profile/' . $channel['channel_address'] . ']' . '[zmg]' . z_root() . '/photo/' . $photo['resource_id'] . '-8[/zmg][/zrl]';
$arr['body'] = sprintf($t,$channel['channel_name'],$ptext) . "\n\n" . $ltext;
$acl = new \Zotlabs\Access\AccessList($channel);
$x = $acl->get();
$arr['allow_cid'] = $x['allow_cid'];
$arr['allow_gid'] = $x['allow_gid'];
$arr['deny_cid'] = $x['deny_cid'];
$arr['deny_gid'] = $x['deny_gid'];
$arr['uid'] = $channel['channel_id'];
$arr['aid'] = $channel['channel_account_id'];
$arr['owner_xchan'] = $channel['channel_hash'];
$arr['author_xchan'] = $channel['channel_hash'];
post_activity_item($arr);
}
/**
* @brief Generate content of profile-photo view
*
* @return string
*
*/
function get() {
if(! local_channel()) {
notice( t('Permission denied.') . EOL );
return;
}
$channel = \App::get_channel();
$newuser = false;
if(argc() == 2 && argv(1) === 'new')
$newuser = true;
if(argv(1) === 'use') {
if (argc() < 3) {
notice( t('Permission denied.') . EOL );
return;
};
// check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
$resource_id = argv(2);
$r = q("SELECT id, album, imgscale FROM photo WHERE uid = %d AND resource_id = '%s' ORDER BY imgscale ASC",
intval(local_channel()),
dbesc($resource_id)
@@ -372,22 +329,22 @@ class Cover_photo extends \Zotlabs\Web\Controller {
if($rr['imgscale'] == 7)
$havescale = true;
}
$r = q("SELECT content, mimetype, resource_id, os_storage FROM photo WHERE id = %d and uid = %d limit 1",
intval($r[0]['id']),
intval(local_channel())
);
if(! $r) {
notice( t('Photo not available.') . EOL );
return;
}
if(intval($r[0]['os_storage']))
$data = @file_get_contents(dbunescbin($r[0]['content']));
else
$data = dbunescbin($r[0]['content']);
$data = dbunescbin($r[0]['content']);
$ph = photo_factory($data, $r[0]['mimetype']);
$smallest = 0;
if($ph->is_valid()) {
@@ -396,7 +353,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
dbesc($r[0]['resource_id']),
intval(local_channel())
);
if($i) {
$hash = $i[0]['resource_id'];
foreach($i as $ii) {
@@ -404,15 +361,15 @@ class Cover_photo extends \Zotlabs\Web\Controller {
}
}
}
$this->cover_photo_crop_ui_head($a, $ph, $hash, $smallest);
}
if(! x(\App::$data,'imagecrop')) {
$tpl = get_markup_template('cover_photo.tpl');
$o .= replace_macros($tpl,array(
'$user' => \App::$channel['channel_address'],
'$info' => t('Your cover photo may be visible to anybody on the internet'),
@@ -422,7 +379,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
'$title' => t('Change Cover Photo'),
'$submit' => t('Upload'),
'$remove' => t('Remove'),
'$profiles' => $profiles,
'$profiles' => false,
'$embedPhotos' => t('Use a photo from your albums'),
'$embedPhotosModalTitle' => t('Use a photo from your albums'),
'$embedPhotosModalCancel' => t('Cancel'),
@@ -434,13 +391,13 @@ class Cover_photo extends \Zotlabs\Web\Controller {
'$modalerrorlink' => t('Error getting photo link'),
'$modalerroralbum' => t('Error getting album'),
'$form_security_token' => get_form_security_token("cover_photo"),
/// @FIXME - yuk
/// @FIXME - yuk
'$select' => t('Select existing photo'),
));
call_hooks('cover_photo_content_end', $o);
return $o;
}
else {
@@ -459,10 +416,8 @@ class Cover_photo extends \Zotlabs\Web\Controller {
));
return $o;
}
return; // NOTREACHED
}
/* @brief Generate the UI for photo-cropping
*
* @param $a Current application
@@ -470,30 +425,30 @@ class Cover_photo extends \Zotlabs\Web\Controller {
* @return void
*
*/
function cover_photo_crop_ui_head(&$a, $ph, $hash, $smallest){
$max_length = get_config('system','max_image_length');
if(! $max_length)
$max_length = MAX_IMAGE_LENGTH;
if($max_length > 0)
$ph->scaleImage($max_length);
$width = $ph->getWidth();
$height = $ph->getHeight();
if($width < 300 || $height < 300) {
$ph->scaleImageUp(240);
$width = $ph->getWidth();
$height = $ph->getHeight();
}
\App::$data['imagecrop'] = $hash;
\App::$data['imagecrop_resolution'] = $smallest;
\App::$page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), array());
return;
}
}

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